<?xml version="1.0" encoding="utf-8" standalone="yes"?><?xml-stylesheet href="/atom.xsl" type="text/xsl"?><feed xmlns="http://www.w3.org/2005/Atom" xmlns:webfeeds="http://webfeeds.org/rss/1.0"><author><name>Fundor333</name><uri>https://fundor333.com/</uri></author><generator uri="https://gohugo.io">Hugo 0.162.1</generator><id>urn:uuid:43c22089-5c06-4cc4-8fd2-5b3563d5d257</id><link rel="self" type="application/atom+xml" href="https://fundor333.com/post/atom.xml" hreflang="en"/><link rel="alternate" type="text/html" href="https://fundor333.com/post/" hreflang="en"/><link rel="alternate" type="application/rss+xml" href="https://fundor333.com/post/index.xml" hreflang="en"/><link rel="alternate" type="application/json" href="https://fundor333.com/post/index.json" hreflang="en"/><icon>https://fundor333.com/apple-touch-icon.png</icon><logo>https://fundor333.com/img/logo.png</logo><subtitle>Fundor 333's personal space on the web</subtitle><title>Fundor333</title><updated>2026-07-18T04:10:58+02:00</updated><webfeeds:icon>https://fundor333.com/favicon-96x96.png</webfeeds:icon><entry><id>tag:fundor333.com,2026:/post/2026/who-knows-that-i-blog-/</id><link rel="alternate" href="https://fundor333.com/post/2026/who-knows-that-i-blog-/"/><title>Who Knows That I Blog</title><published>2026-05-23T12:50:49+02:00</published><updated>2026-07-16T22:49:21+02:00</updated><summary type="text">A response to the question "Who knows that you blog?"</summary><content type="html" xml:base="https://fundor333.com/" xml:lang="en">
<![CDATA[<blockquote>
<p>Question for the audience: Do you tell people you blog?</p>
</blockquote>
<p>Yes&hellip; No&hellip; It depend.
It is not a thing I talk about my blog in my every day life. And I have more than one blog so&hellip;</p>
<h2 id="so-i-tell-people-about-my-blog" class="no-underline ">
  <a href="#so-i-tell-people-about-my-blog">
    <i class="fa-whiteboard fa-semibold fa-angle-right"></i>
    So I tell people about my blog?
  </a>
  </h2>
<p>Yes I tell but not unprompted. I told people while talking about the argument of my blog, like if I have a post about what we are talking or if the topic of the blog can be usefull for the discussion.</p>
<h2 id="am-i-anonymous-when-blogging" class="no-underline ">
  <a href="#am-i-anonymous-when-blogging">
    <i class="fa-whiteboard fa-semibold fa-angle-right"></i>
    Am I anonymous when blogging?
  </a>
  </h2>
<blockquote>
<p>I appreciate some people like to be anonymous when blogging. That&rsquo;s their choice. I am an open book. You can ask me anything and I will reply honestly, as long as it conforms to my town-square rule.</p>
</blockquote>
<p>In my case is not so black and white. This blog url and title is Fundor333. This is my online alias. If you find somewhere fundor333 you find one of my account. So I am well know as Fundor333. So I am &ldquo;anonymous&rdquo; when I blog (as I don&rsquo;t use my real name) but I don&rsquo;t hide my alias.</p>
<h2 id="conclusion" class="no-underline ">
  <a href="#conclusion">
    <i class="fa-whiteboard fa-semibold fa-angle-right"></i>
    Conclusion
  </a>
  </h2>
<p>So I tell people I blog but not at random and I don&rsquo;t hide my blog. But is not one of my opening line when talking with someone.</p>
]]></content></entry><entry><id>tag:fundor333.com,2026:/post/2026/hacking-my-kobo/</id><link rel="alternate" href="https://fundor333.com/post/2026/hacking-my-kobo/"/><title>Hacking My Kobo with KOReader</title><published>2026-04-13T12:10:12+02:00</published><updated>2026-07-16T22:49:21+02:00</updated><summary type="text">A little diary about my expirience</summary><content type="html" xml:base="https://fundor333.com/" xml:lang="en">
<![CDATA[<p>A long long time ago I start using a EBook Reader, the first Kindle PaperWhite (2012) and I never stop using EReader.</p>
<p>The last one I own is a Kobo Clara Colour, this one.</p>
<p><img  class="center-img u-photo "  src="kobo.jpg" alt="Kobo Clara Colour"></p>
<p>I love it and the fact I can read in color comics, manga, web comics and graphic novel everywhere is a plus.</p>
<p>But more and more I use Ebook Readers more and more I want to customize it. Like I have in the pic.</p>
<h2 id="what-can-i-do-what-do-i-want-to-do-with-my-kobo" class="no-underline ">
  <a href="#what-can-i-do-what-do-i-want-to-do-with-my-kobo">
    <i class="fa-whiteboard fa-semibold fa-angle-right"></i>
    What can I do? What do I want to do with my Kobo?
  </a>
  </h2>
<p>I have some task and prerequisite for my Ebook Reader so I check an Hack which resolve all:</p>
<ul>
<li><em>I need to sync with Calibre</em>: I have an huge Calibre Library and I want to keep it</li>
<li><em>Change the default cover</em>: I want my cover, not the default covers</li>
<li><em>Integration with GoodRead or Hardcover</em>: I want to sync with GoodRead or Hardover the data from my ebook reader.</li>
<li><em>Open Source software</em>: I want to use an Open Source project because I can code so if i need something I can code it.</li>
</ul>
<p>So I did some research on the web and find KoReader<sup id="fnref:1"><a href="#fn:1" class="footnote-ref" role="doc-noteref">1</a></sup>.</p>
<p>It is a software which, after installing on the ereader, it add support for plugins and custom covers&hellip; So I start with it.</p>
<h2 id="how-to-install-it" class="no-underline ">
  <a href="#how-to-install-it">
    <i class="fa-whiteboard fa-semibold fa-angle-right"></i>
    How to install it?
  </a>
  </h2>
<p>Searching for the wiki page for starting/installing I found some tread about the installation<sup id="fnref:2"><a href="#fn:2" class="footnote-ref" role="doc-noteref">2</a></sup> and I follow them. Here I rewrite all the steps with newer link for the stuff needed and rewrote some step because the two treads aren&rsquo;t clear enough for me.</p>
<ol start="0">
<li>Check if your device support the software</li>
<li>Download the last version of what you want to install. In this case <a class="a-post interlink-script" href="https://github.com/koreader/koreader/releases"   target="_blank">Last version of KoReader&nbsp;&nbsp;<i class="fa-whiteboard fa-semibold fa-link"></i></a>
 is what I want and support on my device</li>
<li>Put all the zip/archive you download in a new directory without unarchive anything</li>
<li>Download the installer script (<a class="a-post interlink-script" href="https://raw.githubusercontent.com/NiLuJe/kfmon/refs/heads/master/tools/install.ps1"   target="_blank">Windows version&nbsp;&nbsp;<i class="fa-whiteboard fa-semibold fa-link"></i></a>
, <a class="a-post interlink-script" href="https://raw.githubusercontent.com/NiLuJe/kfmon/refs/heads/master/tools/install.sh"   target="_blank">Mac version&nbsp;&nbsp;<i class="fa-whiteboard fa-semibold fa-link"></i></a>
, <a class="a-post interlink-script" href="https://raw.githubusercontent.com/NiLuJe/kfmon/refs/heads/master/tools/install.sh"   target="_blank">Linux version&nbsp;&nbsp;<i class="fa-whiteboard fa-semibold fa-link"></i></a>
) and put in the same directory as all the other stuff downloaded in 2</li>
<li>Plug in the Kobo and check if you can read and write file inside it</li>
<li>If needed fix the permission for execute the installer download at step 3</li>
<li>Follow the on-screen instruction and close the terminal when done</li>
<li>Safely eject your Kobo, watch it process (it look like in some way a glitching and crashing device but it need to look like that) and waite for the end of the reboot.</li>
</ol>
<p>If you have doubt, here is a screenshot of what the terminal look like in step 6 if you did all in the right way.</p>
<p><img  class="center-img u-photo "  src="terminal.png" alt="teminal code"></p>
<p>After the reboot of the device I start to add the plugins for some customization</p>
<h2 id="adding-stuff" class="no-underline ">
  <a href="#adding-stuff">
    <i class="fa-whiteboard fa-semibold fa-angle-right"></i>
    Adding stuff
  </a>
  </h2>
<p>I add some KoReader Plugin, which you need to install.</p>
<p>All the plugin are installed in the same way:</p>
<ol>
<li>You need to download the plugin</li>
<li>You need to extract the <em>plugin_name</em>.koplugin</li>
<li>Edit any config file for the plugin (only some plugin required this)</li>
<li>Put the koplugin folder in the path for the device (in Kobo case is <strong>.adds/koreader/plugins</strong>)</li>
<li>Restart KOReader</li>
</ol>
<ul>
<li><a class="a-post interlink-script" href="https://github.com/joshuacant/ProjectTitle"   target="_blank">ProjectTitle KOReader&nbsp;&nbsp;<i class="fa-whiteboard fa-semibold fa-link"></i></a>
 for a better looking homepage for KOReader (needed)</li>
<li><a class="a-post interlink-script" href="https://github.com/pxlflux/customisablesleepscreen.koplugin"   target="_blank">Customisable Sleep Screen&nbsp;&nbsp;<i class="fa-whiteboard fa-semibold fa-link"></i></a>
 for having a customisable sleep screen (as the name of the plugin say)</li>
<li><a class="a-post interlink-script" href="https://github.com/Billiam/hardcoverapp.koplugin"   target="_blank">Hardcover.app for KOReader&nbsp;&nbsp;<i class="fa-whiteboard fa-semibold fa-link"></i></a>
 for sync the data with my <a class="a-post interlink-script" href="https://hardcover.app/"   target="_blank">HardCover&nbsp;&nbsp;<i class="fa-whiteboard fa-semibold fa-link"></i></a>
 account</li>
</ul>
<p><img  class="center-img u-photo "  src="kobo-complete.jpg" alt="Kobo Clara Colour"></p>
<p>I also create some image with trasparent background for having this type of cover, where you can see under the sleep-screen what are you reading.</p>
<h2 id="and-i-did-more" class="no-underline ">
  <a href="#and-i-did-more">
    <i class="fa-whiteboard fa-semibold fa-angle-right"></i>
    And I did more
  </a>
  </h2>
<p>I did a lot of configuration inside of KOReader for this or that component and I don&rsquo;t want to lose all. So, after asking Reddit <a class="a-post interlink-script" href="https://www.reddit.com/r/koreader/comments/1sgk3zc/comment/of5k8qe/"   target="_blank">How can I make a backup?&nbsp;&nbsp;<i class="fa-whiteboard fa-semibold fa-link"></i></a>
 and make this script.</p>

<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-python" data-lang="python"><span style="display:flex;"><span><span style="color:#75715e">#!/usr/bin/env python3</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">import</span> os
</span></span><span style="display:flex;"><span><span style="color:#f92672">import</span> sys
</span></span><span style="display:flex;"><span><span style="color:#f92672">import</span> shutil
</span></span><span style="display:flex;"><span><span style="color:#f92672">from</span> datetime <span style="color:#f92672">import</span> datetime
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>KOREADER_DIR <span style="color:#f92672">=</span> <span style="color:#e6db74">&#34;.adds&#34;</span>
</span></span><span style="display:flex;"><span>BACKUP_DESTINATION <span style="color:#f92672">=</span> <span style="color:#e6db74">&#34;~/BackUp/KoReader&#34;</span>
</span></span><span style="display:flex;"><span>BACKUP_FILENAME <span style="color:#f92672">=</span> <span style="color:#e6db74">&#34;koreader_backup_</span><span style="color:#e6db74">{date}</span><span style="color:#e6db74">.zip&#34;</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">def</span> <span style="color:#a6e22e">find_kobo_device</span>():
</span></span><span style="display:flex;"><span>    <span style="color:#e6db74">&#34;&#34;&#34;Find the path to the Kobo&#34;&#34;&#34;</span>
</span></span><span style="display:flex;"><span>    volumes_path <span style="color:#f92672">=</span> <span style="color:#e6db74">&#34;/Volumes&#34;</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">if</span> os<span style="color:#f92672">.</span>path<span style="color:#f92672">.</span>exists(volumes_path):
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">for</span> entry <span style="color:#f92672">in</span> os<span style="color:#f92672">.</span>listdir(volumes_path):
</span></span><span style="display:flex;"><span>            full_path <span style="color:#f92672">=</span> os<span style="color:#f92672">.</span>path<span style="color:#f92672">.</span>join(volumes_path, entry)
</span></span><span style="display:flex;"><span>            <span style="color:#66d9ef">if</span> os<span style="color:#f92672">.</span>path<span style="color:#f92672">.</span>isdir(full_path):
</span></span><span style="display:flex;"><span>                <span style="color:#66d9ef">try</span>:
</span></span><span style="display:flex;"><span>                    contents <span style="color:#f92672">=</span> os<span style="color:#f92672">.</span>listdir(full_path)
</span></span><span style="display:flex;"><span>                    <span style="color:#66d9ef">if</span> <span style="color:#e6db74">&#34;.kobo&#34;</span> <span style="color:#f92672">in</span> contents:
</span></span><span style="display:flex;"><span>                        <span style="color:#66d9ef">return</span> full_path
</span></span><span style="display:flex;"><span>                <span style="color:#66d9ef">except</span> <span style="color:#a6e22e">PermissionError</span>:
</span></span><span style="display:flex;"><span>                    <span style="color:#66d9ef">continue</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">return</span> <span style="color:#66d9ef">None</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">def</span> <span style="color:#a6e22e">get_koreader_path</span>(kobo_path):
</span></span><span style="display:flex;"><span>    <span style="color:#e6db74">&#34;&#34;&#34;Returns the path to KoReader on the Kobo.&#34;&#34;&#34;</span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">return</span> os<span style="color:#f92672">.</span>path<span style="color:#f92672">.</span>join(kobo_path, KOREADER_DIR)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">def</span> <span style="color:#a6e22e">create_backup</span>(source_path, backup_destination):
</span></span><span style="display:flex;"><span>    <span style="color:#e6db74">&#34;&#34;&#34;Creates a zip backup of KoReader.&#34;&#34;&#34;</span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">if</span> <span style="color:#f92672">not</span> os<span style="color:#f92672">.</span>path<span style="color:#f92672">.</span>exists(source_path):
</span></span><span style="display:flex;"><span>        print(<span style="color:#e6db74">f</span><span style="color:#e6db74">&#34;Error: KoReader not found in </span><span style="color:#e6db74">{</span>source_path<span style="color:#e6db74">}</span><span style="color:#e6db74">&#34;</span>)
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">return</span> <span style="color:#66d9ef">False</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    print(<span style="color:#e6db74">f</span><span style="color:#e6db74">&#34;Creating backup from: </span><span style="color:#e6db74">{</span>source_path<span style="color:#e6db74">}</span><span style="color:#e6db74">&#34;</span>)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    date_str <span style="color:#f92672">=</span> datetime<span style="color:#f92672">.</span>now()<span style="color:#f92672">.</span>strftime(<span style="color:#e6db74">&#34;%Y%m</span><span style="color:#e6db74">%d</span><span style="color:#e6db74">_%H%M%S&#34;</span>)
</span></span><span style="display:flex;"><span>    backup_filename <span style="color:#f92672">=</span> BACKUP_FILENAME<span style="color:#f92672">.</span>format(date<span style="color:#f92672">=</span>date_str)
</span></span><span style="display:flex;"><span>    backup_path <span style="color:#f92672">=</span> os<span style="color:#f92672">.</span>path<span style="color:#f92672">.</span>join(backup_destination, backup_filename)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    print(<span style="color:#e6db74">f</span><span style="color:#e6db74">&#34;Backup to: </span><span style="color:#e6db74">{</span>backup_path<span style="color:#e6db74">}</span><span style="color:#e6db74">&#34;</span>)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">try</span>:
</span></span><span style="display:flex;"><span>        shutil<span style="color:#f92672">.</span>make_archive(
</span></span><span style="display:flex;"><span>            backup_path<span style="color:#f92672">.</span>replace(<span style="color:#e6db74">&#34;.zip&#34;</span>, <span style="color:#e6db74">&#34;&#34;</span>), <span style="color:#e6db74">&#34;zip&#34;</span>, root_dir<span style="color:#f92672">=</span>source_path, base_dir<span style="color:#f92672">=</span><span style="color:#e6db74">&#34;.&#34;</span>
</span></span><span style="display:flex;"><span>        )
</span></span><span style="display:flex;"><span>        print(<span style="color:#e6db74">f</span><span style="color:#e6db74">&#34;Backup created: </span><span style="color:#e6db74">{</span>backup_path<span style="color:#e6db74">}</span><span style="color:#e6db74">&#34;</span>)
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">return</span> <span style="color:#66d9ef">True</span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">except</span> <span style="color:#a6e22e">Exception</span> <span style="color:#66d9ef">as</span> e:
</span></span><span style="display:flex;"><span>        print(<span style="color:#e6db74">f</span><span style="color:#e6db74">&#34;Error during backup creation: </span><span style="color:#e6db74">{</span>e<span style="color:#e6db74">}</span><span style="color:#e6db74">&#34;</span>)
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">return</span> <span style="color:#66d9ef">False</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">def</span> <span style="color:#a6e22e">main</span>():
</span></span><span style="display:flex;"><span>    kobo_path <span style="color:#f92672">=</span> find_kobo_device()
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">if</span> <span style="color:#f92672">not</span> kobo_path:
</span></span><span style="display:flex;"><span>        print(<span style="color:#e6db74">&#34;Kobo not found. Connect the device and try again.&#34;</span>)
</span></span><span style="display:flex;"><span>        sys<span style="color:#f92672">.</span>exit(<span style="color:#ae81ff">1</span>)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    print(<span style="color:#e6db74">f</span><span style="color:#e6db74">&#34;Kobo found at: </span><span style="color:#e6db74">{</span>kobo_path<span style="color:#e6db74">}</span><span style="color:#e6db74">&#34;</span>)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    koreader_path <span style="color:#f92672">=</span> get_koreader_path(kobo_path)
</span></span><span style="display:flex;"><span>    backup_destination <span style="color:#f92672">=</span> os<span style="color:#f92672">.</span>path<span style="color:#f92672">.</span>expanduser(BACKUP_DESTINATION)
</span></span><span style="display:flex;"><span>    os<span style="color:#f92672">.</span>makedirs(backup_destination, exist_ok<span style="color:#f92672">=</span><span style="color:#66d9ef">True</span>)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    success <span style="color:#f92672">=</span> create_backup(koreader_path, backup_destination)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">if</span> success:
</span></span><span style="display:flex;"><span>        print(<span style="color:#e6db74">&#34;Backup completed successfully!&#34;</span>)
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">else</span>:
</span></span><span style="display:flex;"><span>        print(<span style="color:#e6db74">&#34;Backup failed.&#34;</span>)
</span></span><span style="display:flex;"><span>        sys<span style="color:#f92672">.</span>exit(<span style="color:#ae81ff">1</span>)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">if</span> __name__ <span style="color:#f92672">==</span> <span style="color:#e6db74">&#34;__main__&#34;</span>:
</span></span><span style="display:flex;"><span>    main()</span></span></code></pre></div><p>This Python script is run every time I connect to my computer with the Kobo and copy the <strong>.adds</strong> in a specific path with a new folder tagged with the timestamp.</p>
<p>So if I break my KOReader config, I can reset all and copy the <strong>.adds</strong> for restore the KOReader.</p>
<h2 id="conclusion" class="no-underline ">
  <a href="#conclusion">
    <i class="fa-whiteboard fa-semibold fa-angle-right"></i>
    Conclusion
  </a>
  </h2>
<p>For now this is what I did with my Kobo but I am thinking new stuff so if I will do something new I will write about it.</p>
<div class="footnotes" role="doc-endnotes">
<hr>
<ol>
<li id="fn:1">
<p><a class="a-post interlink-script" href="https://github.com/koreader/koreader"   target="_blank">KoReader&nbsp;&nbsp;<i class="fa-whiteboard fa-semibold fa-link"></i></a>
 Github official page&#160;<a href="#fnref:1" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
<li id="fn:2">
<p><a class="a-post interlink-script" href="https://www.mobileread.com/forums/showpost.php?p=3797095&amp;postcount=1"   target="_blank">Install Tread part1&nbsp;&nbsp;<i class="fa-whiteboard fa-semibold fa-link"></i></a>
 and <a class="a-post interlink-script" href="https://www.mobileread.com/forums/showpost.php?p=3797096&amp;postcount=2"   target="_blank">Install Tread part2&nbsp;&nbsp;<i class="fa-whiteboard fa-semibold fa-link"></i></a>
&#160;<a href="#fnref:2" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
</ol>
</div>
]]></content></entry><entry><id>tag:fundor333.com,2026:/post/2026/django-table-filter-export-with-htmx/</id><link rel="alternate" href="https://fundor333.com/post/2026/django-table-filter-export-with-htmx/"/><title>Django Table, Filter and Export With Htmx</title><published>2026-04-03T08:21:34+02:00</published><updated>2026-07-16T22:49:21+02:00</updated><summary type="text">A little code fragment for show how to use in the same project Htmx, Django-table2 e Django-filters</summary><content type="html" xml:base="https://fundor333.com/" xml:lang="en">
<![CDATA[<p>Some time ago I wrote a <a class="a-post interlink-script" href="/post/2026/htmx-django-and-django-table2/"  >blog post</a>
 about Htmx and Django-table2 and all went well&hellip;</p>
<p><img  class="center-img u-photo "  src="soso.gif" alt="So So"></p>
<p>No he didn&rsquo;t work as I wanted so I did some editing of the code here and there.</p>
<h2 id="the-old-one" class="no-underline ">
  <a href="#the-old-one">
    <i class="fa-whiteboard fa-semibold fa-angle-right"></i>
    The old one
  </a>
  </h2>
<p>We start with the code I didn&rsquo;t change:</p>
<p>First the model</p>

<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-python" data-lang="python"><span style="display:flex;"><span><span style="color:#75715e"># blog/model.py</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">class</span> <span style="color:#a6e22e">Post</span>(models<span style="color:#f92672">.</span>Model):
</span></span><span style="display:flex;"><span>    title <span style="color:#f92672">=</span> models<span style="color:#f92672">.</span>CharField(max_length<span style="color:#f92672">=</span><span style="color:#ae81ff">400</span>)
</span></span><span style="display:flex;"><span>    slug <span style="color:#f92672">=</span> models<span style="color:#f92672">.</span>SlugField(max_length<span style="color:#f92672">=</span><span style="color:#ae81ff">400</span>, unique<span style="color:#f92672">=</span><span style="color:#66d9ef">True</span>, blank<span style="color:#f92672">=</span><span style="color:#66d9ef">True</span>)
</span></span><span style="display:flex;"><span>    content <span style="color:#f92672">=</span> models<span style="color:#f92672">.</span>TextAreaField()
</span></span><span style="display:flex;"><span>    date <span style="color:#f92672">=</span> models<span style="color:#f92672">.</span>DateTimeField(auto_now_add<span style="color:#f92672">=</span><span style="color:#66d9ef">True</span>)</span></span></code></pre></div><p>The table</p>

<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-python" data-lang="python"><span style="display:flex;"><span><span style="color:#75715e"># blog/tables.py</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">import</span> django_tables2 <span style="color:#66d9ef">as</span> tables
</span></span><span style="display:flex;"><span><span style="color:#f92672">from</span> blog.models <span style="color:#f92672">import</span> Post
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">class</span> <span style="color:#a6e22e">PostTable</span>(tables<span style="color:#f92672">.</span>Table):
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">class</span> <span style="color:#a6e22e">Meta</span>:
</span></span><span style="display:flex;"><span>        model <span style="color:#f92672">=</span> Post
</span></span><span style="display:flex;"><span>        order_by <span style="color:#f92672">=</span> (<span style="color:#e6db74">&#34;-date&#34;</span>, <span style="color:#e6db74">&#34;title&#34;</span>)
</span></span><span style="display:flex;"><span>        fields <span style="color:#f92672">=</span> [<span style="color:#e6db74">&#34;date&#34;</span>, <span style="color:#e6db74">&#34;title&#34;</span>, <span style="color:#e6db74">&#34;slug&#34;</span>]</span></span></code></pre></div><p>This two fragment are perfect as is so I didn&rsquo;t touch them. But all the other part I reworked as I needed.</p>
<h2 id="the-new-parts" class="no-underline ">
  <a href="#the-new-parts">
    <i class="fa-whiteboard fa-semibold fa-angle-right"></i>
    The new parts
  </a>
  </h2>
<p>I need to have a &ldquo;universal table&rdquo; for show data, with filter and export the data.
And I need to have an &ldquo;universal template&rdquo; for all the combination Table-Export-Filter&hellip;</p>
<p>So I wrote one</p>
<p><img  class="center-img u-photo "  src="typing.gif" alt="Typing"></p>
<p>First thing (after the model and the table) I need view with filter and exporter support. And using <em>django-table2</em><sup id="fnref:1"><a href="#fn:1" class="footnote-ref" role="doc-noteref">1</a></sup> all was easy.<sup id="fnref:2"><a href="#fn:2" class="footnote-ref" role="doc-noteref">2</a></sup></p>
<p>So I wrote this class which support all I need for using it as Htmx endpoint.</p>

<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-python" data-lang="python"><span style="display:flex;"><span><span style="color:#75715e"># blog/views.py</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">from</span> django_tables2 <span style="color:#f92672">import</span> SingleTableMixin
</span></span><span style="display:flex;"><span><span style="color:#f92672">from</span> django_tables2.export <span style="color:#f92672">import</span> ExportMixin, TableExport
</span></span><span style="display:flex;"><span><span style="color:#f92672">from</span> django_filters.views <span style="color:#f92672">import</span> FilterView
</span></span><span style="display:flex;"><span><span style="color:#f92672">from</span> blog.model <span style="color:#f92672">import</span> Post
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">class</span> <span style="color:#a6e22e">DataHtmx</span>(ExportMixin, SingleTableMixin, FilterView):
</span></span><span style="display:flex;"><span>    model <span style="color:#f92672">=</span> Post
</span></span><span style="display:flex;"><span>    template_name <span style="color:#f92672">=</span> <span style="color:#e6db74">&#34;generic/table2.html&#34;</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    table_class <span style="color:#f92672">=</span> PostTable
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    filterset_fields <span style="color:#f92672">=</span> [<span style="color:#e6db74">&#34;title&#34;</span>,<span style="color:#e6db74">&#34;slug&#34;</span>, <span style="color:#e6db74">&#34;date&#34;</span>]
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    export_formats <span style="color:#f92672">=</span> (
</span></span><span style="display:flex;"><span>        TableExport<span style="color:#f92672">.</span>CSV,
</span></span><span style="display:flex;"><span>        TableExport<span style="color:#f92672">.</span>XLS,
</span></span><span style="display:flex;"><span>        TableExport<span style="color:#f92672">.</span>XLSX,
</span></span><span style="display:flex;"><span>        TableExport<span style="color:#f92672">.</span>ODS,
</span></span><span style="display:flex;"><span>    )
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">def</span> <span style="color:#a6e22e">get_export_filename</span>(self, export_format):
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">return</span> <span style="color:#e6db74">f</span><span style="color:#e6db74">&#34;Export Data.</span><span style="color:#e6db74">{</span>export_format<span style="color:#e6db74">}</span><span style="color:#e6db74">&#34;</span></span></span></code></pre></div><ul>
<li><em>ExportMixin</em>, with the <em>export_formats</em> are the the export part of the view</li>
<li><em>SingleTableMixin</em> is the table part of the view</li>
<li><em>FilterView</em> is the filter part of the view, with <em>filterset_fields</em> as the field you can filter. You can also haave a filterset_class if you need</li>
</ul>
<p>Done this I need a template. More generic template because I don&rsquo;t want to rewrite the same code every time&hellip;</p>
<p>So here is it!</p>

<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-django" data-lang="django"><span style="display:flex;"><span># templates/generic/table.html
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">{%</span> <span style="color:#66d9ef">load</span> render_table from django_tables2 <span style="color:#75715e">%}</span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">{%</span> <span style="color:#66d9ef">load</span> export_url from django_tables2 <span style="color:#75715e">%}</span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">{%</span> <span style="color:#66d9ef">load</span> django_bootstrap5 <span style="color:#75715e">%}</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">{%</span> <span style="color:#66d9ef">if</span> filter  <span style="color:#75715e">%}</span>
</span></span><span style="display:flex;"><span>  <span style="color:#75715e">{%</span> <span style="color:#66d9ef">if</span> <span style="color:#e6db74">&#39;hide_filter&#39;</span> <span style="color:#66d9ef">not</span> <span style="color:#66d9ef">in</span> request.GET <span style="color:#75715e">%}</span>
</span></span><span style="display:flex;"><span>      &lt;div class=&#34;col-12 col-md-9&#34;&gt;
</span></span><span style="display:flex;"><span>        &lt;div class=&#34;card mb-4&#34;&gt;
</span></span><span style="display:flex;"><span>          &lt;div class=&#34;card-header&#34;&gt;
</span></span><span style="display:flex;"><span>            &lt;button class=&#34;btn btn-section&#34; type=&#34;button&#34; data-bs-toggle=&#34;collapse&#34; data-bs-target=&#34;#filterCollapse&#34;&gt;
</span></span><span style="display:flex;"><span>              &lt;i class=&#34;fa-solid fa-filter&#34;&gt;&lt;/i&gt; Filtri &lt;i class=&#34;fa-solid fa-chevron-down&#34;&gt;&lt;/i&gt;
</span></span><span style="display:flex;"><span>            &lt;/button&gt;
</span></span><span style="display:flex;"><span>          &lt;/div&gt;
</span></span><span style="display:flex;"><span>          &lt;div id=&#34;filterCollapse&#34; class=&#34;collapse&#34;&gt;
</span></span><span style="display:flex;"><span>            &lt;div class=&#34;card-body&#34;&gt;
</span></span><span style="display:flex;"><span>              &lt;form method=&#34;get&#34; class=&#34;row&#34;&gt;
</span></span><span style="display:flex;"><span>                <span style="color:#75715e">{%</span> <span style="color:#66d9ef">load</span> django_bootstrap5 <span style="color:#75715e">%}</span>
</span></span><span style="display:flex;"><span>                <span style="color:#75715e">{%</span> <span style="color:#66d9ef">bootstrap_form</span> filter.form layout<span style="color:#f92672">=</span><span style="color:#e6db74">&#39;floating&#39;</span> <span style="color:#75715e">%}</span>
</span></span><span style="display:flex;"><span>                  <span style="color:#75715e">{%</span> <span style="color:#66d9ef">include</span> <span style="color:#e6db74">&#39;generic/_btn_search.html&#39;</span> <span style="color:#75715e">%}</span>
</span></span><span style="display:flex;"><span>              &lt;/form&gt;
</span></span><span style="display:flex;"><span>            &lt;/div&gt;
</span></span><span style="display:flex;"><span>          &lt;/div&gt;
</span></span><span style="display:flex;"><span>        &lt;/div&gt;
</span></span><span style="display:flex;"><span>      &lt;/div&gt;
</span></span><span style="display:flex;"><span><span style="color:#75715e">{%</span> <span style="color:#66d9ef">endif</span> <span style="color:#75715e">%}</span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">{%</span> <span style="color:#66d9ef">endif</span> <span style="color:#75715e">%}</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>&lt;div class=&#34;row&#34;&gt;
</span></span><span style="display:flex;"><span>    <span style="color:#75715e">{%</span> <span style="color:#66d9ef">if</span> <span style="color:#e6db74">&#39;hide_export&#39;</span> <span style="color:#66d9ef">not</span> <span style="color:#66d9ef">in</span> request.GET <span style="color:#75715e">%}</span>
</span></span><span style="display:flex;"><span>      <span style="color:#75715e">{%</span> <span style="color:#66d9ef">for</span> format <span style="color:#66d9ef">in</span> view.export_formats <span style="color:#75715e">%}</span>
</span></span><span style="display:flex;"><span>      &lt;a  class=&#34;btn col col-sm&#34; href=&#34;<span style="color:#75715e">{{</span> request.path <span style="color:#75715e">}}{%</span> <span style="color:#66d9ef">export_url</span> format <span style="color:#75715e">%}</span>&#34; target=&#34;_blank&#34;&gt;
</span></span><span style="display:flex;"><span>        &lt;i class=&#34;fa-duotone fa-regular fa-download&#34;&gt;&lt;/i&gt; &lt;code&gt;<span style="color:#75715e">{{</span> format <span style="color:#75715e">}}</span>&lt;/code&gt;
</span></span><span style="display:flex;"><span>      &lt;/a&gt;
</span></span><span style="display:flex;"><span>      <span style="color:#75715e">{%</span> <span style="color:#66d9ef">endfor</span> <span style="color:#75715e">%}</span>
</span></span><span style="display:flex;"><span>    <span style="color:#75715e">{%</span> <span style="color:#66d9ef">endif</span> <span style="color:#75715e">%}</span>
</span></span><span style="display:flex;"><span>    &lt;hr&gt;
</span></span><span style="display:flex;"><span>    <span style="color:#75715e">{%</span> <span style="color:#66d9ef">render_table</span> table <span style="color:#75715e">%}</span>
</span></span><span style="display:flex;"><span>&lt;/div&gt;</span></span></code></pre></div><p>This template work if you have filters, export or not.</p>
<ul>
<li>the load are for django-table2 and boostrap (the last is for me, is not needed for the code)</li>
<li><em>&lsquo;hide_filter&rsquo; not in request.GET</em> check if the url has the params for <em>hide_filter</em>. If it is present, the template hides the filters</li>
<li><em>&lsquo;hide_export&rsquo; not in request.GET</em> check if the url has the params for <em>hide_export</em>. If it is present, the template hides the exports</li>
</ul>
<p>One example for the Htmx code is the following.</p>

<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-django" data-lang="django"><span style="display:flex;"><span>&lt;div hx-get=&#34;<span style="color:#75715e">{%</span> <span style="color:#66d9ef">url</span> <span style="color:#e6db74">&#39;blog:post_htmx&#39;</span> <span style="color:#75715e">%}</span>?date_at=<span style="color:#75715e">{{</span> query_date <span style="color:#f92672">|</span> <span style="color:#a6e22e">date</span><span style="color:#e6db74">:&#34;Y-m-d&#34;</span>  <span style="color:#75715e">}}</span>&amp;hide_filter&#34; hx-trigger=&#34;load&#34;&gt;</span></span></code></pre></div><p>In this example I had the filter set (with data form the template) and with <em>hide_filter</em> which hide the filters but not the exports button.</p>
<p>I thing this will be a stable of my django code and it can be move in a custom module for share and easy import.</p>
<div class="footnotes" role="doc-endnotes">
<hr>
<ol>
<li id="fn:1">
<p><a class="a-post interlink-script" href="https://django-tables2.readthedocs.io/en/latest/"   target="_blank">Django-table2&nbsp;&nbsp;<i class="fa-whiteboard fa-semibold fa-link"></i></a>
&#160;<a href="#fnref:1" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
<li id="fn:2">
<p>I also use <a class="a-post interlink-script" href="https://tablib.readthedocs.io/en/stable/"   target="_blank">tablib&nbsp;&nbsp;<i class="fa-whiteboard fa-semibold fa-link"></i></a>
 for the export and <a class="a-post interlink-script" href="https://django-filter.readthedocs.io/en/stable/"   target="_blank">django-filter&nbsp;&nbsp;<i class="fa-whiteboard fa-semibold fa-link"></i></a>
 for the filtering.&#160;<a href="#fnref:2" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
</ol>
</div>
]]></content></entry><entry><id>tag:fundor333.com,2026:/post/2026/starting-my-home-automation-experiment/</id><link rel="alternate" href="https://fundor333.com/post/2026/starting-my-home-automation-experiment/"/><title>Starting My Home Automation Experiment</title><published>2026-03-31T08:46:01+02:00</published><updated>2026-07-16T22:49:21+02:00</updated><summary type="text">I am starting a Home Automation in my home and this is how I start it</summary><content type="html" xml:base="https://fundor333.com/" xml:lang="en">
<![CDATA[<p>And some time ago I installed the Fiber<sup id="fnref:1"><a href="#fn:1" class="footnote-ref" role="doc-noteref">1</a></sup> in my home and I want to use in the best way, so I start to rework all my local network and I think about adding some home automation.</p>





<div class="xkcd-container">
  <h4 class="xkcd-title">Xkcd - Virtual Assistant</h4>
  <a href="https://xkcd.com/1931/" target="_blank" rel="noopener">
    <img src="https://imgs.xkcd.com/comics/virtual_assistant.png" alt="If you ask it to please turn off that feature, it apologizes a whole bunch and promises to try to be quieter, then switches to a slightly lower-volume version of the clip with &#34;sorry!&#34; after the louder sounds." title="If you ask it to please turn off that feature, it apologizes a whole bunch and promises to try to be quieter, then switches to a slightly lower-volume version of the clip with &#34;sorry!&#34; after the louder sounds." class="xkcd-image u-photo">
  </a>
  <p class="xkcd-subtitle">
    <em>If you ask it to please turn off that feature, it apologizes a whole bunch and promises to try to be quieter, then switches to a slightly lower-volume version of the clip with &#34;sorry!&#34; after the louder sounds.</em>
  </p>
</div>


<h2 id="what-do-i-need" class="no-underline ">
  <a href="#what-do-i-need">
    <i class="fa-whiteboard fa-semibold fa-angle-right"></i>
    What do I need?
  </a>
  </h2>
<p>First I search for understand what I need to have for build my personal home automation. So serching on the web I found I need:</p>
<ul>
<li>A brain/core/server for coordinate all the stuffs</li>
<li>A software for the brain, for the automation  and other stuff</li>
<li>A router for adding the brain to the network for update and other stuff</li>
<li>Dongle/sensor/tech for connectivity with the sensors and smart stuff (one for protocol)</li>
<li>The smart stuff (light bulb, sensor, timer, endpoint api&hellip;)</li>
</ul>
<p>So I need to choose which protocol I want in my home&hellip; And I don&rsquo;t know&hellip;</p>
<p>So I change the point of view:</p>
<ul>
<li>I want to use good smart stuff but I don&rsquo;t want to pay too much</li>
<li>I want something Open Source so I am not bind to a company</li>
<li>I want something offline or/and on MY HOME SERVER</li>
</ul>
<h3 id="the-protocols" class="no-underline ">
  <a href="#the-protocols">
    <i class="fa-whiteboard fa-semibold fa-angle-right"></i><i class="fa-whiteboard fa-semibold fa-angle-right"></i>
    The protocols
  </a>
  </h3>
<p>Searching for the protocols I choose Thread<sup id="fnref:2"><a href="#fn:2" class="footnote-ref" role="doc-noteref">2</a></sup> and Zigbee<sup id="fnref:3"><a href="#fn:3" class="footnote-ref" role="doc-noteref">3</a></sup>.
One reason is because they are the most used protocol for communication and more easy to find online (Amazon) and offline (Ikea and othe local shop).</p>
<p>For starting I will implement only Thread because the more easy tech for me are all Matter over Thread so I start with Thread.</p>
<p>From the infographic I found, I need to implement Matter<sup id="fnref:4"><a href="#fn:4" class="footnote-ref" role="doc-noteref">4</a></sup> also because Matter is the top stuff for an Home Assistant.
<img  class="center-img u-photo "  src="matter_thread_infographic.png" alt="Matter Thread Infographic "></p>
<h3 id="the-software" class="no-underline ">
  <a href="#the-software">
    <i class="fa-whiteboard fa-semibold fa-angle-right"></i><i class="fa-whiteboard fa-semibold fa-angle-right"></i>
    The software
  </a>
  </h3>
<p>Now I want a software, Open Source, which I can support Thread and Matter (and also Zigbee) and I found a software (Open Source) wich support all I need: Home Assistant<sup id="fnref:5"><a href="#fn:5" class="footnote-ref" role="doc-noteref">5</a></sup>.</p>
<p>It support Matter<sup id="fnref:6"><a href="#fn:6" class="footnote-ref" role="doc-noteref">6</a></sup>, Thread<sup id="fnref:7"><a href="#fn:7" class="footnote-ref" role="doc-noteref">7</a></sup> and Zigbee<sup id="fnref:8"><a href="#fn:8" class="footnote-ref" role="doc-noteref">8</a></sup> and I can put it in a RaspberryPi or other server.</p>
<h2 id="hardware" class="no-underline ">
  <a href="#hardware">
    <i class="fa-whiteboard fa-semibold fa-angle-right"></i>
    Hardware
  </a>
  </h2>
<p>So I start to make a list of what I have and what I need.
Some things I buy online, some things come from some tech market and some come form the shoes box of my old stuff&hellip;</p>
<p>I only write about the real things but if I use cable or other &ldquo;standard stuff&rdquo; I don&rsquo;t write about it.
So yes I bought some usb extention and some network cable but they aren&rsquo;t important for this post.</p>
<h3 id="corebrain-stuff" class="no-underline ">
  <a href="#corebrain-stuff">
    <i class="fa-whiteboard fa-semibold fa-angle-right"></i><i class="fa-whiteboard fa-semibold fa-angle-right"></i>
    Core/Brain Stuff
  </a>
  </h3>
<p>First I need the Brain for the project</p>
<p><img  class="center-img u-photo "  src="ABnormal_GIF.gif" alt="Brain"></p>
<p>From what I read in the Home Assistant<sup id="fnref1:5"><a href="#fn:5" class="footnote-ref" role="doc-noteref">5</a></sup> documentation I need some type of server with some gadget connected to them.</p>
<p>So I search and  got a RaspberryPi 4B<sup id="fnref:9"><a href="#fn:9" class="footnote-ref" role="doc-noteref">9</a></sup>.
<img  class="center-img u-photo "  src="raspberry.jpg" alt="Raspberry"></p>
<p>I also bought a microSD with 64GB of memory (I am on a budget for this project) as an Hard Disk for the &ldquo;server&rdquo;.</p>
<p>Searching in my closet and in some shoes boxes I found a case<sup id="fnref:10"><a href="#fn:10" class="footnote-ref" role="doc-noteref">10</a></sup> for RaspberryPi with active cooling system (and LGB light)</p>
<p>So I flash the microSD with the Home Assistant software. Thanks to the Raspberry Pi Software<sup id="fnref:11"><a href="#fn:11" class="footnote-ref" role="doc-noteref">11</a></sup> choosing the right iso and flash it in the SD was a walk in the park.</p>
<p>After the flashing I set it up and add to my local network and check for update.</p>
<p>So the brain is ready!</p>
<h3 id="sensor-form-ikea" class="no-underline ">
  <a href="#sensor-form-ikea">
    <i class="fa-whiteboard fa-semibold fa-angle-right"></i><i class="fa-whiteboard fa-semibold fa-angle-right"></i>
    Sensor form Ikea
  </a>
  </h3>
<p>I went to Ikea for some stuff and some Swedish meatballs and I came back with an Ikea Alpstuga<sup id="fnref:12"><a href="#fn:12" class="footnote-ref" role="doc-noteref">12</a></sup>.</p>
<p><img  class="center-img u-photo "  src="ikea.jpg" alt="Ikea Alpstuga"></p>
<p>It is a timer, air sensor with CO2 and PM2.5 sensor and output all of them and an Air Quality value.</p>
<p>The only bad thing about it is the color but for the price I don&rsquo;t complain.</p>
<p>So after coming home I found it didn&rsquo;t work.</p>
<p><img  class="center-img u-photo "  src="nope.gif" alt="Nope"></p>
<p>As is the RaspberryPi 4B do not support Thread or Zigbee without some type of specialized antenna&hellip;
I was understanding that the software use the wifi module of the RaspberryPi as a Zigbee/Thread emitter/reciver but no so I search on Amazon for the dongle for Thread.</p>
<h3 id="antenna" class="no-underline ">
  <a href="#antenna">
    <i class="fa-whiteboard fa-semibold fa-angle-right"></i><i class="fa-whiteboard fa-semibold fa-angle-right"></i>
    Antenna
  </a>
  </h3>
<p>I bought a Usb dongle<sup id="fnref:13"><a href="#fn:13" class="footnote-ref" role="doc-noteref">13</a></sup> for connecting the RaspberryPi and the other gadget in the house (for now only the Ikea one)</p>
<p><img  class="center-img u-photo "  src="antenna.jpg" alt="Antenna"><sup id="fnref1:13"><a href="#fn:13" class="footnote-ref" role="doc-noteref">13</a></sup></p>
<p>This antenna is a little special: you can flash it for changing it form Zigbee to Thread and vice versa so I start to config it.</p>
<h4 id="setup-the-antenna" class="no-underline ">
  <a href="#setup-the-antenna">
    <i class="fa-whiteboard fa-semibold fa-angle-right"></i><i class="fa-whiteboard fa-semibold fa-angle-right"></i><i class="fa-whiteboard fa-semibold fa-angle-right"></i>
    Setup the Antenna
  </a>
  </h4>
<p>First I flash the antenna. I need to port from Zigbee to Thread<sup id="fnref:14"><a href="#fn:14" class="footnote-ref" role="doc-noteref">14</a></sup> and with the online tool it was so easy I thought I did something wrong.</p>
<p>After this I connect the dongle and start to config the Home Assistant.</p>
<p>First I need to have installed Thread  from &ldquo;Add Integration&rdquo; and it showed an empty list of device. This is correct because I didn&rsquo;t have a Thread router installed.</p>
<p>So we add a OpenRouter. How? Installing from the officials app of mine Home Assistant.</p>
<p><img  class="center-img u-photo "  src="Thread.png" alt="Open Thread on a menu"></p>
<p>After this I edit the config in this way (the device was auto-finded) and I set this for my device. <sup id="fnref:15"><a href="#fn:15" class="footnote-ref" role="doc-noteref">15</a></sup></p>
<p><img  class="center-img u-photo "  src="openThread.png" alt="Open Thread config"></p>
<p>For checking if all was ok I went and seach in the log for the OpenThread for a specific line.</p>
<p><img  class="center-img u-photo "  src="log-antenna.png" alt="Log Antenna"></p>
<p>After this I went to check if the Thread integration showed the Ikea sensor and it didn&rsquo;t show&hellip; Why? Because I am STUPID.</p>
<h4 id="setup-the-last-little-things" class="no-underline ">
  <a href="#setup-the-last-little-things">
    <i class="fa-whiteboard fa-semibold fa-angle-right"></i><i class="fa-whiteboard fa-semibold fa-angle-right"></i><i class="fa-whiteboard fa-semibold fa-angle-right"></i>
    Setup the last little things
  </a>
  </h4>
<p>Alpstuga (my air sensor) is not Thread, is Matter over Thread, so I need to add the thing with the Matter integration. And with this last integration the system worked!</p>
<p><img  class="center-img u-photo "  src="its-alive.gif" alt="Its alive"></p>
<p>I am happy of this system? No. Why? I have the wrong time on the Alpstuga.</p>
<p>This thing I don&rsquo;t understand so I search online for understand how can I fix the time on the device.</p>
<p>I find this is a common problem with the Alpstuga device and someone made a Hacs<sup id="fnref:16"><a href="#fn:16" class="footnote-ref" role="doc-noteref">16</a></sup> plugin<sup id="fnref:17"><a href="#fn:17" class="footnote-ref" role="doc-noteref">17</a></sup> wich add a cron and a button for sync the Home Assistant&rsquo;s clock. I also add the plugin for integrate my Playstation Network in my Home Assistant<sup id="fnref:18"><a href="#fn:18" class="footnote-ref" role="doc-noteref">18</a></sup>.</p>
<h2 id="conclusion" class="no-underline ">
  <a href="#conclusion">
    <i class="fa-whiteboard fa-semibold fa-angle-right"></i>
    Conclusion
  </a>
  </h2>
<p>For now this is what I had done but I want to have automation (for now I don&rsquo;t have any) and some stuff for lower the gas bill so there will be more post about my smart home.</p>
<div class="footnotes" role="doc-endnotes">
<hr>
<ol>
<li id="fn:1">
<p>I pay a company to install it and I clean after.&#160;<a href="#fnref:1" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
<li id="fn:2">
<p><a class="a-post interlink-script" href="https://threadgroup.org/"   target="_blank">Thread Standard&nbsp;&nbsp;<i class="fa-whiteboard fa-semibold fa-link"></i></a>
&#160;<a href="#fnref:2" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
<li id="fn:3">
<p><a class="a-post interlink-script" href="https://csa-iot.org/all-solutions/zigbee/"   target="_blank">Zigbee Standard&nbsp;&nbsp;<i class="fa-whiteboard fa-semibold fa-link"></i></a>
&#160;<a href="#fnref:3" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
<li id="fn:4">
<p><a class="a-post interlink-script" href="https://csa-iot.org/all-solutions/matter/"   target="_blank">Matter Standard&nbsp;&nbsp;<i class="fa-whiteboard fa-semibold fa-link"></i></a>
&#160;<a href="#fnref:4" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
<li id="fn:5">
<p><a class="a-post interlink-script" href="https://www.home-assistant.io/"   target="_blank">Home Assistant&nbsp;&nbsp;<i class="fa-whiteboard fa-semibold fa-link"></i></a>
&#160;<a href="#fnref:5" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a>&#160;<a href="#fnref1:5" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
<li id="fn:6">
<p><a class="a-post interlink-script" href="https://www.home-assistant.io/integrations/matter/"   target="_blank">Home Assistant Matter&nbsp;&nbsp;<i class="fa-whiteboard fa-semibold fa-link"></i></a>
&#160;<a href="#fnref:6" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
<li id="fn:7">
<p><a class="a-post interlink-script" href="https://www.home-assistant.io/integrations/thread/"   target="_blank">Home Assistant Thread&nbsp;&nbsp;<i class="fa-whiteboard fa-semibold fa-link"></i></a>
&#160;<a href="#fnref:7" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
<li id="fn:8">
<p><a class="a-post interlink-script" href="https://www.home-assistant.io/integrations/zha/"   target="_blank">Zigbee Home Automation&nbsp;&nbsp;<i class="fa-whiteboard fa-semibold fa-link"></i></a>
&#160;<a href="#fnref:8" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
<li id="fn:9">
<p><a class="a-post interlink-script" href="https://www.raspberrypi.com/products/raspberry-pi-4-model-b/"   target="_blank">RaspberryPi 4B&nbsp;&nbsp;<i class="fa-whiteboard fa-semibold fa-link"></i></a>
&#160;<a href="#fnref:9" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
<li id="fn:10">
<p><a class="a-post interlink-script" href="https://www.amazon.it/dp/B07YJGWPQL"   target="_blank">Raspberry Pi 4B Case from Owootecc&nbsp;&nbsp;<i class="fa-whiteboard fa-semibold fa-link"></i></a>
&#160;<a href="#fnref:10" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
<li id="fn:11">
<p><a class="a-post interlink-script" href="https://www.raspberrypi.com/software/"   target="_blank">Raspberry Pi software&nbsp;&nbsp;<i class="fa-whiteboard fa-semibold fa-link"></i></a>
&#160;<a href="#fnref:11" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
<li id="fn:12">
<p><a class="a-post interlink-script" href="https://www.ikea.com/it/it/p/alpstuga-sensore-della-qualita-dellaria-smart-50604187/"   target="_blank">Ikea Alpstuga&nbsp;&nbsp;<i class="fa-whiteboard fa-semibold fa-link"></i></a>
&#160;<a href="#fnref:12" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
<li id="fn:13">
<p><a class="a-post interlink-script" href="https://www.amazon.it/dp/B0FMJD288B"   target="_blank">SONOFF Zigbee 3.0 USB Dongle Plus MG24&nbsp;&nbsp;<i class="fa-whiteboard fa-semibold fa-link"></i></a>
&#160;<a href="#fnref:13" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a>&#160;<a href="#fnref1:13" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
<li id="fn:14">
<p><a class="a-post interlink-script" href="https://dongle.sonoff.tech/sonoff-dongle-flasher/"   target="_blank">Sonoff dongle flasher/&nbsp;&nbsp;<i class="fa-whiteboard fa-semibold fa-link"></i></a>
&#160;<a href="#fnref:14" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
<li id="fn:15">
<p>This config work for me, it can not work for you&#160;<a href="#fnref:15" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
<li id="fn:16">
<p><a class="a-post interlink-script" href="https://www.hacs.xyz/"   target="_blank">Home Assistant Hacs&nbsp;&nbsp;<i class="fa-whiteboard fa-semibold fa-link"></i></a>
&#160;<a href="#fnref:16" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
<li id="fn:17">
<p><a class="a-post interlink-script" href="https://github.com/Loweack/Matter-Time-Sync/"   target="_blank">Matter time synk&nbsp;&nbsp;<i class="fa-whiteboard fa-semibold fa-link"></i></a>
&#160;<a href="#fnref:17" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
<li id="fn:18">
<p><a class="a-post interlink-script" href="https://www.home-assistant.io/integrations/playstation_network/"   target="_blank">PlayStation Network Home Assistant&nbsp;&nbsp;<i class="fa-whiteboard fa-semibold fa-link"></i></a>
&#160;<a href="#fnref:18" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
</ol>
</div>
]]></content></entry><entry><id>tag:fundor333.com,2026:/post/2026/why-do-i-disinstall-poetry-and-use-only-uv-/</id><link rel="alternate" href="https://fundor333.com/post/2026/why-do-i-disinstall-poetry-and-use-only-uv-/"/><title>Why Do I Disinstall Poetry and Use Only Uv</title><published>2026-01-26T21:58:02+01:00</published><updated>2026-07-16T22:49:21+02:00</updated><content type="html" xml:base="https://fundor333.com/" xml:lang="en">
<![CDATA[<p>558 days ago (yes I count them), I wrote a follow-up article called <a class="a-post interlink-script" href="/post/2024/why-do-i-disinstall-pipenv-and-use-only-poetry/"  >Why Do I Disinstall Pipenv and Use Only Poetry?</a>
 and now I remake mine dev space, for building python project.</p>
<p>Some of the arguments are old, some are new but all come from my dev stack.</p>
<h2 id="build-a-venv" class="no-underline ">
  <a href="#build-a-venv">
    <i class="fa-whiteboard fa-semibold fa-angle-right"></i>
    Build a .venv
  </a>
  </h2>
<p>For every Python project I wrote, I code all the project with a Virtual Env or .venv.
It is a local &ldquo;installation&rdquo; of Python for the folder and it keep all the dependency inside it.</p>
<p>It is the best way to develop python project because you can have any number of Python project, with different version of Python and/or different version of the dipendency for each project.</p>
<p>Because I use git I need a good way to lock and commit the dipendency of my project. Some time ago I was using Poetry but now I use UV for build, update and manage the Virtual Env</p>
<p><img  class="center-img u-photo "  src="virtual-environment-make.jpg" alt="virtual-environment-make.jpg"></p>
<h2 id="creating-a-env-file" class="no-underline ">
  <a href="#creating-a-env-file">
    <i class="fa-whiteboard fa-semibold fa-angle-right"></i>
    Creating a .env file
  </a>
  </h2>
<p>Every python project I create, I always add a .env file, where I store all the environment variable for the project but I don&rsquo;t add them to the repo because It is not necessary add the local config for dev in a repo.</p>
<p>You can also automatically use the .env file in Uv so every time you are inside the .venv, you also have all the variables.</p>
<h2 id="using-uv" class="no-underline ">
  <a href="#using-uv">
    <i class="fa-whiteboard fa-semibold fa-angle-right"></i>
    Using UV
  </a>
  </h2>
<p>So after some time I was using Poetry and Pipenv, I find <a class="a-post interlink-script" href="https://github.com/astral-sh/uv"   target="_blank">UV&nbsp;&nbsp;<i class="fa-whiteboard fa-semibold fa-link"></i></a>
, a tool write in Rust for locking dipendnecy, set up and manage the .venv and create package for the publication in one tool.</p>
<p>You can easly start a procjet with a simple command</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>uv init</span></span></code></pre></div>
<p>which create the pyproject.toml and the .venv with all the dipendency.</p>
<p>With some other command you can easily add, remove and update the dipendency or import in a easy way your .env file.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>uv run --env-file<span style="color:#f92672">=</span>.env</span></span></code></pre></div>
<p>I move to UV because I can use a single tool for all my python necessity and it is faster and less bugged.</p>
<h2 id="editor-config" class="no-underline ">
  <a href="#editor-config">
    <i class="fa-whiteboard fa-semibold fa-angle-right"></i>
    Editor Config
  </a>
  </h2>
<p>We have the .venv, we have the .env, we have the dependency manager so I add the Editor Config file for the style of the code.
The <a class="a-post interlink-script" href="https://editorconfig.org/"   target="_blank">Editor Config file&nbsp;&nbsp;<i class="fa-whiteboard fa-semibold fa-link"></i></a>
 is a file where you define the style for the type of file you write in your repo.</p>
<p>I have mine made year after year but I start with the <a class="a-post interlink-script" href="https://editorconfig.org/#example-file"   target="_blank">example&nbsp;&nbsp;<i class="fa-whiteboard fa-semibold fa-link"></i></a>
 in the site because it is easy and with all the stuff you need.</p>
<h2 id="makefile-it" class="no-underline ">
  <a href="#makefile-it">
    <i class="fa-whiteboard fa-semibold fa-angle-right"></i>
    Makefile it
  </a>
  </h2>
<p>So, after adding stuff over stuff to the repo, I add a makefile where yu have all the aliases for a python project, <sup id="fnref:1"><a href="#fn:1" class="footnote-ref" role="doc-noteref">1</a></sup>.</p>
<p>My basic makefile is something like this</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-Makefile" data-lang="Makefile"><span style="display:flex;"><span>SHELL <span style="color:#f92672">:=</span> /bin/bash
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>RUNNER <span style="color:#f92672">:=</span> uv run --env-file<span style="color:#f92672">=</span>.env
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">.PHONY</span><span style="color:#f92672">:</span> help
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">help</span><span style="color:#f92672">:</span> <span style="color:#75715e">## Show this help
</span></span></span><span style="display:flex;"><span>	@egrep -h <span style="color:#e6db74">&#39;\s##\s&#39;</span> <span style="color:#66d9ef">$(</span>MAKEFILE_LIST<span style="color:#66d9ef">)</span> | sort | awk <span style="color:#e6db74">&#39;BEGIN {FS = &#34;:.*?## &#34;}; {printf &#34;\033[36m%-20s\033[0m %s\n&#34;, $$1, $$2}&#39;</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">.PHONY</span><span style="color:#f92672">:</span> install
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">install</span><span style="color:#f92672">:</span> <span style="color:#75715e">## Make venv and install requirements
</span></span></span><span style="display:flex;"><span>	@uv sync
</span></span><span style="display:flex;"><span>	@<span style="color:#66d9ef">$(</span>RUNNER<span style="color:#66d9ef">)</span> pre-commit install
</span></span><span style="display:flex;"><span>	@pre-commit autoupdate
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">.PHONY</span><span style="color:#f92672">:</span> update
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">update</span><span style="color:#f92672">:</span> <span style="color:#75715e">## Update requirements
</span></span></span><span style="display:flex;"><span>	@uv lock --upgrade
</span></span><span style="display:flex;"><span>	@<span style="color:#66d9ef">$(</span>RUNNER<span style="color:#66d9ef">)</span> pre-commit autoupdate
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">precommit</span><span style="color:#f92672">:</span> <span style="color:#75715e">## Run pre-commit hooks
</span></span></span><span style="display:flex;"><span>	@git add . &amp; uv run --env-file<span style="color:#f92672">=</span>.env pre-commit run --all-files
</span></span></code></pre></div>
<p>The help command come form a blog post<sup id="fnref:2"><a href="#fn:2" class="footnote-ref" role="doc-noteref">2</a></sup> and describe better at my other post<sup id="fnref:3"><a href="#fn:3" class="footnote-ref" role="doc-noteref">3</a></sup></p>
<p>I write a makefile for all my project because I forgot a lot of the command and parameters, so a makefile is a good way to have an &ldquo;deploy&rdquo; command or a &ldquo;test&rdquo; command for the project and forgot all the task needed for run a &ldquo;test&rdquo; or a &ldquo;deploy&rdquo;.</p>
<p>I also put all the test command into the makefile because sometime the test command is too long to remember&hellip;</p>
<h2 id="pre-commit-and-some-automation" class="no-underline ">
  <a href="#pre-commit-and-some-automation">
    <i class="fa-whiteboard fa-semibold fa-angle-right"></i>
    Pre commit and some automation
  </a>
  </h2>
<p>This is my personal safety net for the commits. Some time I wrote and push without any work or thing about what I am doing&hellip; For this reason I add pre-commit<sup id="fnref:4"><a href="#fn:4" class="footnote-ref" role="doc-noteref">4</a></sup> for autofix and check all this minor error.</p>
<p><img  class="center-img u-photo "  src="cox.gif" alt="cox.gif"></p>
<p>The took launch a lot of test BEFORE I can save the commit so I can find the error or getting a big fat NOPE for the commit, which I need to review for the problem.</p>
<h2 id="conclusion" class="no-underline ">
  <a href="#conclusion">
    <i class="fa-whiteboard fa-semibold fa-angle-right"></i>
    Conclusion
  </a>
  </h2>
<p>This is the stack I work with and I love it. It can be something custom and old style for some of the older tecnology but I find it complete for what I do.</p>
<div class="footnotes" role="doc-endnotes">
<hr>
<ol>
<li id="fn:1">
<p>I wrote an article about makefile caller <a class="a-post interlink-script" href="https://fundor333.com/post/2021/the-team-makefile/"   target="_blank">The Team Makefile&nbsp;&nbsp;<i class="fa-whiteboard fa-semibold fa-link"></i></a>
&#160;<a href="#fnref:1" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
<li id="fn:2">
<p><a class="a-post interlink-script" href="https://victoria.dev/archive/how-to-create-a-self-documenting-makefile/"   target="_blank">How to create a self-documenting Makefile&nbsp;&nbsp;<i class="fa-whiteboard fa-semibold fa-link"></i></a>
&#160;<a href="#fnref:2" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
<li id="fn:3">
<p><a class="a-post interlink-script" href="https://fundor333.com/post/2021/the-team-makefile/"   target="_blank">The Team Makefile&nbsp;&nbsp;<i class="fa-whiteboard fa-semibold fa-link"></i></a>
&#160;<a href="#fnref:3" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
<li id="fn:4">
<p><a class="a-post interlink-script" href="https://praful932.dev/blog-2-pre-commit-hooks/"   target="_blank">Using pre-commit hooks to write better code&nbsp;&nbsp;<i class="fa-whiteboard fa-semibold fa-link"></i></a>
&#160;<a href="#fnref:4" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
</ol>
</div>
]]></content></entry><entry><id>tag:fundor333.com,2026:/post/2026/htmx-django-and-django-table2/</id><link rel="alternate" href="https://fundor333.com/post/2026/htmx-django-and-django-table2/"/><title>Htmx Django and Django Table2</title><published>2026-01-19T12:33:09+01:00</published><updated>2026-07-16T22:49:21+02:00</updated><summary type="text">How I use Htmx for showing in a Django project a django-table2 filled with data from a MonthArchiveView</summary><content type="html" xml:base="https://fundor333.com/" xml:lang="en">
<![CDATA[<p>For some time I am developing my personal Django server. It keeps some data for me and it is my automation server. And I want to test a Htmx code on Django so I make a little thing in my personal django project.</p>
<h2 id="what-i-have" class="no-underline ">
  <a href="#what-i-have">
    <i class="fa-whiteboard fa-semibold fa-angle-right"></i>
    What I have
  </a>
  </h2>
<p>I have a MonthArchiveView with render a table list with a lot of function I need: add element, change month show, exports query as files, etc&hellip;</p>
<p>I also don&rsquo;t like to reload all the page for change the month I am seeing on the page.
So I start to implement what I need.</p>
<p>And, from some comment from the web and some friends, I want less code and more clean one.</p>
<h2 id="what-i-used" class="no-underline ">
  <a href="#what-i-used">
    <i class="fa-whiteboard fa-semibold fa-angle-right"></i>
    What I used
  </a>
  </h2>
<p>For this project I used:</p>
<ul>
<li><strong>Django</strong> the framework used<sup id="fnref:1"><a href="#fn:1" class="footnote-ref" role="doc-noteref">1</a></sup></li>
<li><strong>Django Table2</strong> a module for easy creation of table for Django<sup id="fnref:2"><a href="#fn:2" class="footnote-ref" role="doc-noteref">2</a></sup></li>
<li><strong>Django Htmx</strong> a module for easy support of Htmx<sup id="fnref:3"><a href="#fn:3" class="footnote-ref" role="doc-noteref">3</a></sup></li>
<li><strong>Tablib</strong> a module for exporting the table as multiple file type<sup id="fnref:4"><a href="#fn:4" class="footnote-ref" role="doc-noteref">4</a></sup></li>
</ul>
<h3 id="the-py-code" class="no-underline ">
  <a href="#the-py-code">
    <i class="fa-whiteboard fa-semibold fa-angle-right"></i><i class="fa-whiteboard fa-semibold fa-angle-right"></i>
    The Py code
  </a>
  </h3>
<p>So I start with the code for the model. It need to have a DateTimeField or a DateField (this becose I want to have an MonthArchiveView view).</p>

<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-python" data-lang="python"><span style="display:flex;"><span><span style="color:#75715e"># blog/model.py</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">class</span> <span style="color:#a6e22e">Post</span>(models<span style="color:#f92672">.</span>Model):
</span></span><span style="display:flex;"><span>    title <span style="color:#f92672">=</span> models<span style="color:#f92672">.</span>CharField(max_length<span style="color:#f92672">=</span><span style="color:#ae81ff">400</span>)
</span></span><span style="display:flex;"><span>    slug <span style="color:#f92672">=</span> models<span style="color:#f92672">.</span>SlugField(max_length<span style="color:#f92672">=</span><span style="color:#ae81ff">400</span>, unique<span style="color:#f92672">=</span><span style="color:#66d9ef">True</span>, blank<span style="color:#f92672">=</span><span style="color:#66d9ef">True</span>)
</span></span><span style="display:flex;"><span>    content <span style="color:#f92672">=</span> models<span style="color:#f92672">.</span>TextAreaField()
</span></span><span style="display:flex;"><span>    date <span style="color:#f92672">=</span> models<span style="color:#f92672">.</span>DateTimeField(auto_now_add<span style="color:#f92672">=</span><span style="color:#66d9ef">True</span>)</span></span></code></pre></div><p>and after I add the code for the table with the ordering of the data</p>

<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-python" data-lang="python"><span style="display:flex;"><span><span style="color:#75715e"># blog/tables.py</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">import</span> django_tables2 <span style="color:#66d9ef">as</span> tables
</span></span><span style="display:flex;"><span><span style="color:#f92672">from</span> blog.models <span style="color:#f92672">import</span> Post
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">class</span> <span style="color:#a6e22e">PostTable</span>(tables<span style="color:#f92672">.</span>Table):
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">class</span> <span style="color:#a6e22e">Meta</span>:
</span></span><span style="display:flex;"><span>        model <span style="color:#f92672">=</span> Post
</span></span><span style="display:flex;"><span>        order_by <span style="color:#f92672">=</span> (<span style="color:#e6db74">&#34;-date&#34;</span>, <span style="color:#e6db74">&#34;title&#34;</span>)
</span></span><span style="display:flex;"><span>        fields <span style="color:#f92672">=</span> [<span style="color:#e6db74">&#34;date&#34;</span>, <span style="color:#e6db74">&#34;title&#34;</span>, <span style="color:#e6db74">&#34;slug&#34;</span>]</span></span></code></pre></div><p>After the model and the table we need the view called by the HTMX code.</p>
<p>I set all the config for choose the right data field and which is the format for month and year, followed for the export types&rsquo; settings.</p>

<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-python" data-lang="python"><span style="display:flex;"><span><span style="color:#75715e"># blog/views.py</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">from</span> django.views.generic <span style="color:#f92672">import</span> ListView
</span></span><span style="display:flex;"><span><span style="color:#f92672">from</span> django.contrib.auth.mixins <span style="color:#f92672">import</span> LoginRequiredMixin
</span></span><span style="display:flex;"><span><span style="color:#f92672">from</span> django_tables2 <span style="color:#f92672">import</span> SingleTableView, tables
</span></span><span style="display:flex;"><span><span style="color:#f92672">from</span> blog.models <span style="color:#f92672">import</span> Post
</span></span><span style="display:flex;"><span><span style="color:#f92672">from</span> blog.tables <span style="color:#f92672">import</span> PostTable
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">class</span> <span style="color:#a6e22e">PostMonthArchiveHtmx</span>(LoginRequiredMixin, ExportMixin, SingleTableMixin, MonthArchiveView):
</span></span><span style="display:flex;"><span>    model <span style="color:#f92672">=</span> Post
</span></span><span style="display:flex;"><span>    template_name <span style="color:#f92672">=</span> <span style="color:#e6db74">&#34;generic/table2_with_export.html&#34;</span>
</span></span><span style="display:flex;"><span>    table_class <span style="color:#f92672">=</span> PostTable
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    date_field <span style="color:#f92672">=</span> <span style="color:#e6db74">&#34;date&#34;</span>
</span></span><span style="display:flex;"><span>    allow_future <span style="color:#f92672">=</span> <span style="color:#66d9ef">True</span>
</span></span><span style="display:flex;"><span>    month_format <span style="color:#f92672">=</span> <span style="color:#e6db74">&#34;%m&#34;</span>
</span></span><span style="display:flex;"><span>    year_format <span style="color:#f92672">=</span> <span style="color:#e6db74">&#34;%Y&#34;</span>
</span></span><span style="display:flex;"><span>    allow_empty <span style="color:#f92672">=</span> <span style="color:#66d9ef">True</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    export_formats <span style="color:#f92672">=</span> (
</span></span><span style="display:flex;"><span>    TableExport<span style="color:#f92672">.</span>CSV,
</span></span><span style="display:flex;"><span>    TableExport<span style="color:#f92672">.</span>XLS,
</span></span><span style="display:flex;"><span>    TableExport<span style="color:#f92672">.</span>XLSX,
</span></span><span style="display:flex;"><span>    TableExport<span style="color:#f92672">.</span>ODS,)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">def</span> <span style="color:#a6e22e">get_month</span>(self):
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">try</span>:
</span></span><span style="display:flex;"><span>            month <span style="color:#f92672">=</span> super()<span style="color:#f92672">.</span>get_month()
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">except</span> Http404:
</span></span><span style="display:flex;"><span>            month <span style="color:#f92672">=</span> now()<span style="color:#f92672">.</span>strftime(self<span style="color:#f92672">.</span>get_month_format())
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">return</span> month
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">def</span> <span style="color:#a6e22e">get_year</span>(self):
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">try</span>:
</span></span><span style="display:flex;"><span>            year <span style="color:#f92672">=</span> super()<span style="color:#f92672">.</span>get_year()
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">except</span> Http404:
</span></span><span style="display:flex;"><span>            year <span style="color:#f92672">=</span> now()<span style="color:#f92672">.</span>strftime(self<span style="color:#f92672">.</span>get_year_format())
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">return</span> year
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">def</span> <span style="color:#a6e22e">get_export_filename</span>(self, export_format):
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">return</span> <span style="color:#e6db74">f</span><span style="color:#e6db74">&#34;Export Post </span><span style="color:#e6db74">{</span>self<span style="color:#f92672">.</span>get_year()<span style="color:#e6db74">}</span><span style="color:#e6db74">-</span><span style="color:#e6db74">{</span>self<span style="color:#f92672">.</span>get_month()<span style="color:#e6db74">}</span><span style="color:#e6db74">.</span><span style="color:#e6db74">{</span>export_format<span style="color:#e6db74">}</span><span style="color:#e6db74">&#34;</span></span></span></code></pre></div><p>I added a function for changing the name of the output file (because I like filename with date reference) and two functions for setting month and year if not given (we need them later for the Htmx part).</p>
<h3 id="the-jinja-part" class="no-underline ">
  <a href="#the-jinja-part">
    <i class="fa-whiteboard fa-semibold fa-angle-right"></i><i class="fa-whiteboard fa-semibold fa-angle-right"></i>
    The Jinja part
  </a>
  </h3>
<p>After the python code I wrote this generic template for all my django-table2 table (in this case with the export code)</p>

<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-django" data-lang="django"><span style="display:flex;"><span># templates/generic/table2_with_export.html
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">{%</span> <span style="color:#66d9ef">load</span> render_table from django_tables2 <span style="color:#75715e">%}</span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">{%</span> <span style="color:#66d9ef">load</span> export_url from django_tables2 <span style="color:#75715e">%}</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>&lt;div&gt;
</span></span><span style="display:flex;"><span>    <span style="color:#75715e">{%</span> <span style="color:#66d9ef">for</span> format <span style="color:#66d9ef">in</span> view.export_formats <span style="color:#75715e">%}</span>
</span></span><span style="display:flex;"><span>    &lt;a href=&#34;<span style="color:#75715e">{{</span> request.path <span style="color:#75715e">}}{%</span> <span style="color:#66d9ef">export_url</span> format <span style="color:#75715e">%}</span>&#34; target=&#34;_blank&#34;&gt;
</span></span><span style="display:flex;"><span>      &lt;code&gt;<span style="color:#75715e">{{</span> format <span style="color:#75715e">}}</span>&lt;/code&gt;
</span></span><span style="display:flex;"><span>    &lt;/a&gt;
</span></span><span style="display:flex;"><span>    <span style="color:#75715e">{%</span> <span style="color:#66d9ef">endfor</span> <span style="color:#75715e">%}</span>
</span></span><span style="display:flex;"><span>    &lt;hr&gt;
</span></span><span style="display:flex;"><span>    <span style="color:#75715e">{%</span> <span style="color:#66d9ef">render_table</span> table <span style="color:#75715e">%}</span>
</span></span><span style="display:flex;"><span>&lt;/div&gt;</span></span></code></pre></div><p>I take out all the css stuff so you can add your style and/or css classes.</p>
<p>At this point we have all we need to have a html page with the table and the exports we need. We only need to add this view into the urls&hellip;</p>
<p>For example this is a generic example for a urls file for this project</p>

<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-python" data-lang="python"><span style="display:flex;"><span><span style="color:#75715e"># blog/urls.py</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">from</span> django.urls <span style="color:#f92672">import</span> path
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">from</span> blog.views <span style="color:#f92672">import</span> (
</span></span><span style="display:flex;"><span>    PostMonthArchiveHtmx,
</span></span><span style="display:flex;"><span>)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>app_name <span style="color:#f92672">=</span> <span style="color:#e6db74">&#34;blog&#34;</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>urlpatterns <span style="color:#f92672">=</span> [
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    path(<span style="color:#e6db74">&#34;htmx/post&#34;</span>, PostMonthArchiveHtmx<span style="color:#f92672">.</span>as_view(month_format<span style="color:#f92672">=</span><span style="color:#e6db74">&#34;%m&#34;</span>,name<span style="color:#f92672">=</span><span style="color:#e6db74">&#34;htmx-post&#34;</span>)),
</span></span><span style="display:flex;"><span>]</span></span></code></pre></div><p>You can see that I didn&rsquo;t add the code for having the month and the year in the url. This is because I had a lot of problems with the next part and this is the cleanest way I found to code this.</p>
<h3 id="the-htmx-fragment" class="no-underline ">
  <a href="#the-htmx-fragment">
    <i class="fa-whiteboard fa-semibold fa-angle-right"></i><i class="fa-whiteboard fa-semibold fa-angle-right"></i>
    The Htmx fragment
  </a>
  </h3>
<p>I will assume that you have done the quickstart form Htmx&rsquo;s site<sup id="fnref:5"><a href="#fn:5" class="footnote-ref" role="doc-noteref">5</a></sup> because I don&rsquo;t want to write about Htmx&hellip;</p>
<p>So for using inside a Django project for calling the page with Htmx we need to add the csrf token inside the header of the request so I added inside the main tag for my project.</p>
<p>It resembles this fragment.</p>

<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-html" data-lang="html"><span style="display:flex;"><span><span style="color:#75715e">&lt;!-- template/base.html --&gt;</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">&lt;!-- Other part of the template--&gt;</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>&lt;<span style="color:#f92672">div</span> <span style="color:#a6e22e">hx-headers</span><span style="color:#f92672">=</span><span style="color:#e6db74">&#39;{&#34;x-csrftoken&#34;: &#34;{{ csrf_token }}&#34;}&#39;</span>&gt;
</span></span><span style="display:flex;"><span>  {% block content %}
</span></span><span style="display:flex;"><span>    (no content)
</span></span><span style="display:flex;"><span>  {% endblock %}
</span></span><span style="display:flex;"><span>&lt;/<span style="color:#f92672">div</span>&gt;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">&lt;!-- Other part of the template--&gt;</span></span></span></code></pre></div><p>So now I need to write the div for the Htmx. And this is what I wrote:</p>

<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-html" data-lang="html"><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>&lt;<span style="color:#f92672">div</span> <span style="color:#a6e22e">hx-get</span><span style="color:#f92672">=</span><span style="color:#e6db74">&#34;{% url &#39;blog:htmx-post&#39; %}?year={{ month|date:&#34;</span><span style="color:#a6e22e">Y</span><span style="color:#960050;background-color:#1e0010">&#34;</span> <span style="color:#960050;background-color:#1e0010">}}&amp;</span><span style="color:#a6e22e">month</span><span style="color:#f92672">=</span><span style="color:#e6db74">{{</span> <span style="color:#a6e22e">month</span><span style="color:#960050;background-color:#1e0010">|</span><span style="color:#a6e22e">date:</span><span style="color:#960050;background-color:#1e0010">&#34;</span><span style="color:#a6e22e">m</span><span style="color:#960050;background-color:#1e0010">&#34;</span> <span style="color:#960050;background-color:#1e0010">}}&amp;{{</span> <span style="color:#a6e22e">request</span><span style="color:#960050;background-color:#1e0010">.</span><span style="color:#a6e22e">GET</span><span style="color:#960050;background-color:#1e0010">.</span><span style="color:#a6e22e">urlencode</span> <span style="color:#960050;background-color:#1e0010">}}&#34;</span>
</span></span><span style="display:flex;"><span>     <span style="color:#a6e22e">hx-trigger</span><span style="color:#f92672">=</span><span style="color:#e6db74">&#34;load&#34;</span>&gt;This will be replaced.&lt;/<span style="color:#f92672">div</span>&gt;</span></span></code></pre></div><p>I build the url in the hx-get in a strange way because I need to add the query input for the MonthArchiveView (the &amp;month and &amp;year field in the url) and add all the other field. In this way I also have the sorting links in the header of the table working.</p>
<h2 id="conclusion" class="no-underline ">
  <a href="#conclusion">
    <i class="fa-whiteboard fa-semibold fa-angle-right"></i>
    Conclusion
  </a>
  </h2>
<p>This is how I have combine this 3 libs for my personal project and if you find it useful share it. Thanks!</p>
<div class="footnotes" role="doc-endnotes">
<hr>
<ol>
<li id="fn:1">
<p><a class="a-post interlink-script" href="https://www.djangoproject.com/"   target="_blank">Django is a high-level Python web framework that encourages rapid development and clean, pragmatic design. Built by experienced developers, it takes care of much of the hassle of web development, so you can focus on writing your app without needing to reinvent the wheel. It’s free and open source&nbsp;&nbsp;<i class="fa-whiteboard fa-semibold fa-link"></i></a>
&#160;<a href="#fnref:1" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
<li id="fn:2">
<p><a class="a-post interlink-script" href="https://github.com/jieter/django-tables2"   target="_blank">django-tables2 - An app for creating HTML tables&nbsp;&nbsp;<i class="fa-whiteboard fa-semibold fa-link"></i></a>
&#160;<a href="#fnref:2" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
<li id="fn:3">
<p><a class="a-post interlink-script" href="https://pypi.org/project/django-htmx/"   target="_blank">django-htmx Extensions for using Django with htmx&nbsp;&nbsp;<i class="fa-whiteboard fa-semibold fa-link"></i></a>
&#160;<a href="#fnref:3" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
<li id="fn:4">
<p><a class="a-post interlink-script" href="https://pypi.org/project/tablib/"   target="_blank">Tablib: format-agnostic tabular dataset library&nbsp;&nbsp;<i class="fa-whiteboard fa-semibold fa-link"></i></a>
&#160;<a href="#fnref:4" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
<li id="fn:5">
<p><a class="a-post interlink-script" href="https://htmx.org/docs/#introduction"   target="_blank">htmx in a Nutshell&nbsp;&nbsp;<i class="fa-whiteboard fa-semibold fa-link"></i></a>
&#160;<a href="#fnref:5" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
</ol>
</div>
]]></content></entry><entry><id>tag:fundor333.com,2025:/post/2025/generate-dataframe-summaries-with-python/</id><link rel="alternate" href="https://fundor333.com/post/2025/generate-dataframe-summaries-with-python/"/><title>Generate Dataframe Summaries With Python</title><published>2025-09-03T17:13:02+08:00</published><updated>2026-07-16T22:49:21+02:00</updated><summary type="text">How to generate dataframe summaries with python and AI for a type of dataset</summary><content type="html" xml:base="https://fundor333.com/" xml:lang="en">
<![CDATA[<p>How much time do you spend with making summaries of dataset? Too much and I don&rsquo;t like doing it so I search to do it with the AI. So this is my sperimentation with some medical data see at PyDataVe 22nd event and Mistral model.</p>
<h2 id="the-code-for-the-inizializzation" class="no-underline ">
  <a href="#the-code-for-the-inizializzation">
    <i class="fa-whiteboard fa-semibold fa-angle-right"></i>
    The code for the inizializzation
  </a>
  </h2>
<p>For start I need to install some dipendency</p>

<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-text" data-lang="text"><span style="display:flex;"><span>langchain&gt;=0.3.27
</span></span><span style="display:flex;"><span>langchain-ollama&gt;=0.3.7
</span></span><span style="display:flex;"><span>pandas&gt;=2.3.2</span></span></code></pre></div>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-python" data-lang="python"><span style="display:flex;"><span><span style="color:#f92672">import</span> pandas <span style="color:#66d9ef">as</span> pd
</span></span><span style="display:flex;"><span><span style="color:#f92672">from</span> langchain_ollama <span style="color:#f92672">import</span> ChatOllama
</span></span><span style="display:flex;"><span><span style="color:#f92672">from</span> typing <span style="color:#f92672">import</span> Literal
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>df <span style="color:#f92672">=</span> pd<span style="color:#f92672">.</span>read_csv(<span style="color:#e6db74">&#34;data/test.csv&#34;</span>)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>print(<span style="color:#e6db74">&#34;-*-&#34;</span> <span style="color:#f92672">*</span> <span style="color:#ae81ff">20</span>)
</span></span><span style="display:flex;"><span>print(<span style="color:#e6db74">f</span><span style="color:#e6db74">&#34;Dataset shape: </span><span style="color:#e6db74">{</span>df<span style="color:#f92672">.</span>shape<span style="color:#e6db74">}</span><span style="color:#e6db74">&#34;</span>)
</span></span><span style="display:flex;"><span>print(<span style="color:#e6db74">&#34;-*-&#34;</span> <span style="color:#f92672">*</span> <span style="color:#ae81ff">20</span>)
</span></span><span style="display:flex;"><span>print(<span style="color:#e6db74">&#34;Missing value stats:&#34;</span>)
</span></span><span style="display:flex;"><span>print(df<span style="color:#f92672">.</span>isnull()<span style="color:#f92672">.</span>sum())</span></span></code></pre></div><pre><code>-*--*--*--*--*--*--*--*--*--*--*--*--*--*--*--*--*--*--*--*-
Dataset shape: (418, 20)
-*--*--*--*--*--*--*--*--*--*--*--*--*--*--*--*--*--*--*--*-
Missing value stats:
ID                 0
N_Days             0
Status             0
Drug             106
Age                0
Sex                0
Ascites          106
Hepatomegaly     106
Spiders          106
Edema              0
Bilirubin          0
Cholesterol      134
Albumin            0
Copper           108
Alk_Phos         106
SGOT             106
Tryglicerides    136
Platelets         11
Prothrombin        2
Stage              6
dtype: int64
</code></pre>
<p>This is a section of the dataset and what is missing value of the stats.</p>
<p>Now we will start with the AI. In my case I user Ollama with Mistral model.
I install the model with</p>

<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>ollama run mistral</span></span></code></pre></div><p>And prepare the code for use the model. First you need to make a connection with the local LLM instance. This code use Mistral but you can pass any local LLM instance you have.</p>

<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-python" data-lang="python"><span style="display:flex;"><span><span style="color:#66d9ef">def</span> <span style="color:#a6e22e">get_llm</span>(model_name: str <span style="color:#f92672">=</span> <span style="color:#e6db74">&#34;mistral:latest&#34;</span>) <span style="color:#f92672">-&gt;</span> ChatOllama:
</span></span><span style="display:flex;"><span>    <span style="color:#e6db74">&#34;&#34;&#34;
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">    Create and configure a ChatOllama instance for local LLM inference.
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">    This function initializes a ChatOllama client configured to connect to a
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">    local Ollama server. The client is set up with deterministic output
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">    (temperature=0) for consistent responses across multiple calls with the
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">    same input.
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">    Parameters
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">    ----------
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">    model_name : str, optional
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">        The name of the Ollama model to use for chat completions.
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">        Must be a valid model name that is available on the local Ollama
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">        installation. Default is &#34;mistral:latest&#34;.
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">    Returns
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">    -------
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">    ChatOllama
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">        A configured ChatOllama instance ready for chat completions.
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">    &#34;&#34;&#34;</span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">return</span> ChatOllama(
</span></span><span style="display:flex;"><span>        model<span style="color:#f92672">=</span>model_name, base_url<span style="color:#f92672">=</span><span style="color:#e6db74">&#34;http://localhost:11434&#34;</span>, temperature<span style="color:#f92672">=</span><span style="color:#ae81ff">0</span>
</span></span><span style="display:flex;"><span>    )</span></span></code></pre></div><p>If you want to test the connection you can use this command</p>

<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-python" data-lang="python"><span style="display:flex;"><span>print(get_llm()<span style="color:#f92672">.</span>invoke(<span style="color:#e6db74">&#34;test&#34;</span>)<span style="color:#f92672">.</span>content)</span></span></code></pre></div><pre><code> Hallo! Wie geht es Ihnen? Ich bin hier, um Ihnen zu helfen. Was möchten Sie heute tun?

Ich kann Ihnen beispielsweise helfen:

* Fragen beantworten
* Informationen suchen
* Aufgaben lösen
* und vieles mehr!

Welche Aufgabe haben wir heute vor uns?
</code></pre>
<h2 id="make-a-context" class="no-underline ">
  <a href="#make-a-context">
    <i class="fa-whiteboard fa-semibold fa-angle-right"></i>
    Make a context
  </a>
  </h2>
<p>Now we need to generate a context for the LLM. If you do this function with all the necessary data you can relaunch this script every time you need a new README/summary of the dataset. This is better to be a dataset with a fixed schema and a date which change every year like medical data (this), monthly sell report, census data&hellip;</p>

<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-python" data-lang="python"><span style="display:flex;"><span><span style="color:#66d9ef">def</span> <span style="color:#a6e22e">get_summary_context_message</span>(df: pd<span style="color:#f92672">.</span>DataFrame, dataset_name:str) <span style="color:#f92672">-&gt;</span> str:
</span></span><span style="display:flex;"><span>    <span style="color:#75715e"># Basic application statistics</span>
</span></span><span style="display:flex;"><span>    total_analisys <span style="color:#f92672">=</span> len(df)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#75715e"># Gender distribution</span>
</span></span><span style="display:flex;"><span>    gender_counts <span style="color:#f92672">=</span> df[<span style="color:#e6db74">&#34;Sex&#34;</span>]<span style="color:#f92672">.</span>value_counts()
</span></span><span style="display:flex;"><span>    male_count <span style="color:#f92672">=</span> gender_counts<span style="color:#f92672">.</span>get(<span style="color:#e6db74">&#34;M&#34;</span>, <span style="color:#ae81ff">0</span>)
</span></span><span style="display:flex;"><span>    female_count <span style="color:#f92672">=</span> gender_counts<span style="color:#f92672">.</span>get(<span style="color:#e6db74">&#34;F&#34;</span>, <span style="color:#ae81ff">0</span>)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#75715e"># Stage Statistics</span>
</span></span><span style="display:flex;"><span>    stage_data <span style="color:#f92672">=</span> df[<span style="color:#e6db74">&#34;Stage&#34;</span>]<span style="color:#f92672">.</span>dropna()
</span></span><span style="display:flex;"><span>    stage_avg <span style="color:#f92672">=</span> stage_data<span style="color:#f92672">.</span>mean()
</span></span><span style="display:flex;"><span>    stage_25th <span style="color:#f92672">=</span> stage_data<span style="color:#f92672">.</span>quantile(<span style="color:#ae81ff">0.25</span>)
</span></span><span style="display:flex;"><span>    stage_50th <span style="color:#f92672">=</span> stage_data<span style="color:#f92672">.</span>quantile(<span style="color:#ae81ff">0.50</span>)
</span></span><span style="display:flex;"><span>    stage_75th <span style="color:#f92672">=</span> stage_data<span style="color:#f92672">.</span>quantile(<span style="color:#ae81ff">0.75</span>)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#75715e"># NDays Statistics</span>
</span></span><span style="display:flex;"><span>    days_data <span style="color:#f92672">=</span> df[<span style="color:#e6db74">&#34;N_Days&#34;</span>]<span style="color:#f92672">.</span>dropna()
</span></span><span style="display:flex;"><span>    days_avg <span style="color:#f92672">=</span> days_data<span style="color:#f92672">.</span>mean()
</span></span><span style="display:flex;"><span>    days_25th <span style="color:#f92672">=</span> days_data<span style="color:#f92672">.</span>quantile(<span style="color:#ae81ff">0.25</span>)
</span></span><span style="display:flex;"><span>    days_50th <span style="color:#f92672">=</span> days_data<span style="color:#f92672">.</span>quantile(<span style="color:#ae81ff">0.50</span>)
</span></span><span style="display:flex;"><span>    days_75th <span style="color:#f92672">=</span> days_data<span style="color:#f92672">.</span>quantile(<span style="color:#ae81ff">0.75</span>)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">def</span> <span style="color:#a6e22e">status_category</span>(exp):
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">if</span> pd<span style="color:#f92672">.</span>isna(exp):
</span></span><span style="display:flex;"><span>            <span style="color:#66d9ef">return</span> <span style="color:#e6db74">&#34;Unkown&#34;</span>
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">elif</span> exp <span style="color:#f92672">==</span> <span style="color:#e6db74">&#34;C&#34;</span>:
</span></span><span style="display:flex;"><span>            <span style="color:#66d9ef">return</span> <span style="color:#e6db74">&#34;Censored&#34;</span>
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">elif</span> exp <span style="color:#f92672">==</span> <span style="color:#e6db74">&#34;CL&#34;</span>:
</span></span><span style="display:flex;"><span>            <span style="color:#66d9ef">return</span> <span style="color:#e6db74">&#34;Censored due to Lever tx&#34;</span>
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">elif</span> exp <span style="color:#f92672">==</span> <span style="color:#e6db74">&#34;D&#34;</span>:
</span></span><span style="display:flex;"><span>            <span style="color:#66d9ef">return</span> <span style="color:#e6db74">&#34;Death&#34;</span>
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">else</span>:
</span></span><span style="display:flex;"><span>            <span style="color:#66d9ef">return</span> <span style="color:#e6db74">&#34;Unkow&#34;</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    df[<span style="color:#e6db74">&#39;Status Str&#39;</span>]<span style="color:#f92672">=</span> df[<span style="color:#e6db74">&#39;Status&#39;</span>]<span style="color:#f92672">.</span>apply(status_category)
</span></span><span style="display:flex;"><span>    status_str_stats <span style="color:#f92672">=</span> []
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">for</span> category <span style="color:#f92672">in</span> [<span style="color:#e6db74">&#34;Censored&#34;</span>, <span style="color:#e6db74">&#34;Censored due to Lever tx&#34;</span>, <span style="color:#e6db74">&#34;Death&#34;</span>,]:
</span></span><span style="display:flex;"><span>        category_data <span style="color:#f92672">=</span> df[df[<span style="color:#e6db74">&#34;Status Str&#34;</span>] <span style="color:#f92672">==</span> category]
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">if</span> len(category_data) <span style="color:#f92672">&gt;</span> <span style="color:#ae81ff">0</span>:
</span></span><span style="display:flex;"><span>            male <span style="color:#f92672">=</span> len(category_data[category_data[<span style="color:#e6db74">&#34;Sex&#34;</span>] <span style="color:#f92672">==</span> <span style="color:#e6db74">&#34;M&#34;</span>])
</span></span><span style="display:flex;"><span>            female <span style="color:#f92672">=</span> len(category_data[category_data[<span style="color:#e6db74">&#34;Sex&#34;</span>] <span style="color:#f92672">==</span> <span style="color:#e6db74">&#34;F&#34;</span>])
</span></span><span style="display:flex;"><span>            total <span style="color:#f92672">=</span> len(category_data)
</span></span><span style="display:flex;"><span>            rate_m <span style="color:#f92672">=</span> (male <span style="color:#f92672">/</span> total) <span style="color:#f92672">*</span> <span style="color:#ae81ff">100</span>
</span></span><span style="display:flex;"><span>            rate_f <span style="color:#f92672">=</span> (female <span style="color:#f92672">/</span> total) <span style="color:#f92672">*</span> <span style="color:#ae81ff">100</span>
</span></span><span style="display:flex;"><span>            status_str_stats<span style="color:#f92672">.</span>append((category, male, female, total, rate_m, rate_f))
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    summary <span style="color:#f92672">=</span><span style="color:#e6db74">f</span><span style="color:#e6db74">&#34;&#34;&#34;</span><span style="color:#e6db74">{</span>dataset_name<span style="color:#e6db74">}</span><span style="color:#e6db74">
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">Total Analisys: </span><span style="color:#e6db74">{</span>total_analisys<span style="color:#e6db74">:</span><span style="color:#e6db74">,</span><span style="color:#e6db74">}</span><span style="color:#e6db74">
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">Gender Distribution:
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">- Male applicants: </span><span style="color:#e6db74">{</span>male_count<span style="color:#e6db74">:</span><span style="color:#e6db74">,</span><span style="color:#e6db74">}</span><span style="color:#e6db74"> (</span><span style="color:#e6db74">{</span>male_count<span style="color:#f92672">/</span>total_analisys<span style="color:#f92672">*</span><span style="color:#ae81ff">100</span><span style="color:#e6db74">:</span><span style="color:#e6db74">.1f</span><span style="color:#e6db74">}</span><span style="color:#e6db74">%)
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">- Female applicants: </span><span style="color:#e6db74">{</span>female_count<span style="color:#e6db74">:</span><span style="color:#e6db74">,</span><span style="color:#e6db74">}</span><span style="color:#e6db74"> (</span><span style="color:#e6db74">{</span>female_count<span style="color:#f92672">/</span>total_analisys<span style="color:#f92672">*</span><span style="color:#ae81ff">100</span><span style="color:#e6db74">:</span><span style="color:#e6db74">.1f</span><span style="color:#e6db74">}</span><span style="color:#e6db74">%)
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">Stage Statistics:
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">- Average Stage: </span><span style="color:#e6db74">{</span>stage_avg<span style="color:#e6db74">:</span><span style="color:#e6db74">.2f</span><span style="color:#e6db74">}</span><span style="color:#e6db74">
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">- 25th percentile: </span><span style="color:#e6db74">{</span>stage_25th<span style="color:#e6db74">:</span><span style="color:#e6db74">.2f</span><span style="color:#e6db74">}</span><span style="color:#e6db74">
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">- 50th percentile (median): </span><span style="color:#e6db74">{</span>stage_50th<span style="color:#e6db74">:</span><span style="color:#e6db74">.2f</span><span style="color:#e6db74">}</span><span style="color:#e6db74">
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">- 75th percentile: </span><span style="color:#e6db74">{</span>stage_75th<span style="color:#e6db74">:</span><span style="color:#e6db74">.2f</span><span style="color:#e6db74">}</span><span style="color:#e6db74">
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">N Day Statistics:
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">- N Days Stage: </span><span style="color:#e6db74">{</span>days_avg<span style="color:#e6db74">:</span><span style="color:#e6db74">.2f</span><span style="color:#e6db74">}</span><span style="color:#e6db74">
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">- 25th percentile: </span><span style="color:#e6db74">{</span>days_25th<span style="color:#e6db74">:</span><span style="color:#e6db74">.2f</span><span style="color:#e6db74">}</span><span style="color:#e6db74">
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">- 50th percentile (median): </span><span style="color:#e6db74">{</span>days_50th<span style="color:#e6db74">:</span><span style="color:#e6db74">.2f</span><span style="color:#e6db74">}</span><span style="color:#e6db74">
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">- 75th percentile: </span><span style="color:#e6db74">{</span>days_75th<span style="color:#e6db74">:</span><span style="color:#e6db74">.2f</span><span style="color:#e6db74">}</span><span style="color:#e6db74">
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">&#34;&#34;&#34;</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    summary <span style="color:#f92672">+=</span> <span style="color:#e6db74">&#34;</span><span style="color:#ae81ff">\n\n</span><span style="color:#e6db74">Status Rates by Sex:&#34;</span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">for</span> category, male, female, total, rate_m, rate_f <span style="color:#f92672">in</span> status_str_stats:
</span></span><span style="display:flex;"><span>        summary <span style="color:#f92672">+=</span> (
</span></span><span style="display:flex;"><span>            <span style="color:#e6db74">f</span><span style="color:#e6db74">&#34;</span><span style="color:#ae81ff">\n</span><span style="color:#e6db74">- </span><span style="color:#e6db74">{</span>category<span style="color:#e6db74">}</span><span style="color:#e6db74">: </span><span style="color:#e6db74">{</span>male<span style="color:#e6db74">}</span><span style="color:#e6db74">/</span><span style="color:#e6db74">{</span>total<span style="color:#e6db74">}</span><span style="color:#e6db74"> Male (</span><span style="color:#e6db74">{</span>rate_m<span style="color:#e6db74">:</span><span style="color:#e6db74">.1f</span><span style="color:#e6db74">}</span><span style="color:#e6db74">% rate)&#34;</span><span style="color:#f92672">+</span>
</span></span><span style="display:flex;"><span>            <span style="color:#e6db74">f</span><span style="color:#e6db74">&#34;</span><span style="color:#ae81ff">\n</span><span style="color:#e6db74">- </span><span style="color:#e6db74">{</span>category<span style="color:#e6db74">}</span><span style="color:#e6db74">: </span><span style="color:#e6db74">{</span>female<span style="color:#e6db74">}</span><span style="color:#e6db74">/</span><span style="color:#e6db74">{</span>total<span style="color:#e6db74">}</span><span style="color:#e6db74"> Female (</span><span style="color:#e6db74">{</span>rate_f<span style="color:#e6db74">:</span><span style="color:#e6db74">.1f</span><span style="color:#e6db74">}</span><span style="color:#e6db74">% rate)&#34;</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>        )
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">return</span> summary</span></span></code></pre></div><h2 id="make-a-report" class="no-underline ">
  <a href="#make-a-report">
    <i class="fa-whiteboard fa-semibold fa-angle-right"></i>
    Make a report
  </a>
  </h2>
<p>After checking all you need to have a template for the repo of the dataset.</p>

<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-python" data-lang="python"><span style="display:flex;"><span>SUMMARIZE_DATAFRAME_PROMPT <span style="color:#f92672">=</span> <span style="color:#e6db74">&#34;&#34;&#34;
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">You are an expert data analyst and data summarizer.
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">Your task is to take in complex datasets and return user-friendly descriptions and findings.
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">You were given this dataset:
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">- Name: </span><span style="color:#e6db74">{dataset_name}</span><span style="color:#e6db74">
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">- Source: </span><span style="color:#e6db74">{dataset_source}</span><span style="color:#e6db74">
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">This dataset was analyzed in a pipeline before it was given to you.
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">These are the findings returned by the analysis pipeline:
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">&lt;context&gt;
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">{context}</span><span style="color:#e6db74">
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">&lt;/context&gt;
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">Based on these findings, write a detailed report in </span><span style="color:#e6db74">{report_format}</span><span style="color:#e6db74"> format.
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">Give the report a meaningful title and separate findings into sections with headings and subheadings.
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">Output only the report in </span><span style="color:#e6db74">{report_format}</span><span style="color:#e6db74"> and nothing else.
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">Report:
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">&#34;&#34;&#34;</span></span></span></code></pre></div><p>This prompt and a lot of the code of this article are from <a class="a-post interlink-script" href="https://towardsdatascience.com/llms-pandas-how-i-use-generative-ai-to-generate-pandas-dataframe-summaries-2/"   target="_blank">this post&nbsp;&nbsp;<i class="fa-whiteboard fa-semibold fa-link"></i></a>
.</p>
<p>After this we need a function that take the dataset <em>df</em>, the prompt <em>SUMMARIZE_DATAFRAME_PROMPT</em> with the needed info and return the content of the report.</p>

<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-python" data-lang="python"><span style="display:flex;"><span><span style="color:#66d9ef">def</span> <span style="color:#a6e22e">get_report_summary</span>(
</span></span><span style="display:flex;"><span>    dataset: pd<span style="color:#f92672">.</span>DataFrame,
</span></span><span style="display:flex;"><span>    dataset_name: str,
</span></span><span style="display:flex;"><span>    dataset_source: str,
</span></span><span style="display:flex;"><span>    report_format: Literal[<span style="color:#e6db74">&#34;markdown&#34;</span>, <span style="color:#e6db74">&#34;html&#34;</span>] <span style="color:#f92672">=</span> <span style="color:#e6db74">&#34;markdown&#34;</span>,
</span></span><span style="display:flex;"><span>) <span style="color:#f92672">-&gt;</span> str:
</span></span><span style="display:flex;"><span>    context_message <span style="color:#f92672">=</span> get_summary_context_message(df<span style="color:#f92672">=</span>dataset, dataset_name<span style="color:#f92672">=</span>dataset_name)
</span></span><span style="display:flex;"><span>    prompt <span style="color:#f92672">=</span> SUMMARIZE_DATAFRAME_PROMPT<span style="color:#f92672">.</span>format(
</span></span><span style="display:flex;"><span>        dataset_name<span style="color:#f92672">=</span>dataset_name,
</span></span><span style="display:flex;"><span>        dataset_source<span style="color:#f92672">=</span>dataset_source,
</span></span><span style="display:flex;"><span>        context<span style="color:#f92672">=</span>context_message,
</span></span><span style="display:flex;"><span>        report_format<span style="color:#f92672">=</span>report_format,
</span></span><span style="display:flex;"><span>    )
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">return</span> get_llm()<span style="color:#f92672">.</span>invoke(input<span style="color:#f92672">=</span>prompt)<span style="color:#f92672">.</span>content</span></span></code></pre></div><p>In our case we launch it as</p>

<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-python" data-lang="python"><span style="display:flex;"><span>md_report <span style="color:#f92672">=</span> get_report_summary(
</span></span><span style="display:flex;"><span>    dataset<span style="color:#f92672">=</span>df,
</span></span><span style="display:flex;"><span>    dataset_name<span style="color:#f92672">=</span><span style="color:#e6db74">&#34;Cirrhosis Patient Survival Prediction&#34;</span>,
</span></span><span style="display:flex;"><span>    dataset_source<span style="color:#f92672">=</span><span style="color:#e6db74">&#34;https://www.kaggle.com/datasets/joebeachcapital/cirrhosis-patient-survival-prediction/data&#34;</span>
</span></span><span style="display:flex;"><span>)
</span></span><span style="display:flex;"><span>print(md_report)</span></span></code></pre></div><pre><code> # Cirrhosis Patient Survival Prediction Analysis Report

## Overview
The dataset analyzed consists of 418 records related to cirrhosis patients, sourced from [Kaggle](https://www.kaggle.com/datasets/joebeachcapital/cirrhosis-patient-survival-prediction/data). The data provides information about the patient's gender, stage of cirrhosis, number of days since diagnosis, and final status (censored or death).

## Demographics
### Gender Distribution
The dataset shows a significant imbalance in gender distribution with 89.5% female applicants (374) and only 10.5% male applicants (44).

## Cirrhosis Stage Statistics
### Average Stage
The average stage of cirrhosis for the analyzed patients is 3.02, indicating a severe level of liver damage.

### Percentiles
- **25th percentile**: The cirrhosis stage is at least 2.00 for 25% of the patients.
- **Median (50th percentile)**: Half of the patients have a cirrhosis stage of 3.00.
- **75th percentile**: For 75% of the patients, the cirrhosis stage is 4.00 or lower.

## N Days Statistics
### N Days Stage
The average number of days since diagnosis for the analyzed patients is 1917.78 days.

### Percentiles
- **25th percentile**: The minimum number of days since diagnosis for 25% of the patients is 1092.75 days.
- **Median (50th percentile)**: Half of the patients have been diagnosed with cirrhosis for at least 1730.00 days.
- **75th percentile**: For 75% of the patients, the number of days since diagnosis is 2613.50 days or less.

## Status Rates by Sex
The following table shows the rates of different statuses (censored due to Lever tx and death) for both male and female applicants:

|                     | Male Applicants | Female Applicants |
|---------------------|-----------------|-------------------|
| Censored            | 17/232 (7.3%)    | 215/232 (92.7%)   |
| Censored due to Lever tx | 3/25 (12.0%)     | 22/25 (88.0%)     |
| Death                | 24/161 (14.9%)   | 137/161 (85.1%)   |

The analysis indicates that female applicants are more likely to have their status censored, either due to the lack of information or other factors, while male applicants are more likely to experience death. However, it's important to note that the sample size for male applicants is significantly smaller than that of female applicants.
</code></pre>
]]></content></entry><entry><id>tag:fundor333.com,2025:/post/2025/hugo-blog-with-jupyter-notebook/</id><link rel="alternate" href="https://fundor333.com/post/2025/hugo-blog-with-jupyter-notebook/"/><title>Hugo Blog With Jupyter Notebook</title><published>2025-09-01T08:40:34+02:00</published><updated>2026-07-16T22:49:21+02:00</updated><summary type="text">How to integrate a Jupyter Notebook to your Hugo Blog</summary><content type="html" xml:base="https://fundor333.com/" xml:lang="en">
<![CDATA[<p>A long time ago, I wrote a <a class="a-post interlink-script" href="/post/2017/jupyter-notebook-pelican-combo/"  >post</a>
 about writing a post for the Pelican static site generator made with a Jupyter Notebook. I did it because, at the time, I was a huge fan of the Notebooks and I had the blog generated by Pelican so&hellip;</p>
<p><img  class="center-img u-photo "  src="pydatave.jpg" alt="pydatave.jpg"></p>
<p>And now, after a PyDataVe (the 22nd event), I make a Jupyter Notebook after a lot of time and I feel the need to have a solution for make a Jupyter Notebook one of the post of my blog so I find a way to do it. This time in Hugo</p>
<h2 id="jupyter-in-my-hugo" class="no-underline ">
  <a href="#jupyter-in-my-hugo">
    <i class="fa-whiteboard fa-semibold fa-angle-right"></i>
    Jupyter in my Hugo
  </a>
  </h2>
<p>So first I search for a way to convert a Jupyter Notebook to a Markdown file with the headers for Hugo. So I find a <a class="a-post interlink-script" href="https://github.com/soda92/hugo-nbconvert"   target="_blank">python module&nbsp;&nbsp;<i class="fa-whiteboard fa-semibold fa-link"></i></a>
 to generate a Notebook with a starting metadata for my blog. All the metadata are inside the first cell set as a Markdown type cell.</p>
<p>All this is made by launching this command for generate the notebook</p>

<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>hugo_nbnew content/post/test-hugo-page</span></span></code></pre></div><p>And at the end of all the writing I launch this command</p>

<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>hugo_nbconvert content/post/test-hugo-page/index.ipynb</span></span></code></pre></div><p>for generate/updating the markdown file for Hugo.</p>
<h2 id="other-little-things-i-have-done" class="no-underline ">
  <a href="#other-little-things-i-have-done">
    <i class="fa-whiteboard fa-semibold fa-angle-right"></i>
    Other little things I have done
  </a>
  </h2>
<p>After testing all of this stuff I make some script for my personal writing pipeline (if I don&rsquo;t make some automation I feel bad) I fix some CSS of my site for the code part. I am a Backend Dev, so I don&rsquo;t share my CSS edit because it is something working but not so pretty to share&hellip;</p>
<p>After that I find myself wanting to have some way to cite a part of the post with a link (because I want to share a specific part of the post as a response to post/tweet/tooth on the web) and I search for something clean and usefull.</p>
<p>So I find a <a class="a-post interlink-script" href="https://www.bryanbraun.com/anchorjs/"   target="_blank">JS script&nbsp;&nbsp;<i class="fa-whiteboard fa-semibold fa-link"></i></a>
 for adding deep anchor links to my post and I set it to add a deep anchor for every paragraph of the posts.</p>
<p><img  class="center-img u-photo "  src="mastodon.png" alt="mastodon.png"></p>
<p>And after all I check if I implement the <a class="a-post interlink-script" href="https://blog.joinmastodon.org/2024/07/highlighting-journalism-on-mastodon/"   target="_blank">meta tag for journalism for Mastodon&nbsp;&nbsp;<i class="fa-whiteboard fa-semibold fa-link"></i></a>
 because I share a lot of stuff on Mastodon.</p>
<h2 id="final-consideration" class="no-underline ">
  <a href="#final-consideration">
    <i class="fa-whiteboard fa-semibold fa-angle-right"></i>
    Final consideration
  </a>
  </h2>
<p>I like my new configuration with the possibility to add Jupyter Notebook in my blog and this is the first Notebook I had to my Hugo Blog. I also like the idea that I can work for something else, make a Notebook and, only changing the data, make multiple article about something with the updated data every time I need to add the blog with the latest report for the dataset.</p>
]]></content></entry><entry><id>tag:fundor333.com,2025:/post/2025/generate-post-with-img-for-hugo/</id><link rel="alternate" href="https://fundor333.com/post/2025/generate-post-with-img-for-hugo/"/><title>Generate Post With Img for Hugo</title><published>2025-07-12T08:36:34+02:00</published><updated>2026-07-16T22:49:21+02:00</updated><summary type="text">How I create new post on Hugo and generate an image as cover</summary><content type="html" xml:base="https://fundor333.com/" xml:lang="en">
<![CDATA[<p>Some days ago I find a new post from a blog I follow about &ldquo;<a class="a-post interlink-script" href="https://www.burgeonlab.com/blog/hugo-and-wordpress-open-graph-meta-tags/"   target="_blank">Open Graph Meta Tags on Hugo and WordPress Blogs&nbsp;&nbsp;<i class="fa-whiteboard fa-semibold fa-link"></i></a>
&rdquo; as a toot</p>








    
    
        
        
    

    
        <div class="toot">
            <div class="toot-header">
                <a class="toot-profile" href="https://fosstodon.org/@eclecticpassions" rel="noopener">
                    <img src="https://cdn.fosstodon.org/accounts/avatars/110/631/569/439/879/798/original/63c2880c18d2bab3.jpg"
                         alt="Avatar for @eclecticpassions@fosstodon.org"
                         loading="lazy">
                </a>
                <div class="toot-author">
                    <a class="toot-author-name"
                       href="https://fosstodon.org/@eclecticpassions"
                       rel="noopener">Naty S</a>
                    <a class="toot-author-handle"
                       href="https://fosstodon.org/@eclecticpassions"
                       rel="noopener">@eclecticpassions@fosstodon.org</a>
                </div>
            </div>

            <div class="toot-content"><p>New <a href="https://fosstodon.org/tags/blogpost" class="mention hashtag" rel="tag">#<span>blogpost</span></a></p><p>➡️ <a href="https://www.burgeonlab.com/blog/hugo-and-wordpress-open-graph-meta-tags/" target="_blank" rel="nofollow noopener" translate="no"><span class="invisible">https://www.</span><span class="ellipsis">burgeonlab.com/blog/hugo-and-w</span><span class="invisible">ordpress-open-graph-meta-tags/</span></a></p><p>I often see bloggers on Mastodon with no images for their blog links or sometimes no link card at all (this was me not too long ago).</p><p>I&#39;ve been sorting out Open Graph meta tags for my three blogs (Hugo and WordPress) and I&#39;m happy to say it&#39;s all working great now! Read my post to get some tips! 👆 </p><p><a href="https://fosstodon.org/tags/BurgeonLab" class="mention hashtag" rel="tag">#<span>BurgeonLab</span></a><br /><a href="https://fosstodon.org/tags/blog" class="mention hashtag" rel="tag">#<span>blog</span></a> <a href="https://fosstodon.org/tags/blogging" class="mention hashtag" rel="tag">#<span>blogging</span></a> <a href="https://fosstodon.org/tags/blogs" class="mention hashtag" rel="tag">#<span>blogs</span></a> <a href="https://fosstodon.org/tags/hugo" class="mention hashtag" rel="tag">#<span>hugo</span></a> <a href="https://fosstodon.org/tags/wordpress" class="mention hashtag" rel="tag">#<span>wordpress</span></a> <a href="https://fosstodon.org/tags/webdev" class="mention hashtag" rel="tag">#<span>webdev</span></a> <a href="https://fosstodon.org/tags/opengraph" class="mention hashtag" rel="tag">#<span>opengraph</span></a></p></div>

            

            <div class="toot-footer">
                <a href="https://fosstodon.org@eclecticpassions/status/114818281454845557"
                   class="toot-date"
                   rel="noopener">3:18 PM · Jul 8, 2025</a>
            </div>
        </div>
    


<p>and I find I do the same thing and some more. I generate a default cover because I prefer to have a &ldquo;standard&rdquo; generated image or a specific image as the feature image. The image set in the settings is a default, a  &ldquo;if all other image fall use this&rdquo; kind of stuff.</p>
<h2 id="how-i-generate-the-post" class="no-underline ">
  <a href="#how-i-generate-the-post">
    <i class="fa-whiteboard fa-semibold fa-angle-right"></i>
    How I generate the post?
  </a>
  </h2>
<p>When I write a post I launch a <a class="a-post interlink-script" href="https://fundor333.com/post/2021/the-team-makefile/"  >makefile command</a>
 and it launch two command for me:</p>
<ol>
<li>Generate a new post with hugo new</li>
<li>Generate a cover with my python script</li>
</ol>
<h2 id="some-code" class="no-underline ">
  <a href="#some-code">
    <i class="fa-whiteboard fa-semibold fa-angle-right"></i>
    Some code
  </a>
  </h2>
<p>For this project I use a font (<a class="a-post interlink-script" href="https://font.download/font/futura-book"   target="_blank">Futura Book font&nbsp;&nbsp;<i class="fa-whiteboard fa-semibold fa-link"></i></a>
) and a image where put the title and other thing of the post (for now only the title).
This is the image &ldquo;clean&rdquo;, without the text.</p>
<p><img  class="center-img u-photo "  src="cover-blank.jpg" alt="cover-blank.jpg"></p>

<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-python" data-lang="python"><span style="display:flex;"><span><span style="color:#f92672">from</span> PIL <span style="color:#f92672">import</span> Image, ImageDraw, ImageFont  <span style="color:#75715e"># 👉️ Import modules from PIL</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">def</span> <span style="color:#a6e22e">generate_img</span>(message: str, path: str):
</span></span><span style="display:flex;"><span>    font_path <span style="color:#f92672">=</span> <span style="color:#e6db74">&#34;Futura Book font.ttf&#34;</span>  <span style="color:#75715e"># 👉️ Font .ttf Path</span>
</span></span><span style="display:flex;"><span>    font_size <span style="color:#f92672">=</span> <span style="color:#ae81ff">100</span>  <span style="color:#75715e"># 👉️ Font Size</span>
</span></span><span style="display:flex;"><span>    img <span style="color:#f92672">=</span> Image<span style="color:#f92672">.</span>open(<span style="color:#e6db74">&#34;cover-blank.jpg&#34;</span>)  <span style="color:#75715e"># 👉️ Open Image</span>
</span></span><span style="display:flex;"><span>    dr <span style="color:#f92672">=</span> ImageDraw<span style="color:#f92672">.</span>Draw(img)  <span style="color:#75715e"># 👉️ Create New Image</span>
</span></span><span style="display:flex;"><span>    my_font <span style="color:#f92672">=</span> ImageFont<span style="color:#f92672">.</span>truetype(font_path, font_size)  <span style="color:#75715e"># 👉️ Initialize Font</span>
</span></span><span style="display:flex;"><span>    text_x <span style="color:#f92672">=</span> (img<span style="color:#f92672">.</span>width) <span style="color:#f92672">//</span> <span style="color:#ae81ff">2</span>
</span></span><span style="display:flex;"><span>    text_y <span style="color:#f92672">=</span> (img<span style="color:#f92672">.</span>height) <span style="color:#f92672">//</span> <span style="color:#ae81ff">2</span>
</span></span><span style="display:flex;"><span>    dr<span style="color:#f92672">.</span>text((text_x, text_y), message, font<span style="color:#f92672">=</span>my_font, fill<span style="color:#f92672">=</span>(<span style="color:#ae81ff">255</span>, <span style="color:#ae81ff">255</span>, <span style="color:#ae81ff">255</span>), anchor<span style="color:#f92672">=</span><span style="color:#e6db74">&#34;mm&#34;</span>)
</span></span><span style="display:flex;"><span>    print(<span style="color:#e6db74">&#34;Generated content/&#34;</span> <span style="color:#f92672">+</span> path <span style="color:#f92672">+</span> <span style="color:#e6db74">&#34;/cover.png&#34;</span>)
</span></span><span style="display:flex;"><span>    img<span style="color:#f92672">.</span>save(<span style="color:#e6db74">&#34;content/&#34;</span> <span style="color:#f92672">+</span> path <span style="color:#f92672">+</span> <span style="color:#e6db74">&#34;/cover.png&#34;</span>)</span></span></code></pre></div><p>This script use Python (the library is PIL) and I set the fill parameters for a standard size OpenGraph image.</p>
<p>If you use a python script for generate new post you can implement this code inside of the script or you can add some code to make a command line to launch after your &ldquo;new post&rdquo; command.</p>
]]></content></entry><entry><id>tag:fundor333.com,2025:/post/2025/add-minor-things-to-django/</id><link rel="alternate" href="https://fundor333.com/post/2025/add-minor-things-to-django/"/><title>Add Minor Things to Django for templating</title><published>2025-06-15T21:36:00+02:00</published><updated>2026-07-16T22:49:21+02:00</updated><summary type="text">Some code I use in my django project for having some utility</summary><content type="html" xml:base="https://fundor333.com/" xml:lang="en">
<![CDATA[<p>More and more time I need some little thing for templating:</p>
<ul>
<li>The date fild of a form with the right input type for the page</li>
<li>A link with all the get parameters of the current page (form, paginator, etc&hellip;) and one added</li>
</ul>
<h2 id="the-code" class="no-underline ">
  <a href="#the-code">
    <i class="fa-whiteboard fa-semibold fa-angle-right"></i>
    The Code
  </a>
  </h2>
<p>This little code is mine but you can use it on all your project without thinking. If you find an error comment or webmention or replay with activity pub to my toot</p>
<h3 id="date-field-for-django-form" class="no-underline ">
  <a href="#date-field-for-django-form">
    <i class="fa-whiteboard fa-semibold fa-angle-right"></i><i class="fa-whiteboard fa-semibold fa-angle-right"></i>
    Date Field for Django Form
  </a>
  </h3>
<p>This is the widget I add to the django form for adding the right input type.</p>

<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-python" data-lang="python"><span style="display:flex;"><span><span style="color:#f92672">from</span> django.forms <span style="color:#f92672">import</span> TextInput
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">class</span> <span style="color:#a6e22e">DateInput</span>(TextInput):
</span></span><span style="display:flex;"><span>    input_type <span style="color:#f92672">=</span> <span style="color:#e6db74">&#34;date&#34;</span></span></span></code></pre></div><p>I need this because the css/js framework I use add a data picker if you fill the input_type</p>
<h3 id="tag-for-changekeep-a-field" class="no-underline ">
  <a href="#tag-for-changekeep-a-field">
    <i class="fa-whiteboard fa-semibold fa-angle-right"></i><i class="fa-whiteboard fa-semibold fa-angle-right"></i>
    Tag for change/keep a field
  </a>
  </h3>
<p>Sometime I need to edit or add a get parameter in a link, like when you change the view from list to grid (for example).
So I coded this simple tag.</p>

<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-python" data-lang="python"><span style="display:flex;"><span><span style="color:#f92672">from</span> django <span style="color:#f92672">import</span> template
</span></span><span style="display:flex;"><span>register <span style="color:#f92672">=</span> template<span style="color:#f92672">.</span>Library()
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">@register.simple_tag</span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">def</span> <span style="color:#a6e22e">url_replace</span>(request, field, value):
</span></span><span style="display:flex;"><span>    dict_ <span style="color:#f92672">=</span> request<span style="color:#f92672">.</span>GET<span style="color:#f92672">.</span>copy()
</span></span><span style="display:flex;"><span>    dict_[field] <span style="color:#f92672">=</span> value
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">return</span> dict_<span style="color:#f92672">.</span>urlencode()</span></span></code></pre></div><p>the only thing it does is change or add a value into the list of existing value.</p>
<p>For example</p>

<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-jinja" data-lang="jinja"><span style="display:flex;"><span>&lt;a href:&#34;https://fundor333.com?<span style="color:#75715e">{%</span> <span style="color:#66d9ef">url_replace_diff</span> request <span style="color:#e6db74">&#39;page&#39;</span> page_obj.page_number <span style="color:#75715e">%}</span>&#34;&gt;Link&lt;/a&gt;</span></span></code></pre></div><p>In this one I pass the pagination number to the new page. Why? Because I need to have the current page and all the serch filter also in the new page and this is the cleaner way WITHOUT using Js (I need control and Js is not controll)</p>
]]></content></entry><entry><id>tag:fundor333.com,2025:/post/2025/so-this-is-why-i-sometime-reset-the-feed-reader-of-friends/</id><link rel="alternate" href="https://fundor333.com/post/2025/so-this-is-why-i-sometime-reset-the-feed-reader-of-friends/"/><title>So This Is Why I Sometime Reset the Feed Reader of Friends</title><published>2025-05-31T12:32:59+02:00</published><updated>2026-07-16T22:49:21+02:00</updated><summary type="text">I find something I didn't know abouts feed rss and atom</summary><content type="html" xml:base="https://fundor333.com/" xml:lang="en">
<![CDATA[<p>I have a friend who read my blog using my feed. And sometime he pings me for some problem with the feed, like a drop of all the article as new</p>








    
    
        
        
    

    
        <div class="toot">
            <div class="toot-header">
                <a class="toot-profile" href="https://social.lol/@robb" rel="noopener">
                    <img src="https://s3.eu-central-003.backblazeb2.com/social-lol-media/accounts/avatars/109/523/762/776/095/110/original/548f0c6ecfffa5f1.jpg"
                         alt="Avatar for @robb@social.lol"
                         loading="lazy">
                </a>
                <div class="toot-author">
                    <a class="toot-author-name"
                       href="https://social.lol/@robb"
                       rel="noopener">Robb Knight</a>
                    <a class="toot-author-handle"
                       href="https://social.lol/@robb"
                       rel="noopener">@robb@social.lol</a>
                </div>
            </div>

            <div class="toot-content"><p>When I open my RSS reader and it has over 200 unread items, I know one of you has messed up your rss feeds</p><p>📌 <a href="https://rknight.me/notes/202501190902/" target="_blank" rel="nofollow noopener" translate="no"><span class="invisible">https://</span><span class="">rknight.me/notes/202501190902/</span><span class="invisible"></span></a></p></div>

            

            <div class="toot-footer">
                <a href="https://social.lol@robb/status/113854214799861227"
                   class="toot-date"
                   rel="noopener">9:04 AM · Jan 19, 2025</a>
            </div>
        </div>
    










    
    
        
        
    

    
        <div class="toot">
            <div class="toot-header">
                <a class="toot-profile" href="https://mastodon.social/@andreagrandi" rel="noopener">
                    <img src="https://files.mastodon.social/accounts/avatars/000/299/643/original/a1fe54a6da8006ce.jpg"
                         alt="Avatar for @andreagrandi@mastodon.social"
                         loading="lazy">
                </a>
                <div class="toot-author">
                    <a class="toot-author-name"
                       href="https://mastodon.social/@andreagrandi"
                       rel="noopener">Andrea Grandi 🦕</a>
                    <a class="toot-author-handle"
                       href="https://mastodon.social/@andreagrandi"
                       rel="noopener">@andreagrandi@mastodon.social</a>
                </div>
            </div>

            <div class="toot-content"><p><span class="h-card" translate="no"><a href="https://social.lol/@robb" class="u-url mention">@<span>robb</span></a></span> I think my friend <span class="h-card" translate="no"><a href="https://mastodon.social/@fundor333" class="u-url mention">@<span>fundor333</span></a></span> ears must be burning right now :D</p></div>

            

            <div class="toot-footer">
                <a href="https://mastodon.social@andreagrandi/status/113854638640440084"
                   class="toot-date"
                   rel="noopener">10:51 AM · Jan 19, 2025</a>
            </div>
        </div>
    


<p>And after read some other post with the same problem ( <a class="a-post interlink-script" href="https://rknight.me/notes/202501190902/"   target="_blank">Robb Knight problem with feed reader&nbsp;&nbsp;<i class="fa-whiteboard fa-semibold fa-link"></i></a>
 <a class="a-post interlink-script" href="https://kevquirk.com/notes/20250528-1702?utm_source=fundor333.com&amp;utm_medium=link&amp;utm_campaign=blogging&amp;ref=fundor333.com"   target="_blank">Kev other problem with feed reader&nbsp;&nbsp;<i class="fa-whiteboard fa-semibold fa-link"></i></a>
 ) I understand a little this: Atom is newer and superior than Rss.</p>
<h2 id="atom-vs-rss" class="no-underline ">
  <a href="#atom-vs-rss">
    <i class="fa-whiteboard fa-semibold fa-angle-right"></i>
    Atom vs Rss
  </a>
  </h2>
<p>Atom is the newer one, born after the RSS and after fix a lot of the RSS bugs like:</p>
<ul>
<li>You have a strict format for checking and validation in Atom</li>
<li>RSS is simpler but less strict and it is riddled with ambiguities which lead to inconsistency of interpretation</li>
<li>You have a unique id for the feed in Atom</li>
</ul>
<p>The last one is the one I was searching&hellip;</p>
<h2 id="the-answer" class="no-underline ">
  <a href="#the-answer">
    <i class="fa-whiteboard fa-semibold fa-angle-right"></i>
    The Answer
  </a>
  </h2>
<p>The feed reader find the new feed (new because you change the url or you change the serverside code) and check:</p>
<ul>
<li>Atom Feed: the reader find the same ID so is the same feed</li>
<li>RSS Feed: the reader don&rsquo;t find the ID and find something different not in the items part so it is a new one</li>
</ul>
<p>So I add the JsonFeed and AtomFeed to the blog for give the reader multiple option for the feed!</p>
<p>You can find all at <a class="a-post interlink-script" href="https://fundor333.com/feeds/"  >this link</a>
</p>
]]></content></entry><entry><id>tag:fundor333.com,2025:/post/2025/webring-into-2025/</id><link rel="alternate" href="https://fundor333.com/post/2025/webring-into-2025/"/><title>Having a Webring Into 2025</title><published>2025-05-24T12:11:42+02:00</published><updated>2026-07-16T22:49:21+02:00</updated><summary type="text">What are the webrings and why you need to be in one into 2025</summary><content type="html" xml:base="https://fundor333.com/" xml:lang="en">
<![CDATA[<p>Once upon a time Internet was different. No social media, no search engine, no fiber&hellip;
So how people find new site? Because the internet users share link into the blogs.</p>
<p>And one of the best way to share other blog without filling a webpage with links was the WebRing.</p>
<h2 id="webring" class="no-underline ">
  <a href="#webring">
    <i class="fa-whiteboard fa-semibold fa-angle-right"></i>
    WebRing?
  </a>
  </h2>
<p>For <a class="a-post interlink-script" href="https://en.wikipedia.org/wiki/Webring"   target="_blank">Wikipedia&nbsp;&nbsp;<i class="fa-whiteboard fa-semibold fa-link"></i></a>
 a Webring is</p>
<blockquote>
<p>A webring (or web ring) is a collection of websites linked together in a circular structure, usually organized around a specific theme, and often educational or social.[1] They were popular in the 1990s and early 2000s, particularly among amateur websites.</p>
</blockquote>
<p>Today, with the Search Engin owned by the big tec and the AI being part of the mayor Search Engine we need more than ever list of human web pages to read and less AI generated post.</p>
<h2 id="for-example" class="no-underline ">
  <a href="#for-example">
    <i class="fa-whiteboard fa-semibold fa-angle-right"></i>
    For example?
  </a>
  </h2>
<p>Some example of WebRing? This are some type of WebRing</p>
<ul>
<li><em>A themed WebRing</em> Like a <a class="a-post interlink-script" href="https://djangowebring.com/"   target="_blank">WebRing about Python&nbsp;&nbsp;<i class="fa-whiteboard fa-semibold fa-link"></i></a>
</li>
<li><em>An Inspirational WebRing</em> Like <a class="a-post interlink-script" href="https://webring.xxiivv.com/"   target="_blank">one for dev and artist&nbsp;&nbsp;<i class="fa-whiteboard fa-semibold fa-link"></i></a>
</li>
<li><em>One for Group of People</em> Like <a class="a-post interlink-script" href="https://webring.recurse.com/"   target="_blank">one for onl;y personal site&nbsp;&nbsp;<i class="fa-whiteboard fa-semibold fa-link"></i></a>
</li>
<li><em>One for a Community</em> Like <a class="a-post interlink-script" href="https://xn--sr8hvo.ws/directory"   target="_blank">one about IndieWeb&nbsp;&nbsp;<i class="fa-whiteboard fa-semibold fa-link"></i></a>
</li>
</ul>
<p>If you don&rsquo;t find a WebRing for your &ldquo;community&rdquo;, you can create a new one with a tutorial ( <a class="a-post interlink-script" href="https://mxb.dev/blog/webring-kit/"   target="_blank">A Webring Kit&nbsp;&nbsp;<i class="fa-whiteboard fa-semibold fa-link"></i></a>
 ) and a framework for making WebRing ( <a class="a-post interlink-script" href="https://github.com/maxboeck/webring"   target="_blank">GitHub Repo from A Webring Kit&nbsp;&nbsp;<i class="fa-whiteboard fa-semibold fa-link"></i></a>
 )</p>
<p>Remember, this is a free way to have more traffic inside your site and for build your community</p>
]]></content></entry><entry><id>tag:fundor333.com,2025:/post/2025/django-generate-barcode-with-reportlab/</id><link rel="alternate" href="https://fundor333.com/post/2025/django-generate-barcode-with-reportlab/"/><title>Django Generate Barcode With Reportlab</title><published>2025-05-19T12:30:00+02:00</published><updated>2026-07-16T22:49:21+02:00</updated><summary type="text">Tutorial to build pages and pages of barcode for labeling stuffs</summary><content type="html" xml:base="https://fundor333.com/" xml:lang="en">
<![CDATA[<p>After <a class="a-post interlink-script" href="https://fundor333.com/post/2022/django-with-barcode-and-qrcode/"   target="_blank">Django With Barcode and Qrcode&nbsp;&nbsp;<i class="fa-whiteboard fa-semibold fa-link"></i></a>
 and <a class="a-post interlink-script" href="https://fundor333.com/post/2022/django-return-pdf-with-reportlab/"   target="_blank">Django Return Pdf With Reportlab&nbsp;&nbsp;<i class="fa-whiteboard fa-semibold fa-link"></i></a>
 I need something new in my Django server. I need a barcode generator for labeling stuffs.</p>
<h2 id="the-problem" class="no-underline ">
  <a href="#the-problem">
    <i class="fa-whiteboard fa-semibold fa-angle-right"></i>
    The problem
  </a>
  </h2>
<p>Every code is a solution to a pratical problem. In this case I need to make the barcode labels with text for keep an inventory.
The basic solution is generate a pdf/img file to print into sticker&rsquo;s paper and cut it after.</p>
<p><img  class="center-img u-photo "  src="barcode.png" alt="Barcode Example"></p>
<p>So, I need the data to convert into lable (the string on top to the barcode) and the barcode (or the qrcode) as in the screenshot, so I wrote this code for do it for pages and ready to print and stick it all around the world!</p>
<h2 id="code" class="no-underline ">
  <a href="#code">
    <i class="fa-whiteboard fa-semibold fa-angle-right"></i>
    Code
  </a>
  </h2>
<h3 id="the-view" class="no-underline ">
  <a href="#the-view">
    <i class="fa-whiteboard fa-semibold fa-angle-right"></i><i class="fa-whiteboard fa-semibold fa-angle-right"></i>
    The view
  </a>
  </h3>
<p>This code is the view for generating download link for the pdf with all the barcode.</p>

<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-python" data-lang="python"><span style="display:flex;"><span><span style="color:#f92672">from</span> django.views.generic <span style="color:#f92672">import</span> View
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">class</span> <span style="color:#a6e22e">ExampleBarcodePdf</span>(View):
</span></span><span style="display:flex;"><span>    bar_height <span style="color:#f92672">=</span> <span style="color:#66d9ef">None</span>
</span></span><span style="display:flex;"><span>    position_text_y <span style="color:#f92672">=</span> <span style="color:#66d9ef">None</span>
</span></span><span style="display:flex;"><span>    filename <span style="color:#f92672">=</span> <span style="color:#e6db74">&#34;ExampleBarCode.pdf&#34;</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">def</span> <span style="color:#a6e22e">get</span>(self, request, <span style="color:#f92672">*</span>args, <span style="color:#f92672">**</span>kwargs):
</span></span><span style="display:flex;"><span>      super()<span style="color:#f92672">.</span>get(request, <span style="color:#f92672">*</span>args, <span style="color:#f92672">**</span>kwargs)
</span></span><span style="display:flex;"><span>      response <span style="color:#f92672">=</span> HttpResponse(content_type<span style="color:#f92672">=</span><span style="color:#e6db74">&#34;application/pdf&#34;</span>)
</span></span><span style="display:flex;"><span>      response[<span style="color:#e6db74">&#34;Content-Disposition&#34;</span>] <span style="color:#f92672">=</span> (
</span></span><span style="display:flex;"><span>          <span style="color:#e6db74">&#39;attachment; filename=&#34;&#39;</span> <span style="color:#f92672">+</span> self<span style="color:#f92672">.</span>filename <span style="color:#f92672">+</span> <span style="color:#e6db74">&#39;&#34;&#39;</span>
</span></span><span style="display:flex;"><span>      )
</span></span><span style="display:flex;"><span>      a4p <span style="color:#f92672">=</span> A4PrinterBarcode()
</span></span><span style="display:flex;"><span>      pdf <span style="color:#f92672">=</span> a4p<span style="color:#f92672">.</span>get_pdf(
</span></span><span style="display:flex;"><span>          buffer<span style="color:#f92672">=</span>BytesIO(),
</span></span><span style="display:flex;"><span>          datas<span style="color:#f92672">=</span>[{barcode:<span style="color:#e6db74">&#34;0000000000000&#34;</span>, <span style="color:#e6db74">&#34;label&#34;</span>}, {<span style="color:#e6db74">&#34;999999999999&#34;</span>, <span style="color:#e6db74">&#34;other label&#34;</span>}],
</span></span><span style="display:flex;"><span>          bar_height<span style="color:#f92672">=</span>self<span style="color:#f92672">.</span>bar_height,
</span></span><span style="display:flex;"><span>          position_text_y<span style="color:#f92672">=</span>self<span style="color:#f92672">.</span>position_text_y,
</span></span><span style="display:flex;"><span>      )
</span></span><span style="display:flex;"><span>      response<span style="color:#f92672">.</span>write(pdf)
</span></span><span style="display:flex;"><span>      <span style="color:#66d9ef">return</span> response</span></span></code></pre></div><h3 id="the-pdf-generator" class="no-underline ">
  <a href="#the-pdf-generator">
    <i class="fa-whiteboard fa-semibold fa-angle-right"></i><i class="fa-whiteboard fa-semibold fa-angle-right"></i>
    The pdf generator
  </a>
  </h3>
<p>This is the &ldquo;printer&rdquo; the code for generate pdf.
After the import you find the constant with define the pdf.ß</p>

<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-python" data-lang="python"><span style="display:flex;"><span><span style="color:#f92672">from</span> reportlab.graphics.barcode.eanbc <span style="color:#f92672">import</span> Ean13BarcodeWidget
</span></span><span style="display:flex;"><span><span style="color:#f92672">from</span> reportlab.graphics.shapes <span style="color:#f92672">import</span> Drawing
</span></span><span style="display:flex;"><span><span style="color:#f92672">from</span> reportlab.graphics.shapes <span style="color:#f92672">import</span> String
</span></span><span style="display:flex;"><span><span style="color:#f92672">from</span> reportlab.lib.pagesizes <span style="color:#f92672">import</span> A4
</span></span><span style="display:flex;"><span><span style="color:#f92672">from</span> reportlab.pdfgen <span style="color:#f92672">import</span> canvas
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>PAGESIZE <span style="color:#f92672">=</span> A4
</span></span><span style="display:flex;"><span>NUM_LABELS_X <span style="color:#f92672">=</span> <span style="color:#ae81ff">3</span>
</span></span><span style="display:flex;"><span>NUM_LABELS_Y <span style="color:#f92672">=</span> <span style="color:#ae81ff">8</span>
</span></span><span style="display:flex;"><span>BAR_WIDTH <span style="color:#f92672">=</span> <span style="color:#ae81ff">1.5</span>
</span></span><span style="display:flex;"><span>BAR_HEIGHT <span style="color:#f92672">=</span> <span style="color:#ae81ff">51.0</span>
</span></span><span style="display:flex;"><span>TEXT_Y <span style="color:#f92672">=</span> <span style="color:#ae81ff">80</span>
</span></span><span style="display:flex;"><span>BARCODE_Y <span style="color:#f92672">=</span> <span style="color:#ae81ff">17</span>
</span></span><span style="display:flex;"><span>FONT_SIZE <span style="color:#f92672">=</span> <span style="color:#ae81ff">8</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>LABEL_WIDTH <span style="color:#f92672">=</span> PAGESIZE[<span style="color:#ae81ff">0</span>] <span style="color:#f92672">/</span> NUM_LABELS_X
</span></span><span style="display:flex;"><span>LABEL_HEIGHT <span style="color:#f92672">=</span> PAGESIZE[<span style="color:#ae81ff">1</span>] <span style="color:#f92672">/</span> NUM_LABELS_Y
</span></span><span style="display:flex;"><span>SHEET_TOP <span style="color:#f92672">=</span> PAGESIZE[<span style="color:#ae81ff">1</span>]
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">class</span> <span style="color:#a6e22e">A4PrinterBarcode</span>:
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">def</span> <span style="color:#a6e22e">generate_label</span>(
</span></span><span style="display:flex;"><span>        self,
</span></span><span style="display:flex;"><span>        ean13: str,
</span></span><span style="display:flex;"><span>        description: str,
</span></span><span style="display:flex;"><span>        label_w: float <span style="color:#f92672">=</span> <span style="color:#ae81ff">0.0</span>,
</span></span><span style="display:flex;"><span>        label_h: float <span style="color:#f92672">=</span> <span style="color:#ae81ff">0.0</span>,
</span></span><span style="display:flex;"><span>        bar_with: float <span style="color:#f92672">=</span> BAR_WIDTH,
</span></span><span style="display:flex;"><span>        bar_height: float <span style="color:#f92672">=</span> BAR_HEIGHT,
</span></span><span style="display:flex;"><span>        postion_text_y: float <span style="color:#f92672">=</span> TEXT_Y,
</span></span><span style="display:flex;"><span>        font_size: int <span style="color:#f92672">=</span> FONT_SIZE,
</span></span><span style="display:flex;"><span>    ) <span style="color:#f92672">-&gt;</span> Drawing:
</span></span><span style="display:flex;"><span>        <span style="color:#e6db74">&#34;&#34;&#34;
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">        Generate a drawing with EAN-13 barcode and descriptive text.
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">        :param ean13: The EAN-13 Code.
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">        :type ean13: str
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">        :param description: Short product description.
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">        :type description: str
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">        :return: Drawing with barcode and description
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">        :rtype: Drawing
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">        &#34;&#34;&#34;</span>
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">if</span> label_w <span style="color:#f92672">==</span> <span style="color:#ae81ff">0.0</span>:
</span></span><span style="display:flex;"><span>            label_w <span style="color:#f92672">=</span> A4[<span style="color:#ae81ff">0</span>] <span style="color:#f92672">/</span> NUM_LABELS_X
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">if</span> label_h <span style="color:#f92672">==</span> <span style="color:#ae81ff">0.0</span>:
</span></span><span style="display:flex;"><span>            label_h <span style="color:#f92672">=</span> A4[<span style="color:#ae81ff">1</span>] <span style="color:#f92672">/</span> NUM_LABELS_Y
</span></span><span style="display:flex;"><span>        text <span style="color:#f92672">=</span> String(
</span></span><span style="display:flex;"><span>            <span style="color:#ae81ff">0</span>,
</span></span><span style="display:flex;"><span>            postion_text_y,
</span></span><span style="display:flex;"><span>            description,
</span></span><span style="display:flex;"><span>            fontName<span style="color:#f92672">=</span><span style="color:#e6db74">&#34;Helvetica&#34;</span>,
</span></span><span style="display:flex;"><span>            fontSize<span style="color:#f92672">=</span>font_size,
</span></span><span style="display:flex;"><span>            textAnchor<span style="color:#f92672">=</span><span style="color:#e6db74">&#34;middle&#34;</span>,
</span></span><span style="display:flex;"><span>        )
</span></span><span style="display:flex;"><span>        text<span style="color:#f92672">.</span>x <span style="color:#f92672">=</span> label_w <span style="color:#f92672">/</span> <span style="color:#ae81ff">2</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>        barcode <span style="color:#f92672">=</span> Ean13BarcodeWidget(ean13)
</span></span><span style="display:flex;"><span>        barcode<span style="color:#f92672">.</span>barWidth <span style="color:#f92672">=</span> bar_with
</span></span><span style="display:flex;"><span>        barcode<span style="color:#f92672">.</span>barHeight <span style="color:#f92672">=</span> bar_height
</span></span><span style="display:flex;"><span>        _, _, bw, _ <span style="color:#f92672">=</span> barcode<span style="color:#f92672">.</span>getBounds()
</span></span><span style="display:flex;"><span>        barcode<span style="color:#f92672">.</span>x <span style="color:#f92672">=</span> (label_w <span style="color:#f92672">-</span> bw) <span style="color:#f92672">/</span> <span style="color:#ae81ff">2</span>  <span style="color:#75715e"># center barcode</span>
</span></span><span style="display:flex;"><span>        barcode<span style="color:#f92672">.</span>y <span style="color:#f92672">=</span> <span style="color:#ae81ff">18</span>  <span style="color:#75715e"># spacing from label bottom (pt)</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>        label_drawing <span style="color:#f92672">=</span> Drawing(label_w, label_h)
</span></span><span style="display:flex;"><span>        label_drawing<span style="color:#f92672">.</span>add(text)
</span></span><span style="display:flex;"><span>        label_drawing<span style="color:#f92672">.</span>add(barcode)
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">return</span> label_drawing
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">def</span> <span style="color:#a6e22e">get_pdf</span>(
</span></span><span style="display:flex;"><span>        self,
</span></span><span style="display:flex;"><span>        buffer,
</span></span><span style="display:flex;"><span>        datas: list,
</span></span><span style="display:flex;"><span>        bar_height: float <span style="color:#f92672">=</span> <span style="color:#66d9ef">None</span>,
</span></span><span style="display:flex;"><span>        position_text_y: float <span style="color:#f92672">=</span> <span style="color:#66d9ef">None</span>,
</span></span><span style="display:flex;"><span>    ) <span style="color:#f92672">-&gt;</span> bytes:
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">if</span> bar_height <span style="color:#f92672">is</span> <span style="color:#66d9ef">None</span> <span style="color:#f92672">or</span> bar_height <span style="color:#f92672">&lt;</span> <span style="color:#ae81ff">0</span>:
</span></span><span style="display:flex;"><span>            bar_height <span style="color:#f92672">=</span> BAR_HEIGHT
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">if</span> position_text_y <span style="color:#f92672">is</span> <span style="color:#66d9ef">None</span> <span style="color:#f92672">or</span> position_text_y <span style="color:#f92672">&lt;</span> <span style="color:#ae81ff">0</span>:
</span></span><span style="display:flex;"><span>            position_text_y <span style="color:#f92672">=</span> TEXT_Y
</span></span><span style="display:flex;"><span>        p <span style="color:#f92672">=</span> canvas<span style="color:#f92672">.</span>Canvas(buffer)
</span></span><span style="display:flex;"><span>        j <span style="color:#f92672">=</span> <span style="color:#ae81ff">0</span>
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">for</span> _ <span style="color:#f92672">in</span> range(len(datas) <span style="color:#f92672">//</span> (NUM_LABELS_X <span style="color:#f92672">*</span> NUM_LABELS_Y) <span style="color:#f92672">+</span> <span style="color:#ae81ff">1</span>):
</span></span><span style="display:flex;"><span>            <span style="color:#66d9ef">for</span> u <span style="color:#f92672">in</span> range(<span style="color:#ae81ff">0</span>, NUM_LABELS_Y):
</span></span><span style="display:flex;"><span>                <span style="color:#66d9ef">for</span> i <span style="color:#f92672">in</span> range(<span style="color:#ae81ff">0</span>, NUM_LABELS_X):
</span></span><span style="display:flex;"><span>                    <span style="color:#66d9ef">if</span> j <span style="color:#f92672">&lt;</span> len(datas):
</span></span><span style="display:flex;"><span>                        data <span style="color:#f92672">=</span> datas[j]
</span></span><span style="display:flex;"><span>                        cb <span style="color:#f92672">=</span> data<span style="color:#f92672">.</span>barcode
</span></span><span style="display:flex;"><span>                        desc <span style="color:#f92672">=</span> data<span style="color:#f92672">.</span>label
</span></span><span style="display:flex;"><span>                        <span style="color:#66d9ef">try</span>:
</span></span><span style="display:flex;"><span>                            label <span style="color:#f92672">=</span> self<span style="color:#f92672">.</span>generate_label(
</span></span><span style="display:flex;"><span>                                ean13<span style="color:#f92672">=</span>cb,
</span></span><span style="display:flex;"><span>                                description<span style="color:#f92672">=</span>desc,
</span></span><span style="display:flex;"><span>                                bar_height<span style="color:#f92672">=</span>bar_height,
</span></span><span style="display:flex;"><span>                                postion_text_y<span style="color:#f92672">=</span>position_text_y,
</span></span><span style="display:flex;"><span>                            )
</span></span><span style="display:flex;"><span>                            x <span style="color:#f92672">=</span> i <span style="color:#f92672">*</span> LABEL_WIDTH
</span></span><span style="display:flex;"><span>                            y <span style="color:#f92672">=</span> SHEET_TOP <span style="color:#f92672">-</span> LABEL_HEIGHT <span style="color:#f92672">-</span> u <span style="color:#f92672">*</span> LABEL_HEIGHT
</span></span><span style="display:flex;"><span>                            label<span style="color:#f92672">.</span>drawOn(p, x, y)
</span></span><span style="display:flex;"><span>                        <span style="color:#66d9ef">except</span> <span style="color:#a6e22e">AttributeError</span>:
</span></span><span style="display:flex;"><span>                            <span style="color:#66d9ef">pass</span>
</span></span><span style="display:flex;"><span>                        j <span style="color:#f92672">+=</span> <span style="color:#ae81ff">1</span>
</span></span><span style="display:flex;"><span>            p<span style="color:#f92672">.</span>showPage()
</span></span><span style="display:flex;"><span>        p<span style="color:#f92672">.</span>save()
</span></span><span style="display:flex;"><span>        pdf <span style="color:#f92672">=</span> buffer<span style="color:#f92672">.</span>getvalue()
</span></span><span style="display:flex;"><span>        buffer<span style="color:#f92672">.</span>close()
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">return</span> pdf</span></span></code></pre></div><h2 id="so-how-do-a4printerbarcode-work-" class="no-underline ">
  <a href="#so-how-do-a4printerbarcode-work-">
    <i class="fa-whiteboard fa-semibold fa-angle-right"></i>
    So how do <em>A4PrinterBarcode</em> work ?
  </a>
  </h2>
<p>The main concept of this class is to generate the &ldquo;labels&rdquo; (barcode and text) and put them into a grid pattern.
So we have two function:</p>
<ul>
<li><em>generate_label</em> generate the single &ldquo;label&rdquo;, one of the time</li>
<li><em>get_pdf</em> generate the pdf putting the &ldquo;labels&rdquo; in a grid pattern</li>
</ul>
<p>If you need, this class can be used without Django, in something like a <a class="a-post interlink-script" href="https://fundor333.com/post/2023/why-i-stop-making-script-and-start-to-make-bash-terminal-commands/"   target="_blank">tool for terminal&nbsp;&nbsp;<i class="fa-whiteboard fa-semibold fa-link"></i></a>
</p>
]]></content></entry><entry><id>tag:fundor333.com,2025:/post/2025/activitypub-vs-webmention-do-you-need-them/</id><link rel="alternate" href="https://fundor333.com/post/2025/activitypub-vs-webmention-do-you-need-them/"/><title>Activitypub vs Webmention Do You Need Them ?</title><published>2025-05-16T07:23:27+02:00</published><updated>2026-07-16T22:49:21+02:00</updated><summary type="text">Some personal thinking about webmention and activitypub and how to use/combine them</summary><content type="html" xml:base="https://fundor333.com/" xml:lang="en">
<![CDATA[<p>I have a lot of article about webmention because I implement them on my site/blog. And I use them ad comment, like sistem and more. But more I read about ActivityPub and the Feedverse more I thing it can be a good think to implement it insite your site for your content and for share to the Feedverse.</p>
<h2 id="why-do-it" class="no-underline ">
  <a href="#why-do-it">
    <i class="fa-whiteboard fa-semibold fa-angle-right"></i>
    Why do it?
  </a>
  </h2>
<p>One of the best arguments for having a personal ActivityPub site/server is you having a unique identity, don&rsquo;t fragmenting your identity<sup id="fnref:1"><a href="#fn:1" class="footnote-ref" role="doc-noteref">1</a></sup> on multiple Feedverse accounts.</p>
<p>But I implemented Webmention and stuff like <a class="a-post interlink-script" href="https://brid.gy/"   target="_blank">Brid&nbsp;&nbsp;<i class="fa-whiteboard fa-semibold fa-link"></i></a>
 for having the likes, comments and all the stuff I have in the ActivityPub about my posts. So why I need to do it?</p>
<p>If I need more reference to your post/article on the Feedverse, Mastodon has a function<sup id="fnref:2"><a href="#fn:2" class="footnote-ref" role="doc-noteref">2</a></sup> for show your account under your link making a link to your profile. It also easy to set up and some platform has a plugin for it (like for Wordpress) or easy articole online for your favorite platfome (for example this is for <a class="a-post interlink-script" href="https://onemanandhisblog.com/2024/10/adding-a-mastodon-author-to-ghost/"   target="_blank">Ghost&nbsp;&nbsp;<i class="fa-whiteboard fa-semibold fa-link"></i></a>
).</p>
<p>But if you aren&rsquo;t in the FeedVerse you are loosing in a way in to a social media moviment which is groing with major players studing and testing the ground (Meta, Tumblr, with also X/Twitter looking without public testing) and more and more time pass, more and more service integrate the ActivityPub in their social/site/service.</p>
<p>I also have a lot of attention from the tech blogger, where if you don&rsquo;t write about excitement<sup id="fnref:3"><a href="#fn:3" class="footnote-ref" role="doc-noteref">3</a></sup> you are writing about how to implement ActivityPub on your site[^4].</p>
<h2 id="and-so-i-need-to-integrate-this-new-stuff-into-my-site" class="no-underline ">
  <a href="#and-so-i-need-to-integrate-this-new-stuff-into-my-site">
    <i class="fa-whiteboard fa-semibold fa-angle-right"></i>
    And so? I need to integrate this new stuff into my site?
  </a>
  </h2>
<p>No and yes. If you want a presence in the FeedVerse you need to be active also there but no with a integration with the ActivityPub protocol: you can share it like the &ldquo;old days&rdquo;.</p>
<p>Also having a ActivityPub implementation somewhere is a resource draining server so you need to think about how much money and time you want to spend on it.</p>
<p>In the end Webmention and ActivityPub are two way to have more interaction with your site but you also need to now which interaction is better for your site.</p>
<div class="footnotes" role="doc-endnotes">
<hr>
<ol>
<li id="fn:1">
<p>Two article about it <a class="a-post interlink-script" href="[Federated/Fragmentated]%28https://cogdogblog.com/2024/11/federated-fragmentated/?ref=jadin.me%29"  >Federated/Fragmentated</a>
 and <a class="a-post interlink-script" href="https://jadin.me/who-is-this/"   target="_blank">Who is this?&nbsp;&nbsp;<i class="fa-whiteboard fa-semibold fa-link"></i></a>
&#160;<a href="#fnref:1" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
<li id="fn:2">
<p>Post about it <a class="a-post interlink-script" href="https://blog.joinmastodon.org/2024/07/highlighting-journalism-on-mastodon/"   target="_blank">Highlighting journalism on Mastodon&nbsp;&nbsp;<i class="fa-whiteboard fa-semibold fa-link"></i></a>
&#160;<a href="#fnref:2" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
<li id="fn:3">
<p>Some article about excitement <a class="a-post interlink-script" href="https://jadin.me/why-im-excited-about-ghost-getting-activitypub-support/"   target="_blank">Why I&rsquo;m excited about Ghost getting ActivityPub support&nbsp;&nbsp;<i class="fa-whiteboard fa-semibold fa-link"></i></a>
 <a class="a-post interlink-script" href="https://onemanandhisblog.com/2025/03/the-federated-one-man-his-blog/"   target="_blank">The federated One Man &amp; His Blog&nbsp;&nbsp;<i class="fa-whiteboard fa-semibold fa-link"></i></a>

[^4] For example this article <a class="a-post interlink-script" href="https://maho.dev/2025/03/a-guide-to-implementing-activitypub-in-a-static-site-or-any-website-q1-2025-updates/"   target="_blank">A Guide to Implementing ActivityPub in a Static Site (or Any Website) - Q1 2025 Updates&nbsp;&nbsp;<i class="fa-whiteboard fa-semibold fa-link"></i></a>
&#160;<a href="#fnref:3" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
</ol>
</div>
]]></content></entry><entry><id>tag:fundor333.com,2025:/post/2025/csv-from-django/</id><link rel="alternate" href="https://fundor333.com/post/2025/csv-from-django/"/><title>Csv From Django</title><published>2025-04-18T12:23:09+02:00</published><updated>2026-07-16T22:49:21+02:00</updated><summary type="text">A little class view for return CSV</summary><content type="html" xml:base="https://fundor333.com/" xml:lang="en">
<![CDATA[<p>Some time you need to export a file into a specific format for some use like upload to the old system.
In this case I need to have a CSV file which another software fill.</p>
<h2 id="the-code" class="no-underline ">
  <a href="#the-code">
    <i class="fa-whiteboard fa-semibold fa-angle-right"></i>
    The code
  </a>
  </h2>
<p>I wrote a ClassView for this case, this class. <sup id="fnref:1"><a href="#fn:1" class="footnote-ref" role="doc-noteref">1</a></sup></p>

<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-python" data-lang="python"><span style="display:flex;"><span><span style="color:#66d9ef">class</span> <span style="color:#a6e22e">CsvCarsDownload</span>(View):
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">def</span> <span style="color:#a6e22e">get</span>(self, request, <span style="color:#f92672">*</span>args, <span style="color:#f92672">**</span>kwargs):
</span></span><span style="display:flex;"><span>        response <span style="color:#f92672">=</span> HttpResponse(content_type<span style="color:#f92672">=</span><span style="color:#e6db74">&#34;text/csv&#34;</span>)
</span></span><span style="display:flex;"><span>        response[<span style="color:#e6db74">&#34;Content-Disposition&#34;</span>] <span style="color:#f92672">=</span> <span style="color:#e6db74">&#39;attachment; filename=&#34;cars.csv&#34;&#39;</span>
</span></span><span style="display:flex;"><span>        my_dict <span style="color:#f92672">=</span> [{
</span></span><span style="display:flex;"><span>          <span style="color:#e6db74">&#34;brand&#34;</span>: <span style="color:#e6db74">&#34;Ford&#34;</span>,
</span></span><span style="display:flex;"><span>          <span style="color:#e6db74">&#34;model&#34;</span>: <span style="color:#e6db74">&#34;Mustang&#34;</span>,
</span></span><span style="display:flex;"><span>          <span style="color:#e6db74">&#34;year&#34;</span>: <span style="color:#ae81ff">1964</span>
</span></span><span style="display:flex;"><span>        }]
</span></span><span style="display:flex;"><span>        writer <span style="color:#f92672">=</span> csv<span style="color:#f92672">.</span>DictWriter(
</span></span><span style="display:flex;"><span>            response, dialect<span style="color:#f92672">=</span><span style="color:#e6db74">&#34;excel&#34;</span>, fieldnames<span style="color:#f92672">=</span>my_dict[<span style="color:#ae81ff">0</span>]<span style="color:#f92672">.</span>keys()
</span></span><span style="display:flex;"><span>        )
</span></span><span style="display:flex;"><span>        writer<span style="color:#f92672">.</span>writeheader()
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">for</span> element <span style="color:#f92672">in</span> my_dict:
</span></span><span style="display:flex;"><span>          writer<span style="color:#f92672">.</span>writerow(element)
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">return</span> response</span></span></code></pre></div><p>You can change the type of the the CSV changing the <strong>dialect</strong> with one of the type of the CSV dialect (excel, excel_tab, unix_dialect) and changing the <strong>my_dict</strong> with any type of list of dict.</p>
<p>With this code you can use any Class Mixin from others module for add other functions like permission supports or loggeer configurations.</p>
<div class="footnotes" role="doc-endnotes">
<hr>
<ol>
<li id="fn:1">
<p>I don&rsquo;t like coding functional view so I only code ClassViews&#160;<a href="#fnref:1" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
</ol>
</div>
]]></content></entry><entry><id>tag:fundor333.com,2025:/post/2025/re-using-re-in-blog-titles/</id><link rel="alternate" href="https://fundor333.com/post/2025/re-using-re-in-blog-titles/"/><title>Re:Using 'Re:' in Blog Titles</title><published>2025-04-14T21:00:21+02:00</published><updated>2026-07-16T22:49:21+02:00</updated><summary type="text">Blogpost about how to write a post response</summary><content type="html" xml:base="https://fundor333.com/" xml:lang="en">
<![CDATA[<p>Following the post from <a class="a-post interlink-script" href="https://rubenerd.com/using-re-in-blog-titles/"   target="_blank">Ruben&nbsp;&nbsp;<i class="fa-whiteboard fa-semibold fa-link"></i></a>
 I start imitating this idea and expand on it.</p>
<blockquote>
<p>&ldquo;Imitation is the sincerest form of flattery that mediocrity can pay to greatness.&rdquo;</p>
<p>Oscar Wilde</p>
</blockquote>
<p>The basic idea come from a post by <a class="a-post interlink-script" href="https://brandons-journal.com/re-im-part-of-the-problem/"   target="_blank">Brandon&rsquo;s Journal&nbsp;&nbsp;<i class="fa-whiteboard fa-semibold fa-link"></i></a>
 where Brandon response to an article and use the <strong>Re:</strong> prefix, like a email threads in the title of the post&hellip;</p>
<p>And I add a microformat following the IndieWeb stuff for the response tags.
So my post which are a &ldquo;Re:&rdquo; will have a <strong>u-in-reply-to</strong> in the class of the links for implementing the IndieWeb, like in this article.</p>
]]></content></entry><entry><id>tag:fundor333.com,2025:/post/2025/pages-you-need-in-your-blog/</id><link rel="alternate" href="https://fundor333.com/post/2025/pages-you-need-in-your-blog/"/><title>Pages You Need in Your Blog</title><published>2025-04-06T13:42:47+02:00</published><updated>2026-07-16T22:49:21+02:00</updated><summary type="text">There are some page you need to have in your blog if your blog is for human</summary><content type="html" xml:base="https://fundor333.com/" xml:lang="en">
<![CDATA[<p>More and more blog I read and more and more I find that a lot of the dev blog and personal blog on the web has a lot of common pages but not the old <em>About</em> or <em>Contacts</em> so I make this list of interesting pages types.</p>
<h2 id="blogroll" class="no-underline ">
  <a href="#blogroll">
    <i class="fa-whiteboard fa-semibold fa-angle-right"></i>
    Blogroll
  </a>
  </h2>
<p>One of the best page I find on a blog. This is a page where the blogger show a link of site/blog (a html page or a Opml file) of interesting stuff.</p>
<p>I find iteresting because I can have an idea about the blogger interest and I can find new and different source of post.</p>
<p>Mine is <a class="a-post interlink-script" href="/blogroll"  >here</a>
</p>
<h2 id="connect" class="no-underline ">
  <a href="#connect">
    <i class="fa-whiteboard fa-semibold fa-angle-right"></i>
    Connect
  </a>
  </h2>
<p>Half of the old <em>About Us</em> page. In this page the blog put all the link needed to follow and/or contact the author on the classic way (email,&hellip;) and the new social way (mastodon, twitter, etc&hellip;)</p>
<p>Mine is <a class="a-post interlink-script" href="/connect"  >here</a>
</p>
<h2 id="feeds" class="no-underline ">
  <a href="#feeds">
    <i class="fa-whiteboard fa-semibold fa-angle-right"></i>
    Feeds
  </a>
  </h2>
<p>Inspired by <a class="a-post interlink-script" href="https://marcus.io/blog/making-rss-more-visible-again-with-slash-feeds"   target="_blank">this post&nbsp;&nbsp;<i class="fa-whiteboard fa-semibold fa-link"></i></a>
 the <em>feeds</em> page is the most functional page for user on a site.
This page has all the feeds&rsquo; links for the blog and other service the blogger is showing. Sometime some feeds aren&rsquo;t from the blog but from other platform of the blogger.</p>
<p>Mine is <a class="a-post interlink-script" href="/feeds"  >here</a>
</p>
<h2 id="now" class="no-underline ">
  <a href="#now">
    <i class="fa-whiteboard fa-semibold fa-angle-right"></i>
    Now
  </a>
  </h2>
<p>The other half of the <em>About Us</em> page. It come from an <a class="a-post interlink-script" href="https://nownownow.com/about"   target="_blank">idea&nbsp;&nbsp;<i class="fa-whiteboard fa-semibold fa-link"></i></a>
 about having a space (in this case a page on a site) about what are you doing with your life and interest.
In this way you can also use it for showing off your little project or have a space for fundraising your project.</p>
<p>Sometime I search on Google now pages for find new project and others things.</p>
<p>Mine is <a class="a-post interlink-script" href="/now"  >here</a>
</p>
<h2 id="uses" class="no-underline ">
  <a href="#uses">
    <i class="fa-whiteboard fa-semibold fa-angle-right"></i>
    Uses
  </a>
  </h2>
<p>The strange page (for me). There is a <a class="a-post interlink-script" href="https://uses.tech/"   target="_blank">uses site&nbsp;&nbsp;<i class="fa-whiteboard fa-semibold fa-link"></i></a>
 where you can send your <em>Uses</em> link where you share what tech you use every day or for the project. In this way you can check what tech other people use and for what.</p>
<p>In this type of pages I love to check what kind of coding and photo set up they have.</p>
<p>Mine is <a class="a-post interlink-script" href="/uses"  >here</a>
</p>
<h2 id="so" class="no-underline ">
  <a href="#so">
    <i class="fa-whiteboard fa-semibold fa-angle-right"></i>
    So?
  </a>
  </h2>
<p>So I suggest to have some of this pages on your blog if you thing of your blog as a personal blog. It can be usefull for start a conversation online or for having a place to send people for answer about your works and your stuffs.</p>
]]></content></entry><entry><id>tag:fundor333.com,2025:/post/2025/an-easy-way-to-start-a-life-in-the-indieweb/</id><link rel="alternate" href="https://fundor333.com/post/2025/an-easy-way-to-start-a-life-in-the-indieweb/"/><title>An Easy Way to Start a Life in the IndieWeb</title><published>2025-01-31T12:46:00+01:00</published><updated>2026-07-16T22:49:21+02:00</updated><summary type="text">A tool to start a life on the IndieWeb leaving the social media behind</summary><content type="html" xml:base="https://fundor333.com/" xml:lang="en">
<![CDATA[<p>There are more and more post about the Indieweb and what you can find in a indiweb site/blog<sup id="fnref:1"><a href="#fn:1" class="footnote-ref" role="doc-noteref">1</a></sup> but I didn&rsquo;t find an easy tutorial for starting with IndiWeb. But first:
What is the IndieWeb?</p>
<h2 id="indieweb-the-definition" class="no-underline ">
  <a href="#indieweb-the-definition">
    <i class="fa-whiteboard fa-semibold fa-angle-right"></i>
    IndieWeb the definition
  </a>
  </h2>
<p>I thing that, to explain IndieWeb we need two definition: one from a more &ldquo;anthropological&rdquo; point of view and one from a &ldquo;tecnical/it&rdquo; point of view</p>
<h3 id="anthropological-definition" class="no-underline ">
  <a href="#anthropological-definition">
    <i class="fa-whiteboard fa-semibold fa-angle-right"></i><i class="fa-whiteboard fa-semibold fa-angle-right"></i>
    Anthropological definition
  </a>
  </h3>
<blockquote>
<p>The #IndieWeb is for everyone, everyone who wants to be part of the world-wide-web of interconnected people. The social internet of people, a network of networks of people, connected peer-to-peer in human-scale groups, communities of locality and affinity.</p>
</blockquote>
<h3 id="tecnicalit-definition" class="no-underline ">
  <a href="#tecnicalit-definition">
    <i class="fa-whiteboard fa-semibold fa-angle-right"></i><i class="fa-whiteboard fa-semibold fa-angle-right"></i>
    Tecnical/It definition
  </a>
  </h3>
<blockquote>
<p>The IndieWeb is a community of independent and personal websites connected by open standards, based on the principles of: owning your domain and using it as your primary online identity, publishing on your own site first (optionally elsewhere), and owning your content.</p>
</blockquote>
<h3 id="so-why-i-need-to-be-in-the-indieweb" class="no-underline ">
  <a href="#so-why-i-need-to-be-in-the-indieweb">
    <i class="fa-whiteboard fa-semibold fa-angle-right"></i><i class="fa-whiteboard fa-semibold fa-angle-right"></i>
    So, why I need to be in the Indieweb?
  </a>
  </h3>
<p><img  class="center-img u-photo "  src="pill.png" alt="red pill blue pill"></p>
<p>You don&rsquo;t need to be in. You need to choose <strong>red pill</strong> or <strong>blue pill</strong></p>
<p><strong>Red Pill</strong>: If you want to have a look inside the mirror and, because you have something to say online, you need to have a personal domain and a space where you have the control and own your content and</p>
<blockquote>
<p>You stay in Wonderland and I show you how deep the rabbit hole goes</p>
</blockquote>
<p><strong>Blue Pill</strong>: You keep the social network account you have and</p>
<blockquote>
<p>The story ends, you wake up in your bed and believe whatever you want to believe</p>
</blockquote>
<h2 id="red-pill-now-what" class="no-underline ">
  <a href="#red-pill-now-what">
    <i class="fa-whiteboard fa-semibold fa-angle-right"></i>
    Red Pill, now what?
  </a>
  </h2>
<p>There are multiple things to do and tools to choose for you if you want to start with IndieWeb so I suggest a site which help you understand what you need to do and what to choose.</p>
<p>This site is <a class="a-post interlink-script" href="https://unplatform.fromthesuperhighway.com/"   target="_blank">Unplatform&nbsp;&nbsp;<i class="fa-whiteboard fa-semibold fa-link"></i></a>
 from the people of the <a class="a-post interlink-script" href="fromthesuperhighway.com"  >fromthesuperhighway</a>
.</p>
<p>This is a simple way to understand and start with the <strong>red pill</strong> and with a complete explanation for every tool you choose so you can have the easyest way to became an IndieWeb user.</p>
<p>Have a nice IndieWeb expirience</p>
<div class="footnotes" role="doc-endnotes">
<hr>
<ol>
<li id="fn:1">
<p><a class="a-post interlink-script" href="https://indieweb.org/"   target="_blank">Indiweb&nbsp;&nbsp;<i class="fa-whiteboard fa-semibold fa-link"></i></a>
, <a class="a-post interlink-script" href="https://news.ycombinator.com/item?id=26950009"   target="_blank">The IndieWeb is a people-focused alternative to the “corporate web”&nbsp;&nbsp;<i class="fa-whiteboard fa-semibold fa-link"></i></a>
, <a class="a-post interlink-script" href="https://blog.rubenwardy.com/2023/10/10/hello-indieweb/"   target="_blank">I have joined the IndieWeb&nbsp;&nbsp;<i class="fa-whiteboard fa-semibold fa-link"></i></a>
, <a class="a-post interlink-script" href="https://darthmall.net/2024/indieweb-is-for-devs/"   target="_blank">The IndieWeb is for Developers&nbsp;&nbsp;<i class="fa-whiteboard fa-semibold fa-link"></i></a>
, <a class="a-post interlink-script" href="https://werd.io/2024/the-indieweb-is-for-everyone"   target="_blank">The indieweb is for everyone&nbsp;&nbsp;<i class="fa-whiteboard fa-semibold fa-link"></i></a>
&#160;<a href="#fnref:1" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
</ol>
</div>
]]></content></entry><entry><id>tag:fundor333.com,2025:/post/2025/substack-vs-medium-what-is-better-for-a-coder/</id><link rel="alternate" href="https://fundor333.com/post/2025/substack-vs-medium-what-is-better-for-a-coder/"/><title>Substack vs Medium: What Is Better for a Coder?</title><published>2025-01-27T12:02:52+01:00</published><updated>2026-07-16T22:49:21+02:00</updated><summary type="text">If you are a developer where do you blog better? Medium or Substack?</summary><content type="html" xml:base="https://fundor333.com/" xml:lang="en">
<![CDATA[<p>I am first and most a Developer and a Coder and I think that coding and developing software (site, app, AI, etc&hellip;) need to be a share experience.
So I think a dev must share knowledge in the web. Somebody help people on StackOverflow and someone (like me) blogs.</p>
<p>In the last <em>X</em> years<sup id="fnref:1"><a href="#fn:1" class="footnote-ref" role="doc-noteref">1</a></sup> I understand the important of blogging and why a dev or a coder need to write a blog/newsletter/magazine about what is doing<sup id="fnref:2"><a href="#fn:2" class="footnote-ref" role="doc-noteref">2</a></sup> and how big time sink is developing and maintaining a custom blog so I have this question:</p>
<blockquote>
<p>For sharing Dev/Coding experiences is better Medium or StackOverflow?<sup id="fnref:3"><a href="#fn:3" class="footnote-ref" role="doc-noteref">3</a></sup></p>
</blockquote>
<h2 id="we-need-a-generic-dev" class="no-underline ">
  <a href="#we-need-a-generic-dev">
    <i class="fa-whiteboard fa-semibold fa-angle-right"></i>
    We need a &ldquo;generic&rdquo; Dev!
  </a>
  </h2>
<p>This is <em>Bob</em>. <em>Bob</em> is a BackEnd Developer, a Python Developer and he is learning some FrontEnd stuffs. So he wants to write about what he knows, what is learning and his doubts.</p>
<p><img  class="center-img u-photo "  src="bob.png" alt="Bob Avatar"></p>
<h3 id="what-a-dev-need-to-share-in-a-post" class="no-underline ">
  <a href="#what-a-dev-need-to-share-in-a-post">
    <i class="fa-whiteboard fa-semibold fa-angle-right"></i><i class="fa-whiteboard fa-semibold fa-angle-right"></i>
    What a Dev need to share in a post
  </a>
  </h3>
<p><em>Bob</em> need to share fragments of the code he writes, some screenshot (images) and a lot of texts. The latest are a simple request because it is the minimum requirements for all the blogging platform.</p>
<p>The code part is the &ldquo;difficult&rdquo; one.</p>
<p>The best situation is if the code is highlighted something like this</p>

<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-python" data-lang="python"><span style="display:flex;"><span>print(<span style="color:#e6db74">&#34;Hello World!&#34;</span>)</span></span></code></pre></div><p>and the platform need to support all the types of the files <em>Bob</em>&rsquo;s code but we only need the highlight for the languages&hellip;
If <em>Bob</em> needs to blog about <em>Cobol</em> or <em>Pascal</em><sup id="fnref:4"><a href="#fn:4" class="footnote-ref" role="doc-noteref">4</a></sup></p>
<h3 id="customing-and-theming" class="no-underline ">
  <a href="#customing-and-theming">
    <i class="fa-whiteboard fa-semibold fa-angle-right"></i><i class="fa-whiteboard fa-semibold fa-angle-right"></i>
    Customing and theming
  </a>
  </h3>
<p><em>Bob</em> need to have a solid site/blog with a mobile and a desktop layout (more and more people read blog only with the tablet or the phone) and he need to make no changes or as little as possible for making HIS SITE/BLOG.</p>
<p>He also need a notification system for the followers (newsletters, feed, app with notification, &hellip;) and a SEO integration (analytics, meta, etc&hellip;) for becoming someone on the web.</p>
<p>Less edit he must do for posting better the platform is.</p>
<h3 id="money" class="no-underline ">
  <a href="#money">
    <i class="fa-whiteboard fa-semibold fa-angle-right"></i><i class="fa-whiteboard fa-semibold fa-angle-right"></i>
    Money
  </a>
  </h3>
<p><em>Bob</em> is a developer for money so he doesn&rsquo;t want to spend money so&hellip; The all budget is 10€ (all needed for the domain) so the platform is a good one if it is free but is better if <em>pay</em> <em>Bob</em>.</p>
<p>So he needs a free platform<sup id="fnref:5"><a href="#fn:5" class="footnote-ref" role="doc-noteref">5</a></sup> and some way to make money from the posts (advertising, subscriptions, etc&hellip;)</p>
<p><img  class="center-img u-photo "  src="newspaper.png" alt="NewsPapers"></p>
<h2 id="and-now-the-platforms" class="no-underline ">
  <a href="#and-now-the-platforms">
    <i class="fa-whiteboard fa-semibold fa-angle-right"></i>
    And now the platforms
  </a>
  </h2>
<p>Now we know what <em>Bob</em> needs and wants, we find some platforms.</p>
<p>Wordpress, Jekill, Ghost, GoHugo and some other platforms aren&rsquo;t the &ldquo;right one&rdquo; because they aren&rsquo;t a &ldquo;out of the box&rdquo; expirience. You need to customized it and you need to have time for the updating of the platform soo we have SubStack and Medium as the platform.</p>
<h3 id="medium" class="no-underline ">
  <a href="#medium">
    <i class="fa-whiteboard fa-semibold fa-angle-right"></i><i class="fa-whiteboard fa-semibold fa-angle-right"></i>
    Medium
  </a>
  </h3>
<p>The old one, <em>Medium</em> is the platform which is trying to become a blogging space for magazine and journal&rsquo; blogs.
He is online from the 2012 and have all the need for a writer, with tool for automatic sharing, automatic posting and seo tools Medium is a complete platform.</p>
<h3 id="substack" class="no-underline ">
  <a href="#substack">
    <i class="fa-whiteboard fa-semibold fa-angle-right"></i><i class="fa-whiteboard fa-semibold fa-angle-right"></i>
    SubStack
  </a>
  </h3>
<p>The new one, <em>SubStack</em> is the platform with two faces: one is a blogging space and the other is the mail-list space.
<em>SubStack</em> out of the box way to work is a mail list for your followers, but the site part is not a bad one. It has automatic sharing, automatic posting and a micro-blogging part. But for SEO and promotion it all on you.</p>
<p>It also has one of the better subscribe platform of the web, where you can set some post to <em>pay to read</em> and some <em>free to read</em>.</p>
<h3 id="some-other-considerations" class="no-underline ">
  <a href="#some-other-considerations">
    <i class="fa-whiteboard fa-semibold fa-angle-right"></i><i class="fa-whiteboard fa-semibold fa-angle-right"></i>
    Some other considerations
  </a>
  </h3>
<p>After all this considerations I need to show somethings behind the curtain : Medium has a lot of negative attention[^mediumproblem] because they have a lot of low quality post<sup id="fnref:6"><a href="#fn:6" class="footnote-ref" role="doc-noteref">6</a></sup> and SubStack has its share of problem with the paywall on the newsletters and some problems for the authors.<sup id="fnref:7"><a href="#fn:7" class="footnote-ref" role="doc-noteref">7</a></sup></p>
<p><img  class="center-img u-photo "  src="oz.png" alt="Oz"></p>
<p>In my opinion, if you want to blog about what are you doing, do it and this two platform can be a good starting point for start with your blogging journey but if it become something more you need to invest time in something more tailor to your need and understand what you need and what the platform give you.</p>
<p>If someone make me choose one between Medium and SubStack, I will choose SubStack because I love the idea of having a newsletters but I also feel the limitation of the close platform, bacause I had years and years of blogging on platform I hacked every way.</p>
<p>For example this blog is a GoHugo installation with a <em>out of the box</em> theme but I put so many changing in the code I have something more similar of the Monster of Frankenstein than a well coded theme&hellip;</p>
<div class="footnotes" role="doc-endnotes">
<hr>
<ol>
<li id="fn:1">
<p>Where <em>X</em> is a big but not too big number&#160;<a href="#fnref:1" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
<li id="fn:2">
<p>This is also explained in one of my <a class="a-post interlink-script" href="https://fundor333.com/photos/2025/square-square-square-and-square/"  >old post</a>
&#160;<a href="#fnref:2" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
<li id="fn:3">
<p>This is my blog/webspace so I say <em>my opinion</em> (coder for more than 5 year)&#160;<a href="#fnref:3" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
<li id="fn:4">
<p>Cobol and Pascal are two of the oldest languages and almost every highlighter in a generic blogging platform don&rsquo;t support them, so you need to use a more professional blogging platform and lost time with the custumizations&#160;<a href="#fnref:4" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
<li id="fn:5">
<p>Some function can be hidden by a paywall but if all the <em>needed</em> function are free, the platform is a good one&#160;<a href="#fnref:5" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
<li id="fn:6">
<p><a class="a-post interlink-script" href="https://news.ycombinator.com/item?id=24942037"   target="_blank">Please stop writing tutorials/tech articles on Medium&nbsp;&nbsp;<i class="fa-whiteboard fa-semibold fa-link"></i></a>
&#160;<a href="#fnref:6" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
<li id="fn:7">
<p><a class="a-post interlink-script" href="https://janefriedman.com/substack-is-both-great-and-terrible-for-authors/"   target="_blank">Substack Is Both Great and Terrible for Authors
&nbsp;&nbsp;<i class="fa-whiteboard fa-semibold fa-link"></i></a>
&#160;<a href="#fnref:7" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
</ol>
</div>
]]></content></entry><entry><id>tag:fundor333.com,2025:/post/2025/github-action-for-syndication-links/</id><link rel="alternate" href="https://fundor333.com/post/2025/github-action-for-syndication-links/"/><title>Github Action for Syndication Links</title><published>2025-01-23T13:22:54+01:00</published><updated>2026-07-16T22:49:21+02:00</updated><summary type="text">How I have syndications'links fill by the machine</summary><content type="html" xml:base="https://fundor333.com/" xml:lang="en">
<![CDATA[<p>A lot of time ago I implement the Webmention in my site following a lot of blogpost.</p>
<p>One of them was a bigger ispiration for my implementation<sup id="fnref:1"><a href="#fn:1" class="footnote-ref" role="doc-noteref">1</a></sup> and I have some chat with the author of the post over Mastodon for the implementation of the syndications link in a static site<sup id="fnref:2"><a href="#fn:2" class="footnote-ref" role="doc-noteref">2</a></sup> and how to implement it.</p>








    
    
        
        
    

    
        <div class="toot">
            <div class="toot-header">
                <a class="toot-profile" href="https://mastodon.social/@fundor333" rel="noopener">
                    <img src="https://files.mastodon.social/accounts/avatars/000/030/873/original/67f41e16a70f9ef6.png"
                         alt="Avatar for @fundor333@mastodon.social"
                         loading="lazy">
                </a>
                <div class="toot-author">
                    <a class="toot-author-name"
                       href="https://mastodon.social/@fundor333"
                       rel="noopener">Fundor333</a>
                    <a class="toot-author-handle"
                       href="https://mastodon.social/@fundor333"
                       rel="noopener">@fundor333@mastodon.social</a>
                </div>
            </div>

            <div class="toot-content"><p><span class="h-card" translate="no"><a href="https://fosstodon.org/@chringel" class="u-url mention">@<span>chringel</span></a></span> How do you fill the syndications&#39; links? By hand?</p></div>

            

            <div class="toot-footer">
                <a href="https://mastodon.social@fundor333/status/108752916197327869"
                   class="toot-date"
                   rel="noopener">10:56 AM · Aug 2, 2022</a>
            </div>
        </div>
    


<p><!-- raw HTML omitted --><!-- raw HTML omitted --></p>








    
    
        
        
    

    
        <div class="toot">
            <div class="toot-header">
                <a class="toot-profile" href="https://fosstodon.org/@chringel" rel="noopener">
                    <img src="https://cdn.fosstodon.org/accounts/avatars/107/558/501/981/999/210/original/ae7e7ef8e5f9c347.png"
                         alt="Avatar for @chringel@fosstodon.org"
                         loading="lazy">
                </a>
                <div class="toot-author">
                    <a class="toot-author-name"
                       href="https://fosstodon.org/@chringel"
                       rel="noopener">Christian 👼</a>
                    <a class="toot-author-handle"
                       href="https://fosstodon.org/@chringel"
                       rel="noopener">@chringel@fosstodon.org</a>
                </div>
            </div>

            <div class="toot-content"><p><span class="h-card" translate="no"><a href="https://mastodon.social/@fundor333" class="u-url mention">@<span>fundor333</span></a></span> Yeah, unfortunately that‘s how I do it.</p><p>1. Publish a post on my blog<br />2. Post the link on Twitter/Mastodon/…<br />3. Update syndication param in front matter and republish</p><p>Haven‘t found another way yet.</p></div>

            

            <div class="toot-footer">
                <a href="https://fosstodon.org@chringel/status/108754642028626230"
                   class="toot-date"
                   rel="noopener">6:15 PM · Aug 2, 2022</a>
            </div>
        </div>
    


<p>After 3 years I find the solution in a post about webmetions!</p>
<h2 id="the-input" class="no-underline ">
  <a href="#the-input">
    <i class="fa-whiteboard fa-semibold fa-angle-right"></i>
    The input
  </a>
  </h2>
<p>Paul Kinlan wrote an article in the 2019 which flow under my radar and I didn&rsquo;read it untile recently<sup id="fnref:3"><a href="#fn:3" class="footnote-ref" role="doc-noteref">3</a></sup>.</p>
<p>In this post he use a Github action to write the webmention into a data folder for his GoHugo implementation. He has a script which download the data and put into file (the name of the file is the hash of the url of the post) which are use to render the webpage interested by the webmention. And all of this into Github Actions&hellip;</p>
<p>So I start thinking about it more and more&hellip;
What can I have the syndications links into a file for url? Like the webmention in this post? I need to read the urls form the social media and other stuff.</p>
<p>But now with X/Twitter in bad shape and Facebook/Meta only good for share photos I only use Mastodon so it is easy read them and write a file for url&hellip;</p>
<p>A implementation I find is this one by Brandon Rozek<sup id="fnref:4"><a href="#fn:4" class="footnote-ref" role="doc-noteref">4</a></sup> that I like in a lot of way but I change it because I don&rsquo;t use Medium&hellip;</p>
<h2 id="the-implementation" class="no-underline ">
  <a href="#the-implementation">
    <i class="fa-whiteboard fa-semibold fa-angle-right"></i>
    The implementation
  </a>
  </h2>
<p>So I start with the development:</p>
<ol>
<li>I need a file type/data structure standard for the Syndication</li>
<li>I need a script (or more) that find the syndication&rsquo;s links</li>
<li>I need to edit/add to the template some code for the render of it</li>
</ol>
<h3 id="structure-data" class="no-underline ">
  <a href="#structure-data">
    <i class="fa-whiteboard fa-semibold fa-angle-right"></i><i class="fa-whiteboard fa-semibold fa-angle-right"></i>
    Structure data
  </a>
  </h3>
<p>First are the data structure: json, with the name of the file is an hash of the url</p>

<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-json" data-lang="json"><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>	<span style="color:#f92672">&#34;syndication&#34;</span>: [
</span></span><span style="display:flex;"><span>		<span style="color:#e6db74">&#34;https://mastodon.social/@fundor333/113809667070052761&#34;</span>
</span></span><span style="display:flex;"><span>	]
</span></span><span style="display:flex;"><span>}</span></span></code></pre></div><p>For example this is my data for <a class="a-post interlink-script" href="https://fundor333.com/photos/2025/square-square-square-and-square/"  >this post</a>
. I choose Json because I can make check on it and it is a beautiful format for data</p>
<h3 id="the-scraper-script" class="no-underline ">
  <a href="#the-scraper-script">
    <i class="fa-whiteboard fa-semibold fa-angle-right"></i><i class="fa-whiteboard fa-semibold fa-angle-right"></i>
    The Scraper script
  </a>
  </h3>
<p>In this case I find that Mastodon generate a feed for every public profile so I only implementa a reader (class MastodonFinder) which read the feed and save the toots url if find a link to my domain, and a writer class (WriterSyndication) which run all the other class (in this case only the Mastodon one) and write the output as a look-a-like of the json show before.</p>

<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-python" data-lang="python"><span style="display:flex;"><span><span style="color:#f92672">import</span> feedparser
</span></span><span style="display:flex;"><span><span style="color:#f92672">from</span> pathlib <span style="color:#f92672">import</span> Path
</span></span><span style="display:flex;"><span><span style="color:#f92672">import</span> os
</span></span><span style="display:flex;"><span><span style="color:#f92672">import</span> json
</span></span><span style="display:flex;"><span><span style="color:#f92672">import</span> hashlib
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>domain <span style="color:#f92672">=</span> <span style="color:#e6db74">&#34;https://fundor333.com&#34;</span>
</span></span><span style="display:flex;"><span>rss_url_mastodon <span style="color:#f92672">=</span> <span style="color:#e6db74">&#34;https://mastodon.social/@fundor333.rss&#34;</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">def</span> <span style="color:#a6e22e">clean_slug</span>(slug: str):
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">return</span> hashlib<span style="color:#f92672">.</span>md5(
</span></span><span style="display:flex;"><span>        (slug<span style="color:#f92672">.</span>split(<span style="color:#e6db74">&#34;?&#34;</span>)[<span style="color:#ae81ff">0</span>])<span style="color:#f92672">.</span>encode(<span style="color:#e6db74">&#34;utf-8&#34;</span>), usedforsecurity<span style="color:#f92672">=</span><span style="color:#66d9ef">False</span>
</span></span><span style="display:flex;"><span>    )<span style="color:#f92672">.</span>hexdigest()
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">class</span> <span style="color:#a6e22e">MastodonFinder</span>:
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">def</span> <span style="color:#a6e22e">find_urls</span>(self, string):
</span></span><span style="display:flex;"><span>        x <span style="color:#f92672">=</span> string<span style="color:#f92672">.</span>split(<span style="color:#e6db74">&#39;&#34;&#39;</span>)
</span></span><span style="display:flex;"><span>        res <span style="color:#f92672">=</span> []
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">for</span> i <span style="color:#f92672">in</span> x:
</span></span><span style="display:flex;"><span>            <span style="color:#66d9ef">if</span> i<span style="color:#f92672">.</span>startswith(<span style="color:#e6db74">&#34;https:&#34;</span>) <span style="color:#f92672">or</span> i<span style="color:#f92672">.</span>startswith(<span style="color:#e6db74">&#34;http:&#34;</span>):
</span></span><span style="display:flex;"><span>                res<span style="color:#f92672">.</span>append(i)
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">return</span> res
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">def</span> <span style="color:#a6e22e">run</span>(self, rss_url: str, domain: str, output: dict):
</span></span><span style="display:flex;"><span>        feed <span style="color:#f92672">=</span> feedparser<span style="color:#f92672">.</span>parse(rss_url)
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">if</span> feed<span style="color:#f92672">.</span>status <span style="color:#f92672">==</span> <span style="color:#ae81ff">200</span>:
</span></span><span style="display:flex;"><span>            <span style="color:#66d9ef">for</span> entry <span style="color:#f92672">in</span> feed<span style="color:#f92672">.</span>entries:
</span></span><span style="display:flex;"><span>                link <span style="color:#f92672">=</span> entry<span style="color:#f92672">.</span>get(<span style="color:#e6db74">&#34;link&#34;</span>)
</span></span><span style="display:flex;"><span>                <span style="color:#66d9ef">for</span> e <span style="color:#f92672">in</span> self<span style="color:#f92672">.</span>find_urls(entry<span style="color:#f92672">.</span>get(<span style="color:#e6db74">&#34;description&#34;</span>)):
</span></span><span style="display:flex;"><span>                    <span style="color:#66d9ef">if</span> domain <span style="color:#f92672">in</span> e:
</span></span><span style="display:flex;"><span>                        e <span style="color:#f92672">=</span> clean_slug(e)
</span></span><span style="display:flex;"><span>                        <span style="color:#66d9ef">if</span> output<span style="color:#f92672">.</span>get(e, <span style="color:#66d9ef">False</span>):
</span></span><span style="display:flex;"><span>                            output[e]<span style="color:#f92672">.</span>append(link)
</span></span><span style="display:flex;"><span>                        <span style="color:#66d9ef">else</span>:
</span></span><span style="display:flex;"><span>                            output[e] <span style="color:#f92672">=</span> [link<span style="color:#f92672">.</span>strip()]
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">else</span>:
</span></span><span style="display:flex;"><span>            print(<span style="color:#e6db74">&#34;Failed to get RSS feed. Status code:&#34;</span>, feed<span style="color:#f92672">.</span>status)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">class</span> <span style="color:#a6e22e">WriterSyndication</span>:
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">def</span> <span style="color:#a6e22e">__init__</span>(self, rss_url_mastodon: str, domain: str):
</span></span><span style="display:flex;"><span>        self<span style="color:#f92672">.</span>output <span style="color:#f92672">=</span> {}
</span></span><span style="display:flex;"><span>        self<span style="color:#f92672">.</span>rss_url_mastodon <span style="color:#f92672">=</span> rss_url_mastodon
</span></span><span style="display:flex;"><span>        self<span style="color:#f92672">.</span>domain <span style="color:#f92672">=</span> domain
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">def</span> <span style="color:#a6e22e">data_gathering</span>(self):
</span></span><span style="display:flex;"><span>        m <span style="color:#f92672">=</span> MastodonFinder()
</span></span><span style="display:flex;"><span>        m<span style="color:#f92672">.</span>run(self<span style="color:#f92672">.</span>rss_url_mastodon, self<span style="color:#f92672">.</span>domain, self<span style="color:#f92672">.</span>output)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">def</span> <span style="color:#a6e22e">write</span>(self):
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">for</span> key <span style="color:#f92672">in</span> self<span style="color:#f92672">.</span>output<span style="color:#f92672">.</span>keys():
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>            path_folder <span style="color:#f92672">=</span> os<span style="color:#f92672">.</span>path<span style="color:#f92672">.</span>join(<span style="color:#e6db74">&#34;data&#34;</span>, <span style="color:#e6db74">&#34;syndication&#34;</span>)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>            Path(path_folder)<span style="color:#f92672">.</span>mkdir(parents<span style="color:#f92672">=</span><span style="color:#66d9ef">True</span>, exist_ok<span style="color:#f92672">=</span><span style="color:#66d9ef">True</span>)
</span></span><span style="display:flex;"><span>            path_file <span style="color:#f92672">=</span> os<span style="color:#f92672">.</span>path<span style="color:#f92672">.</span>join(path_folder, key)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>            <span style="color:#66d9ef">with</span> open(path_file <span style="color:#f92672">+</span> <span style="color:#e6db74">&#34;.json&#34;</span>, <span style="color:#e6db74">&#34;w&#34;</span>) <span style="color:#66d9ef">as</span> fp:
</span></span><span style="display:flex;"><span>                json<span style="color:#f92672">.</span>dump({<span style="color:#e6db74">&#34;syndication&#34;</span>: self<span style="color:#f92672">.</span>output[key]}, fp)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">def</span> <span style="color:#a6e22e">run</span>(self):
</span></span><span style="display:flex;"><span>        self<span style="color:#f92672">.</span>data_gathering()
</span></span><span style="display:flex;"><span>        self<span style="color:#f92672">.</span>write()
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>w <span style="color:#f92672">=</span> WriterSyndication(rss_url_mastodon, domain)
</span></span><span style="display:flex;"><span>w<span style="color:#f92672">.</span>run()</span></span></code></pre></div><p>I wrote in this way because I can change the readers or add new one but all the rest of the code remain the same.</p>
<h4 id="todo-one-bug" class="no-underline ">
  <a href="#todo-one-bug">
    <i class="fa-whiteboard fa-semibold fa-angle-right"></i><i class="fa-whiteboard fa-semibold fa-angle-right"></i><i class="fa-whiteboard fa-semibold fa-angle-right"></i>
    TODO one bug
  </a>
  </h4>
<p>Only thing is I need to implement some code for reading all the old file and add to them and not create a new data file if there is an old one.</p>
<h3 id="the-github-action" class="no-underline ">
  <a href="#the-github-action">
    <i class="fa-whiteboard fa-semibold fa-angle-right"></i><i class="fa-whiteboard fa-semibold fa-angle-right"></i>
    The GitHub Action
  </a>
  </h3>
<p>I run it as a Github Action with this parameters.</p>

<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-yaml" data-lang="yaml"><span style="display:flex;"><span><span style="color:#f92672">name</span>: <span style="color:#ae81ff">Syndication Link</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">on</span>:
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">schedule</span>:
</span></span><span style="display:flex;"><span>    - <span style="color:#f92672">cron</span>: <span style="color:#e6db74">&#34;0 */2 * * *&#34;</span>
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">workflow_dispatch</span>:
</span></span><span style="display:flex;"><span><span style="color:#f92672">jobs</span>:
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">webmentions</span>:
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">runs-on</span>: <span style="color:#ae81ff">ubuntu-latest</span>
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">steps</span>:
</span></span><span style="display:flex;"><span>      - <span style="color:#f92672">name</span>: <span style="color:#ae81ff">Check out repository</span>
</span></span><span style="display:flex;"><span>        <span style="color:#f92672">uses</span>: <span style="color:#ae81ff">actions/checkout@master</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>      - <span style="color:#f92672">name</span>: <span style="color:#ae81ff">Set up Python</span>
</span></span><span style="display:flex;"><span>        <span style="color:#f92672">uses</span>: <span style="color:#ae81ff">actions/setup-python@v5</span>
</span></span><span style="display:flex;"><span>        <span style="color:#f92672">with</span>:
</span></span><span style="display:flex;"><span>          <span style="color:#f92672">python-version</span>: <span style="color:#e6db74">&#34;3.13&#34;</span>
</span></span><span style="display:flex;"><span>          <span style="color:#f92672">cache</span>: <span style="color:#e6db74">&#34;pip&#34;</span> <span style="color:#75715e"># caching pip dependencies</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>      - <span style="color:#f92672">name</span>: <span style="color:#ae81ff">Install Pip dependencies</span>
</span></span><span style="display:flex;"><span>        <span style="color:#f92672">run</span>: <span style="color:#ae81ff">pip install -r requirements.txt</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>      - <span style="color:#f92672">name</span>: <span style="color:#ae81ff">Fetch Syndication</span>
</span></span><span style="display:flex;"><span>        <span style="color:#f92672">run</span>: <span style="color:#ae81ff">python ./action_script/syndication-collector.py</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>      - <span style="color:#f92672">name</span>: <span style="color:#ae81ff">Commit to repository</span>
</span></span><span style="display:flex;"><span>        <span style="color:#f92672">env</span>:
</span></span><span style="display:flex;"><span>          <span style="color:#f92672">GITHUB_TOKEN</span>: <span style="color:#ae81ff">${{ secrets.TOKEN }}</span>
</span></span><span style="display:flex;"><span>          <span style="color:#f92672">COMMIT_MSG</span>: |<span style="color:#e6db74">
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">            👾Fetch webmentions
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">            skip-checks: true</span>
</span></span><span style="display:flex;"><span>        <span style="color:#f92672">run</span>: |<span style="color:#e6db74">
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">          git config user.email &#34;git@fundor333.com&#34;
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">          git config user.name &#34;fundor333&#34;
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">          git remote set-url origin https://x-access-token:${GITHUB_TOKEN}@github.com/fundor333/fundor333.github.io.git
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">          git checkout main
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">          git add .
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">          git diff --quiet &amp;&amp; git diff --staged --quiet || (git commit -m &#34;${COMMIT_MSG}&#34;; git push origin main)</span></span></span></code></pre></div><p>I always put &ldquo;workflow_dispatch&rdquo; as one of the running condiction for having a manual button for running it.</p>
<h3 id="the-template" class="no-underline ">
  <a href="#the-template">
    <i class="fa-whiteboard fa-semibold fa-angle-right"></i><i class="fa-whiteboard fa-semibold fa-angle-right"></i>
    The template
  </a>
  </h3>
<p>This is the template fragment I use to show the syndication of one of the post.
It return a single line of text with all the link of the syndication label as the host of the service (as if it is a mastodon.social/xxxx/xxxx link, the label will be mastodon.social).</p>

<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-go-html-template" data-lang="go-html-template"><span style="display:flex;"><span><span style="color:#75715e">{{</span> <span style="color:#a6e22e">$urlized</span> <span style="color:#f92672">:=</span> <span style="color:#a6e22e">.Page.Permalink</span> <span style="color:#f92672">|</span> <span style="color:#a6e22e">md5</span> <span style="color:#75715e">}}</span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">{{</span> <span style="color:#66d9ef">if</span> <span style="color:#66d9ef">index</span> <span style="color:#a6e22e">.Site.Data.syndication</span> <span style="color:#a6e22e">$urlized</span> <span style="color:#75715e">}}</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>&lt;<span style="color:#f92672">hr</span>&gt;
</span></span><span style="display:flex;"><span>&lt;<span style="color:#f92672">br</span>&gt;
</span></span><span style="display:flex;"><span>  &lt;<span style="color:#f92672">div</span> <span style="color:#a6e22e">class</span><span style="color:#f92672">=</span><span style="color:#e6db74">&#34;syndication&#34;</span>&gt;
</span></span><span style="display:flex;"><span>      &lt;<span style="color:#f92672">i</span> <span style="color:#a6e22e">class</span><span style="color:#f92672">=</span><span style="color:#e6db74">&#34;fas fa-link&#34;</span>&gt;&lt;/<span style="color:#f92672">i</span>&gt;
</span></span><span style="display:flex;"><span>      This post was also syndicated to:
</span></span><span style="display:flex;"><span>      <span style="color:#75715e">{{</span> <span style="color:#a6e22e">$data</span><span style="color:#f92672">:=</span>  <span style="color:#66d9ef">index</span> <span style="color:#a6e22e">.Site.Data.syndication</span> <span style="color:#a6e22e">$urlized</span>  <span style="color:#75715e">}}</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>      <span style="color:#75715e">{{</span> <span style="color:#a6e22e">$data</span><span style="color:#f92672">:=</span> <span style="color:#a6e22e">$data</span><span style="color:#a6e22e">.syndication</span> <span style="color:#75715e">}}</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>      <span style="color:#75715e">{{</span> <span style="color:#66d9ef">range</span> <span style="color:#a6e22e">$index</span><span style="color:#f92672">,</span> <span style="color:#a6e22e">$url</span> <span style="color:#f92672">:=</span> <span style="color:#a6e22e">$data</span><span style="color:#75715e">}}</span>
</span></span><span style="display:flex;"><span>        <span style="color:#75715e">{{-</span> <span style="color:#a6e22e">$parsed_url</span> <span style="color:#f92672">:=</span> <span style="color:#a6e22e">urls</span><span style="color:#a6e22e">.Parse</span> <span style="color:#a6e22e">$url</span> <span style="color:#75715e">-}}</span>
</span></span><span style="display:flex;"><span>        <span style="color:#75715e">{{-</span> <span style="color:#66d9ef">if</span> <span style="color:#a6e22e">$index</span> <span style="color:#75715e">}}</span>, <span style="color:#75715e">{{-</span> <span style="color:#66d9ef">end</span> <span style="color:#75715e">}}</span>
</span></span><span style="display:flex;"><span>        &lt;<span style="color:#f92672">a</span> <span style="color:#a6e22e">class</span><span style="color:#f92672">=</span><span style="color:#e6db74">&#34;u-syndication&#34;</span> <span style="color:#a6e22e">href</span><span style="color:#f92672">=</span><span style="color:#e6db74">&#34;</span><span style="color:#75715e">{{</span> <span style="color:#a6e22e">$url</span> <span style="color:#75715e">}}</span><span style="color:#e6db74">&#34;</span> <span style="color:#a6e22e">rel</span><span style="color:#f92672">=</span><span style="color:#e6db74">&#34;syndication&#34;</span>&gt;<span style="color:#75715e">{{</span> <span style="color:#a6e22e">$parsed_url</span><span style="color:#a6e22e">.Host</span> <span style="color:#75715e">}}</span>&lt;/<span style="color:#f92672">a</span>&gt;
</span></span><span style="display:flex;"><span>      <span style="color:#75715e">{{</span> <span style="color:#66d9ef">end</span> <span style="color:#75715e">}}</span>
</span></span><span style="display:flex;"><span>  &lt;/<span style="color:#f92672">div</span>&gt;
</span></span><span style="display:flex;"><span>  &lt;<span style="color:#f92672">br</span>&gt;
</span></span><span style="display:flex;"><span><span style="color:#75715e">{{</span> <span style="color:#66d9ef">end</span> <span style="color:#75715e">}}</span></span></span></code></pre></div><p>I also add the microformat2 tags because all my site has them.</p>
<h2 id="conclusion" class="no-underline ">
  <a href="#conclusion">
    <i class="fa-whiteboard fa-semibold fa-angle-right"></i>
    Conclusion
  </a>
  </h2>
<p>I love this way and I am happy because I resolve a problem I had with my blog for 3 years</p>
<div class="footnotes" role="doc-endnotes">
<hr>
<ol>
<li id="fn:1">
<p><a class="a-post interlink-script" href="https://chringel.dev/2022/07/indiewebify-me-and-dont-forget-my-webmentions/"   target="_blank">Indiewebify me! And don&rsquo;t forget my webmentions!&nbsp;&nbsp;<i class="fa-whiteboard fa-semibold fa-link"></i></a>
&#160;<a href="#fnref:1" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
<li id="fn:2">
<p><a class="a-post interlink-script" href="https://fosstodon.org/@chringel/108754642028626230"   target="_blank">dev with the same problem&nbsp;&nbsp;<i class="fa-whiteboard fa-semibold fa-link"></i></a>
&#160;<a href="#fnref:2" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
<li id="fn:3">
<p><a class="a-post interlink-script" href="https://paul.kinlan.me/using-web-mentions-in-a-static-sitehugo/"   target="_blank">Using Web Mentions in a static site (Hugo)&nbsp;&nbsp;<i class="fa-whiteboard fa-semibold fa-link"></i></a>
&#160;<a href="#fnref:3" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
<li id="fn:4">
<p><a class="a-post interlink-script" href="https://brandonrozek.com/blog/syndicating-hugo-to-medium/"   target="_blank">Syndicating Hugo Posts to Medium&nbsp;&nbsp;<i class="fa-whiteboard fa-semibold fa-link"></i></a>
&#160;<a href="#fnref:4" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
</ol>
</div>
]]></content></entry></feed>