Matthias Kestenholz: Posts about Weeknotes KestenholzWeeknotes (2024 week 14)<h1>Weeknotes (2024 week 14)</h1><p>I&rsquo;m having a bit of a slow week with the easter weekend and a wisdom tooth extraction. I&rsquo;m recovering quite quickly it seems and I&rsquo;m glad about it.</p> <p>This weeknotes entry is short and quick. I&rsquo;m trying to get back into the habit of writing them after a mediocre start this year.</p> <h2>20th Anniversary Celebration of Young Greens Switzerland</h2> <p>I have attended the celebration of Young Greens Switzerland. I have been a founding member and have been active for close to ten years. A lot of time has passed since then. It has been great to reminisce about old times with friends and, more importantly, to see how the torch is carried on.</p> <h2>Releases</h2> <ul> <li><a href="">blacknoise 0.0.5</a>: blacknoise is an ASGI app for static file serving inspired by <a href="">whitenoise</a>. It only supports a very limited subset of whitenoise&rsquo;s functionality, but it supports async.</li> <li><a href="">html-sanitizer 2.4.1</a>: The lxml library moved the HTML cleaner into its own package, <a href="">lxml-html-clean</a>; this release adds support for that. I didn&rsquo;t know that the HTML cleaner is viewed as being problematic by the lxml maintainers. I&rsquo;m having another look at <a href="">nh3</a> and will maybe switch html-sanitizer&rsquo;s guts from lxml to nh3 in the future.</li> <li><a href="">django-tree-queries 0.18</a>: django-tree-queries now supports ordering siblings by multiple fields and even allows descending orderings.</li> <li><a href="">django-cabinet 0.14.2</a>: This release fixes the CKEditor 4 filebrowser popup when using Django 5 or better.</li> </ul>Weeknotes (2024 week 11)<h1>Weeknotes (2024 week 11)</h1><h2>Estimates</h2> <p><a href="">Jacob wrote an excellent post on breaking down tasks</a>. I did like the post a lot. Maybe I&rsquo;ll write a longer reply later, but for now just this. <a href="">There definitely are good reasons for the pushback against estimation</a>, and it&rsquo;s really not just that some people lack professionalism.</p> <h2>Releases</h2> <ul> <li><a href="">django-cabinet 0.14.1</a>: Mini release containing a Turkish translation. It&rsquo;s always nice if software is used.</li> <li><a href="">feincms3 4.6</a>: Fixed a bug where the move form wouldn&rsquo;t use a potentially overridden <code>ModelAdmin.get_queryset</code> method.</li> <li><a href="">form-designer 0.24</a>: Updated the package for django-recaptcha 4.0.</li> <li><a href="">html-sanitizer 2.3.1</a>: Fixed an edge case sanitization bug (luckily without security implications).</li> <li><a href="">django-content-editor 6.4.2</a>: django-content-editor now again supports transitioning plugin fieldsets when opening <em>and</em> closing thanks to CSS grid&rsquo;s ability to animate the maximum height of an element. Also, the initialization in 6.4 was badly broken.</li> <li><a href="">django-prose-editor 0.2</a>: <a href="">See the announcement blog post from Wednesday</a>.</li> </ul>Weeknotes (2024 week 07)<h1>Weeknotes (2024 week 07)</h1><p>This is a short weeknotes entry which mainly contains a large list of releases. The reason for the large list is that I haven&rsquo;t published a weeknotes entry in weeks.</p> <h2>Releases</h2> <ul> <li><a href="">form-designer 0.23</a>: Only small changes, mainly updated the package for current Django and Python versions.</li> <li><a href="">feincms3-cookiecontrol 1.4.6</a>: A minor change: Swallow exceptions which happen during startup when clobbering the scripts data fails. As an aside: I find it funny that I have discovered the <code>.f3cc</code> class in some cookie banner blocklists. It feels good to be recognized even if this maybe isn&rsquo;t the nicest way, but it works for me since I actually do not like cookie banners either. At least feincms3-cookiecontrol doesn&rsquo;t inject anything without users&rsquo; consent, and doesn&rsquo;t require a third party service to run.</li> <li><a href="">django-simple-redirects 2.2.0</a>: Minor release which adds a search field to the admin changelist. django-simple-redirects is a repackaged version of <code>django.contrib.redirects</code> without the <code>django.contrib.sites</code> dependency.</li> <li><a href="">speckenv 6.2</a>: <code>django_cache_url</code> now supports parsing redis configuration for a leader-replica redis installation with a read-write leader host and read-only replica hosts. I use the same configuration format as <a href="">django-cache-url</a> does.</li> <li><a href="">django-debug-toolbar 4.3</a>: I haven&rsquo;t done much here, just some reviewing here and there. I enjoy the Djangonaut Space contributions a lot.</li> <li><a href="">django-cabinet 0.14</a>: I have removed the constraint which enforces unique names for subfolders. Enforcing the uniqueness does make sense, but it also makes bulk-updating the media library using serialized data more painful than it should be. It&rsquo;s a clear case of worse is better for me. If people want to confuse themselves I&rsquo;m not going to stop them (anymore, in this case) but it makes the rest of the code so much easier to write that it&rsquo;s not even funny.</li> <li><a href="">html-sanitizer 2.3</a>: This release contains a nice contribution which removes some whitespace which has been added by the sanitizer when merging adjacent tags of the same type, e.g. <code>&lt;strong&gt;abc&lt;/strong&gt;&lt;strong&gt;def&lt;/strong&gt;</code>.</li> <li><a href="">django-ckeditor 6.7.1</a>: See above.</li> <li><a href="">django-json-schema-editor 0.0.11</a>: Fixed a crash which happened when not providing the optional (!) configuration. Shit happens. I should really have a test suite for this package.</li> <li><a href="">feincms3 4.5.2</a>: Disables the CKEditor version check.</li> <li><a href="">django-content-editor 6.4</a>: The first release since December 2022! Very stable software. The editor now restores the collapsed state of inlines and the scroll position when using &ldquo;Save and continue editing&rdquo;. This is especially useful if editing an object with many content blocks.</li> </ul>Weeknotes (2024 week 03)<h1>Weeknotes (2024 week 03)</h1><h2>Djangonaut Space</h2> <p>I wish all participants a good time and much success. I do not have anything to do with it really but I enjoy the idea a lot and maybe there will be a pull request or two to review.</p> <h2>Kubernetes</h2> <p>After years and years of hosting all sites on VPS I have finally reached the point where the old setup is more annoying to work with than switching to a new one. I have searched long for a solution which wasn&rsquo;t as limited as some PaaS and as complex as going full Kubernetes, and where I can still delegate the responsibility of actually keeping things up and running to other people. In the end I have now accepted that such a thing doesn&rsquo;t exist; either you have the limitations of a ready made solution, the limitation of having to open many many support tickets or the problem of having to learn Kubernetes (or something similar) with its extremely steep learning curve.</p> <p>After spending days with it I&rsquo;m slowly getting to the point where setting up local development environments and deploying changes is fun again. I&rsquo;m using the GitOps paradigm; while I&rsquo;m still building and uploading Docker (podman) images from the local development environment everything else is automated and goes through a Git based process. That&rsquo;s much nicer than clicking around in some interface or copy pasting obscure commands into the console.</p> <p>The biggest problem I encountered was (perhaps unsurprisingly) managing secrets as a team. It seems to me that while <a href="">sealed secrets</a> work great as an individual developer they don&rsquo;t really offer straightforward solutions to avoid different people overwriting and resetting each others secrets when updating them. I&rsquo;m a happy user of the external secrets operator and using some cloud service to actually store those secrets.</p> <p>I have started using <a href="">granian</a> in production. I like the idea of a Rust-based ASGI/WSGI server. Nothing mission critical yet. My idea is to build confidence in the software stack.</p> <h2>Compulsory social measures</h2> <p>The more I learn about how Switzerland treats its citizens the more I wonder about the ways in which humans can mistreat other humans in a so called civilized and peaceful society.</p> <p>It&rsquo;s not exactly a new topic for me, but working on platforms which help remember and which help introducing people to the history certainly causes a heightened awareness for issues such as these.</p> <p><a href="">More on this</a>.</p> <h2>Releases</h2> <ul> <li><a href="">feincms3-sites 0.20.2</a>: It previously wasn&rsquo;t possible to filter the list of sites to only show those sites which do <em>not</em> have a default language. This has been fixed.</li> <li><a href="">django-json-schema-editor 0.0.10</a>: It&rsquo;s now actually possible to use the JSON editor outside inlines! That was a fun bug&hellip; not. Apart from the mentioned bug this new release mostly contains fixes to the styles. We&rsquo;re slowly getting there.</li> <li><a href="">django-mptt 0.16</a>: I didn&rsquo;t do anything except for the changelog and the release. That&rsquo;s alright. The release contains a few minor fixes.</li> </ul>Weeknotes (2024 week 01)<h1>Weeknotes (2024 week 01)</h1><p>First weeknotes post for 2024! Happy new year!</p> <h2>Looking back on 2023</h2> <h3>Writing</h3> <p>I have published almost 40 posts last year. That&rsquo;s almost as many posts as I published in the time period from 2014 to 2023. <a href="">Coworking to write more</a> does work.</p> <p>I already had a quite active blog from 2005 to 2008 with a few posts after that; everything before 2014 was in german and mainly concerned with green politics and climate change. I&rsquo;m still very interested in these topics but I don&rsquo;t feel as if I have much to add to the conversation, even though it&rsquo;s the more important issue.</p> <h3>Open Source</h3> <p>Not much changed here. I enjoy basically everything I do in open source land, and co-maintaining the Django Debug Toolbar with Tim is a joy.</p> <p>I still wish that some of my projects had more impact in Django land, especially those who augment the Django administration interface to be a lightweight CMS which requires very little maintenance and work in the long run. I think it&rsquo;s great that one of the core components, <a href="">django-content-editor</a>, hasn&rsquo;t required a release in more than one year. It doesn&rsquo;t have to be expanded because it just works. It would be great if there was a good way to <a href="">distinguish</a> between software which basically doesn&rsquo;t require any updates and software which is abandoned.</p> <p>The only project which doesn&rsquo;t bring me much joy is django-mptt. Most people accept that there are no guarantees, but some people are just rude in the way in which they expect others to do the work. The first reaction was to return the blow and I&rsquo;m glad that I didn&rsquo;t give in to the temptation to do that. It&rsquo;s basically never worth it to do that in writing.</p> <h3>Family</h3> <p>We had a good 2023 together and I&rsquo;m very much looking forward to a just as good 2024.</p> <h2>Plans for 2024</h2> <p>I have bought a ticket for the <a href="">DjangoCon Europe 2024</a> in Spain and I&rsquo;m very much looking forward to that.</p> <p>Maybe we&rsquo;ll visit a music festival again this summer. After listening to a lot of metal music in the last ten or more years I rediscovered the dark side of D&rsquo;n&rsquo;B. Good times.</p> <h2>Advent of Code</h2> <p>I have finished the Advent of Code with some help from the Subreddit. Almost all of the puzzles were fun to think about. I didn&rsquo;t have fun solving each and everyone of them, especially not the second part of a few of the later days. I feel good checking out solutions from other people in the subreddit, and maybe adding newly gained ideas to my code or even running someone else&rsquo;s code 1:1 on my data after studying the algorithms used and hopefully learning something.</p> <p>I had a good time and enjoyed shutting down the computer after that.</p> <h2>Releases</h2> <ul> <li><a href="">FeinCMS 23.12</a>: A few minor changes to the thumbnailing code. It&rsquo;s always nice to hear from people who are still using this project.</li> </ul>Weeknotes (2023 week 50)<h1>Weeknotes (2023 week 50)</h1><h2>django-imagefield</h2> <p>The path building scheme used by <a href="">django-imagefield</a> has proven problematic: It&rsquo;s too likely that processed images will have the same path.</p> <p>I have changed the strategy used for generating paths to use more data from the source; it&rsquo;s now possible (and recommended!) to set <code>IMAGEFIELD_BIN_DEPTH</code> to a value greater than 1; 2 or 3 should be sufficient. The default value is 1 which corresponds to the old default so that the change won&rsquo;t be backwards incompatible. However, you&rsquo;ll always get a deprecation warning if you don&rsquo;t set a bigger value yourself. The default will probably change in the future.</p> <h2>Advent of Code</h2> <p>I have always felt a bit as an imposter because I do not have any formal CS education; not so much in the last few years but certainly earlier in my career. I have enjoyed participating in the <a href="">Advent of Code 2022</a> a lot and I have definitely learned to know when to use and how to use a few algorithms I didn&rsquo;t even know before. I&rsquo;m again working through the puzzles in my own pace and have managed to solve almost all of them up to today this year. There still are some puzzles where I don&rsquo;t even know how to start the second part 😅.</p> <h2>Hosting</h2> <p>We&rsquo;re still hosting most sites on virtualized servers, without any containers or any of the new stuff. I&rsquo;m finally reaching the point where the downsides of this approach start to drag new projects down and the workarounds start looking worse than maybe switching to containers or even Kubernetes. Wish me luck, I&rsquo;m more confused than I&rsquo;ve been in years.</p> <h2>Health</h2> <p>To absolutely nobody&rsquo;s surprise the family and myself have continued to be sick in the last two weeks. Nothing really bad happened, so we&rsquo;re still lucky.</p> <p>There&rsquo;s unfortunately no way to solve a societal problem individually, so that will probably continue to be our life for now.</p> <h2>Releases</h2> <ul> <li><a href="">django-imagefield 0.18</a>: See above.</li> <li><a href="">feincms3-sites 0.20.1</a>: Added additional validation (cleaning) checks. Showing error messages is preferrable to crashing with <code>IntegrityError</code> exceptions after all.</li> <li><a href="">django-js-asset 2.2.0</a>: Hatchling seems to dislike it if the project name and the Python module name do not match. I actually like <code>django-js-asset</code>&rsquo;s Python module to be <code>js_asset</code> but I&rsquo;m beginning to rethink this decision.</li> <li><a href="">django-json-schema-editor 0.0.4</a>: See <a href="">the post from this week</a>.</li> </ul>Weeknotes (2023 week 48)<h1>Weeknotes (2023 week 48)</h1><p>A few weeks have passed since the last update. The whole family was repeatedly sick with different viruses etc&hellip; I hope that the worst is over now. Who knows.</p> <h2>12-factor Django storage configuration</h2> <p>I should maybe write a longer and separate post about this, but <a href="">speckenv</a> has gained support for the Django <code>STORAGES</code> setting. No documentation yet, but it supports two storage backends for now, the file system storage and <a href="">django-s3-storage</a>, my go-to library for S3-compatible services.</p> <p>Using it looks something like this:</p> <div class="chl"><pre><span></span><code><span class="kn">from</span> <span class="nn">speckenv</span> <span class="kn">import</span> <span class="n">env</span> <span class="kn">from</span> <span class="nn">speckenv_django</span> <span class="kn">import</span> <span class="n">django_storage_url</span> <span class="n">STORAGES</span> <span class="o">=</span> <span class="p">{</span> <span class="s2">&quot;default&quot;</span><span class="p">:</span> <span class="n">django_storage_url</span><span class="p">(</span> <span class="n">env</span><span class="p">(</span> <span class="s2">&quot;STORAGE_URL&quot;</span><span class="p">,</span> <span class="n">default</span><span class="o">=</span><span class="s2">&quot;file:./media/?base_url=/media/&quot;</span><span class="p">,</span> <span class="n">warn</span><span class="o">=</span><span class="kc">True</span><span class="p">,</span> <span class="p">),</span> <span class="n">base_dir</span><span class="o">=</span><span class="n">BASE_DIR</span><span class="p">,</span> <span class="p">),</span> <span class="s2">&quot;staticfiles&quot;</span><span class="p">:</span> <span class="p">{</span> <span class="s2">&quot;BACKEND&quot;</span><span class="p">:</span> <span class="s2">&quot;;</span><span class="p">,</span> <span class="p">},</span> <span class="p">}</span> </code></pre></div> <p>Then, if you want to use S3 you can put something like this in your <code>.env</code> file:</p> <div class="chl"><pre><span></span><code><span class="n">STORAGE_URL</span><span class="o">=</span><span class="nl">s3</span><span class="p">:</span><span class="o">//</span><span class="n">access</span><span class="o">-</span><span class="k">key</span><span class="err">:</span><span class="n">secret</span><span class="nv">@bucket</span><span class="p">.</span><span class="n">name</span><span class="p">.</span><span class="n">s3</span><span class="p">.</span><span class="n">eu</span><span class="o">-</span><span class="n">central</span><span class="o">-</span><span class="mf">1.</span><span class="n">amazonaws</span><span class="p">.</span><span class="n">com</span><span class="o">/</span><span class="n">media</span><span class="o">/</span> </code></pre></div> <p>Or maybe something like this, if you want to serve media files without authentication:</p> <div class="chl"><pre><span></span><code><span class="n">STORAGE_URL</span><span class="o">=</span><span class="nl">s3</span><span class="p">:</span><span class="o">//</span><span class="n">access</span><span class="o">-</span><span class="k">key</span><span class="err">:</span><span class="n">secret</span><span class="nv">@bucket</span><span class="p">.</span><span class="n">name</span><span class="p">.</span><span class="n">s3</span><span class="p">.</span><span class="n">eu</span><span class="o">-</span><span class="n">central</span><span class="o">-</span><span class="mf">1.</span><span class="n">amazonaws</span><span class="p">.</span><span class="n">com</span><span class="o">/</span><span class="n">media</span><span class="o">/</span><span class="vm">?</span><span class="n">aws_s3_public_auth</span><span class="o">=</span><span class="k">False</span><span class="o">&amp;</span><span class="n">aws_s3_max_age_seconds</span><span class="o">=</span><span class="mi">31536000</span> </code></pre></div> <h2>Releases</h2> <ul> <li><a href="">speckenv 6.1.1</a>: See above.</li> <li><a href="">feincms3-meta 4.6</a>: York has contributed support for emitting structured data records. Looks nice. No documentation yet.</li> <li><a href="">django-tree-queries 0.16.1</a>: <code>.values()</code> and <code>.values_list()</code> queries are now handled better and more consistently than before.</li> </ul>Weeknotes (2023 week 44)<h1>Weeknotes (2023 week 44)</h1><h2>Unmaintained but maintained packages</h2> <p>There&rsquo;s a discussion going on in the <a href="">django-mptt issue tracker</a> about the maintenance state of django-mptt. <a href="">I have marked the project as unmaintained in March 2021</a> and haven&rsquo;t regretted this decision at all. I haven&rsquo;t had to fix <a href="">inconsistencies in the tree structure</a> once since switching to <a href="">django-tree-queries</a>. And if that wasn&rsquo;t enough, I get little but only warm and thankful feedback for the latter, so that&rsquo;s extra nice.</p> <p>Despite marking django-mptt as unmaintained I seem to be doing a little bit of maintenance still. I&rsquo;m still using it in old paid projects and so the things I do to make the package work for me is paid work. I&rsquo;m not personally invested in the package anymore, so I&rsquo;m able to tell people that there are absolutely no guarantees about the maintenance, and that feels good.</p> <h2>Read the Docs</h2> <p>I do understand why the <code>.readthedocs.yaml</code> file is now necessary. I wish that I wouldn&rsquo;t have to do all the busywork of adding one to projects. I have just resubscribed to the Read the Docs Gold Membership which probably has expired at some point in the past. Read the Docs is excellent and everybody who can should support them.</p> <h2>Releases</h2> <ul> <li><a href="">feincms3 4.5</a>, <a href="">feincms3-sites 0.20</a> and <a href="">feincms3-language-sites 0.3</a>: Fixed the check which only allows adding an application through the CMS to the page tree (yes, that&rsquo;s right) once; feincms3 worked fine, feincms3-language-sites by accident but feincms3-sites didn&rsquo;t.</li> <li><a href="">towel 0.31</a>: Towel is one of my oldest packages which is still being used in real-world projects. Towel is a tool for building CRUD-type applications and is designed to keep you DRY while doing that. The project has been heavily inspired by a Django-based agency software I built many years back. The package even has <a href="">docs</a>! I&rsquo;m still quite proud of the mostly transparent support for multitenancy, but apart from that I haven&rsquo;t used it in many new projects.</li> </ul>Weeknotes (2023 week 43)<h1>Weeknotes (2023 week 43)</h1><h2>Switching to ruff format</h2> <p><a href="">ruff v0.1.2</a> includes the beta version of the ruff formatter. It formats the code almost the same way as black, but much much faster. I have started switching projects I&rsquo;m working on and the experience has been nothing but great.</p> <h2>100% test coverage</h2> <p>I have again fixed a bad bug in code which had 100% test coverage. It&rsquo;s not news that 100% test coverage isn&rsquo;t a recipe for bug-free code, and it&rsquo;s probably not even worth optimizing for that metric in code. It&rsquo;s nothing more but a proxy for what you should really measure. Nevertheless it certainly does feel good to achieve high coverage values!</p> <h2>Releases</h2> <p>No releases at all.</p>Weeknotes (2023 week 42)<h1>Weeknotes (2023 week 42)</h1><h2>Vacation in Italy</h2> <p>We have spent a wonderful family week in Italy. The voyage by train was very comfortable and we had a great time there. I have lived close to lakes all my life but the sea is always something else. Now I enjoy the cold temperatures of fall.</p> <h2>Going back (forward) to GitJournal</h2> <p>I have tried several note taking apps but I&rsquo;m now back using <a href="">GitJournal</a> with a Git repository filled with Markdown notes. It works well enough. I just wish that there was a way to make notes more distinguishable and I wish that the editor was more forgiving when encountering badly formatted checklists.</p> <h2>Analog blogging</h2> <p>I have long wanted to write about <a href="">our switch from Slack to Discord</a>. I have started to write this post with pen and paper. I find that I think better when using pen and paper than when using the computer keyboard. One factor is certainly that the computer offers more distractions, but I suspect that another, more important factor is that as a fast typist the fingers and the thinking are always getting out of step, and this happens less when using a slower method of writing. This actually isn&rsquo;t an idea I had myself, but I don&rsquo;t remember where I got it from.</p> <h2>Zero-based versioning: Good or bad?</h2> <p>I discovered <a href="">ZeroVer</a> sometime in the last few days. I have many many Django packages with zero-based versions. Some of them have been used in production for years now. I sometimes wonder if staying with <code>0.</code> is unprofessional and I should just release 1.0 and be done with it or if it doesn&rsquo;t really matter at all.</p> <p>If I evaluate software packages more often than not I don&rsquo;t look at the version number or the version numbering scheme (except when a package is still using <code>0.0.</code>) when deciding whether to rely on it or not. The documentation and the code itself are much more important to me.</p> <h2>Releases</h2> <p>I haven&rsquo;t uploaded any releases in the last 14 days. That&rsquo;s good: I&rsquo;m one of those people who have made their passion their job (which is great) but that sometimes makes it hard to not work at all since I can always tell myself that I&rsquo;m not working, that it&rsquo;s just a hobby.</p>Weeknotes (2023 week 40)<h1>Weeknotes (2023 week 40)</h1><h2>More work on hosting several websites from a single Django application server using feincms3-sites</h2> <p>I have mentioned feincms3-sites last week in my last weeknotes entry; I have again given this package a lot of attention in the last days, so another update is in order.</p> <p>It is now possible to override the list of languages available on each site. That&rsquo;s especially useful for an upcoming campaign site where the umbrella group&rsquo;s site is available in three languages, but (most?) individual group sites (hosted on subdomains) will only have a subset of languages. Since I live in a country with four national languages (english isn&rsquo;t one of them, but is spoken by many!) supporting more than one language, or even many languages is totally commonplace. It&rsquo;s great that Django has good support for internationalization. For the sake of an example, I have the following sites:</p> <ul> <li><code></code>: The default. The host has to match exactly.</li> <li><code></code>: One individual group&rsquo;s site. The host has to match the regex <code>^subdomain\.</code> (sorry, I actually do like regexes).</li> </ul> <h3>Overriding configured hosts for local development</h3> <p>One thing which always annoyed me when using <code>django.contrib.sites</code> was that &ldquo;just&rdquo; pulling the database from production to the local development environment always produced links pointing back to the remote host instead of working locally (when producing absolute URLs). This problem was shared by feincms3-sites as well. I have now found a very ugly but perfectly workable solution: Overwrite <code>Site.get_host()</code> locally:</p> <div class="chl"><pre><span></span><code><span class="k">if</span> <span class="n">DEBUG</span><span class="p">:</span> <span class="n">domain</span> <span class="o">=</span> <span class="s2">&quot;;</span> <span class="c1"># Or whatever</span> <span class="n">_get_host</span> <span class="o">=</span> <span class="k">lambda</span> <span class="n">site</span><span class="p">:</span> <span class="n">site</span><span class="o">.</span><span class="n">host</span><span class="o">.</span><span class="n">replace</span><span class="p">(</span><span class="n">domain</span><span class="p">,</span> <span class="s2">&quot;localhost:8000&quot;</span><span class="p">)</span> <span class="n">FEINCMS3_SITES_SITE_GET_HOST</span> <span class="o">=</span> <span class="n">_get_host</span> </code></pre></div> <p>This works especially well when using <code></code> and maybe subdomains of <code></code>: All absolute links will point to <code>localhost:8000</code> or <code>subdomain.localhost:8000</code>. Since <code>*.localhost</code> always resolves to the local IP the browser knows where it should connect to, and since <code>subdomain.localhost:8000</code> also matches the <code>^subdomain\.</code> regex mentioned above, the site selection logic works as well.</p> <p>Of course if you have more domains, not just subdomains, you could adapt the <code>get_host</code> override and the relevant regexes to those use cases.</p> <h3>Closing words</h3> <p>We&rsquo;re at 100% code coverage now when running the test suite. That&rsquo;s really nice.</p> <h2>Logging into the Django admin using your Google account</h2> <p>This functionality has long been provided by <a href="">django-admin-sso</a>; however, as mentioned a long time ago this package still uses a deprecated OAuth2 library. <a href="">django-authlib</a> supports using a Google account to authenticate with the Django admin since 2017. I have now fixed a small problem with it: If you are logged into a single Google account, and this account&rsquo;s email address doesn&rsquo;t match the configured admin login rule, you were out of luck: There was no way to add another account at that time because the library didn&rsquo;t request the account selection. That has changed now, if the first login attempt doesn&rsquo;t work, it now explicitly tells Google to let the user select their Google account. A small quality of life improvement for those using more than one Google account (voluntarily or not).</p> <h2>Releases</h2> <ul> <li><a href="">feincms3 4.4.3</a>: Polished the CKEditor integration a little bit. Re-enabled the source button now that we&rsquo;re back to using the classic iframe-based editor again.</li> <li><a href="">feincms3-sites 0.19.3</a>: See above.</li> <li><a href="">django-authlib 0.16.4</a>: See above.</li> </ul>Weeknotes (2023 week 39)<h1>Weeknotes (2023 week 39)</h1><p>Again a few weeks have passed since the last weeknotes entry :-)</p> <h2>Moving feincms3 repositories into the feincms organization</h2> <p>The <a href="">feincms</a> GitHub organization has seen more active days when FeinCMS 1.x was still actively developed. Since my interest has moved to feincms3 some years ago I haven&rsquo;t kept the organization up to date. That has changed this week, and I have moved most feincms3-related repositories into the organization.</p> <p>This move doesn&rsquo;t change much though, but it certainly feels more official now.</p> <h2>Adding scheduled tests</h2> <p>I have started using the cronjob schedule feature of GitHub actions to ensure that tests run at least once a month in a few important projects. I want to get notified of changes in Django@main affecting my packages not only when actively working on them. I try to keep up with Django@main in all packages I maintain.</p> <h2>Releases</h2> <ul> <li><a href="">feincms3-sites 0.18.2</a>: Many releases in the last weeks. Stopped using permanent redirects in DEBUG mode. Avoid migrations when Django adds more languages. Added utilities which allow restricting model relations to objects in the same site (trickier than it sounds). Added utilities for building full URLs to other sites without taxing the database as much.</li> <li><a href="">feincms3-language-sites 0.2.0</a>: No biggie. No permanent redirects in DEBUG mode anymore.</li> <li><a href="">feincms3-cookiecontrol 1.4.5</a>: Reduced the byte size of the CSS and JavaScript some more. Added spanish translations.</li> <li><a href="">django-authlib 0.16.3</a>: I have published a post last week describing the new <a href="">role-based permissions feature</a>.</li> <li><a href="">django-imagefield 0.17</a>: The <code>process_imagefields</code> management command now allows specifying globs. If you wanted to prerender all imagefields in the pages app you can use <code>./ process_imagefields pages.*</code> now instead of listing all image fields&rsquo; labels explicitly.</li> <li><a href="">feincms3 4.4.1</a>: I&rsquo;m enormously unhappy but I had to go back to the classic CKEditor instead of using the inline editor. The latter looked much nicer but overriding the Django admin CSS was very very painful. Also, I can totally understand why CKEditor 5 is completely different and why CKEditor 4 is only maintained in a paid LTS plan. It still is making me look for alternatives.</li> <li><a href="">django-mptt 0.15</a>: I unfortunately am still using this despite the fact that I have marked it as officially unmaintained since march 2021. I did a mediocre job of making the library run on Django@main again. Parts of the library do not work, but since I&rsquo;m not using them I don&rsquo;t care too much. I&rsquo;m still wondering if someone wants to take over maintenance of the library since it still seems to be actively used in projects of others as well. When I don&rsquo;t have to use django-mptt I&rsquo;m still really happy with <a href="">django-tree-queries</a>.</li> <li><a href="">form-designer 0.22</a>: This is probably my oldest actively developed project these days. 13 years! (Except for django-content-editor of course.) I have modernized the package, switched to hatchling and put out a new release.</li> </ul>Weeknotes (2023 week 33)<h1>Weeknotes (2023 week 33)</h1><p>I&rsquo;m not sure if I should call these posts weeknotes when I see the posting schedule, but oh well. Keep expectations up but also practice forgiveness when not meeting them, it&rsquo;s fine really.</p> <h2><code>py_modules</code> using hatchling</h2> <p>I converted <a href="">speckenv</a> and <a href="">django-sitemaps</a> after finding the following very helpful post on packaging projects consisting of Python modules without any packages: <a href="">Packaging of single Python module projects with Hatch/Hatchling</a>. It&rsquo;s very easy in hindsight, but that&rsquo;s basically always the case.</p> <p>The relevant part is including the files in the build:</p> <div class="chl"><pre><span></span><code><span class="k">[]</span> <span class="n">include</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">[</span> <span class="w"> </span><span class="s2">&quot;;</span><span class="p">,</span> <span class="w"> </span><span class="s2">&quot;;</span><span class="p">,</span> <span class="w"> </span><span class="s2">&quot;;</span><span class="p">,</span> <span class="p">]</span> </code></pre></div> <p>That&rsquo;s all.</p> <h2>django-debug-toolbar and tracing the cause of DB queries in an async world</h2> <p>I have also started investigating what would have to be changed in django-debug-toolbar to make it fully support async Django. We currently patch Django&rsquo;s database cursors per thread, which works fine in sync Django land to attribute SQL queries to a particular request/response cycle.</p> <p>Since async Django executes DB queries in a thread pool executor and the rest of the work happens inside awaitables (async land) I don&rsquo;t immediately see a way how we could do the same thing. It doesn&rsquo;t seem possible to find out which task spawned another task (without dropping down to C?) but maybe there&rsquo;s something I&rsquo;m overlooking. I hope that someone smarter than me finds a way :-) or that I find the time and motivation to either find a way using Python or using C/Rust/whatever.</p> <h2>Releases</h2> <ul> <li><a href="">feincms3-sites 0.16</a>: I added basic support for <code>i18n_patterns</code> when using feincms3-sites with its <code>default_language_middleware</code> (which allows setting a default language per site in case there is no other mechanism overriding it, such as <code>i18n_patterns</code>).</li> <li><a href="">feincms3-cookiecontrol 1.4.1</a>: The privacy policy is now linked inside the banner text instead of adding a link after the text. Looks much nicer.</li> <li><a href="l">speckenv 5.0</a>: Finally released changes made a long time ago which make one edge case when parsing settings less surprising.</li> <li><a href="">django-debug-toolbar 4.2</a>: I didn&rsquo;t do much work here again, mostly code reviews, some changes to the ruff configuration and general polishing. I also didn&rsquo;t do the release itself, that was handled by Tim. Thanks!</li> <li><a href="">FeinCMS 23.8</a>: Fixes for Pillow 10, and some feincms3 / django-content-editor interoperability improvements which make it easier to reuse plugins/content types.</li> <li><a href="">feincms3 4.1</a>: Some basic support for using the apps middleware with async Django. Not documented yet and not deployed anywhere but it basically works. Some documentation edits and changes to the inline CKEditor styling because of the recent changes to Django admin&rsquo;s CSS.</li> </ul>Weeknotes (2023 week 30)<h1>Weeknotes</h1> <h2>Async Django</h2> <p>I have used <a href="">Django Channels</a> successfully in a few projects from 2017 to 2019. A few months back I have worked with <a href="">Starlette</a>. And now I have finally started digging into using Django itself with an ASGI server, and not just for one or two views but also including the middleware stack etc since I also need authentication, not just an endpoint forwarding requests to a remote server. I have looked at <a href="">Granian</a>, an RSGI/ASGI server written in Rust. But for now I am using <a href="">uvicorn</a>.</p> <p>Django truly has come a long way but there&rsquo;s much left to do. Django 5.0 is looking great already, but 4.2 misses many pieces still. I am really really glad Django wants to stay backwards compatible but I wish I could wave a magic wand and upgrade everything to async. Adding <code>a</code> prefixes everywhere for the async version is certainly a good compromise and probably the way to go but it&rsquo;s just not that nice.</p> <p>I have been playing around with making <a href="">feincms3</a>&rsquo;s applications middleware async compatible because I want the full middleware stack to be async. The code is already released but undocumented and not even mentioned in the changelog. So, feel free to play around with it but it&rsquo;s not supposed to be stable or supported yet.</p> <h2>Releases</h2> <ul> <li><a href="">feincms3 4.1</a>: Switched to hatchling and ruff. Updated the feincms3-sites docs. Some async updates mentioned above. A Django 4.2 admin CSS update for the inline CKEditor.</li> <li><a href="">feincms3-forms 0.4</a>: Switched to hatchling and ruff. Started defining default icons for the form fields <a href="">content editor</a> plugins.</li> <li><a href="">django-ckeditor 6.7</a>: I&rsquo;m still maintaining the CKEditor 4 integration for Django even though CKEditor 4 itself isn&rsquo;t supported anymore. Minor updates to the editor itself and Pillow compatibility updates.</li> <li><a href="">feincms3-cookiecontrol 1.3.2</a>: The cookie banner doesn&rsquo;t generate an empty <code>&lt;div class="f3cc"&gt;</code> element anymore if there&rsquo;s nothing to add inside (e.g. if the user only accepted necessary cookies).</li> </ul>Weeknotes (2023 week 29)<h1>Weeknotes</h1> <p>I have mainly done work in private projects this week. Not much to talk about. Except for the ZIP file <code>content-type</code> bug which was interesting enough to justify <a href="">its own blog post</a>.</p> <h2>Releases</h2> <ul> <li><a href="">django-cabinet 0.13</a>: I converted the package to use ruff, hatchling; started running CI tests using Python 3.11. The internals of the Django admin&rsquo;s filters have changed to allow multi-valued filters, this has required some changes to the implementation of the folder filter. I opted to using a relatively ugly <code>django.VERSION</code> hack; but that&rsquo;s not too bad since such branches will be automatically removed by the awesome <a href="">django-upgrade</a>. I would have tried finding other ways in the past but now that old compatibility code can be removed by a single run of <code>django-upgrade</code> (respectively <code>pre-commit</code>) there really is no point to doing it in a different way.</li> </ul>Weeknotes (2023 week 28)<h1>Weeknotes (2023 week 28)</h1><h2>Releases</h2> <ul> <li><a href="">html-sanitizer 2.2</a>: Made the sanitizer&rsquo;s configuration initialization more strict. Strings cannot be used anymore in places where the sanitizer expects a set (resp. any iterable). It&rsquo;s useful that strings are iterable in Python and I wouldn&rsquo;t want to change that, but the fact that <code>("class")</code> is a string and not a tuple makes me sad. The fact that tuples are created by <code>,</code> and not by <code>()</code> will always trip up people.</li> <li><a href="">feincms3-language-sites 0.1</a>: The version number is wrong but whatever. I&rsquo;m certainly happy with the state of things. The big change in 0.1 is that <code>Page.get_absolute_url</code> no longer generates protocol-relative URLs. Depending on the value of <code>SECURE_SSL_REDIRECT</code> it automatically prepends either <code>http:</code> or <code>https:</code>.</li> <li><a href="">django-authlib 0.15</a>: django-authlib&rsquo;s admin Single Sign On module now supports a hook to automatically create staff users when a matching user doesn&rsquo;t exist already. I don&rsquo;t plan to use this functionality myself and I have recommended people to implement the functionality themselves using the tools in django-authlib if they need it, but the change was so small and well-contained that adding it to the core made sense to me.</li> </ul> <h2>pipx inject</h2> <p>We learned that <a href="">pipx</a> seems to remember injected packages even across <code>pipx reinstall</code> invocations. Not too surprising now that we know it, but we certainly spent some time scratching our heads. <code>pipx uninject</code> was the thing we needed to stop pipx from installing an old version of a dependency instead of the one being specified in <code>pyproject.toml</code>.</p> <h2>hatchling and data files</h2> <p>I&rsquo;m very confused by the way <a href="">hatchling</a> sometimes includes data files and sometimes it doesn&rsquo;t. I had to add <code>[] include=["authlib/"]</code> to <a href="">django-authlib&rsquo;s <code>pyproject.toml</code> file</a> to make it include HTML files from subpackages. Maybe the subpackages are the reason, but I&rsquo;m not sure.</p> <h2>Payment providers that must not be named</h2> <p>I have spent hours and hours battling with the badly documented, incomplete, inconsistent and confusing API of a (not that well known) payment provider based in Switzerland. I&rsquo;m surprised that this still happens years and years after Stripe started offering a really well thought out and documented API geared towards programmers. It&rsquo;s really sad because when the same structure is named with differing naming conventions (e.g. <code>snake_case</code> vs. <code>camelCase</code>) in different parts of the API you just know that somebody spent too much time writing too much code instead of reusing already existing functionality.</p>Weeknotes (2023 week 26)<h1>Weeknotes (2023 week 26)</h1><h2>Releases</h2> <p>I released updates to a few of my packages; I have continued converting packages to <a href="">hatchling</a> and <a href="">ruff</a> while doing that.</p> <p>New releases in the last two weeks include:</p> <ul> <li><a href="">django-tree-queries 0.15</a>: Added a new function, <code>.without_tree_fields()</code> to the queryset which can be used to avoid the <code>.with_tree_fields(False)</code> boolean trap warning.</li> <li><a href="">feincms3-cookiecontrol 1.3.1</a>: This small update allows replacing the feincms3 <a href=""></a> oEmbed code using other libraries such as <a href="">micawber</a> which support a wider range of URLs while still gating the embed behind users&rsquo; explicit consent.</li> <li><a href="">feincms3-downloads 0.5.3</a>: Updated translations.</li> <li><a href="">django-ckeditor 6.6.1</a>: Updated the bundled CKEditor 4 and merged a pull request adding better integration with Django admin&rsquo;s dark mode.</li> <li><a href="">django-js-asset 2.1</a>: Just basic maintainability and packaging updates. The <code>JS()</code> implementation itself is untouched since February 2022.</li> <li><a href="">html-sanitizer 2.0</a>: Not really a backwards incompatible change (at least not according to the tests); I just wanted to avoid <code>1.10</code> and go directly to <code>2.0</code> this time.</li> </ul> <h2>GitHub projects</h2> <p>We are using GitHub project boards more and more. It definitely isn&rsquo;t the most versatile way of managing projects but it sort-of hits the sweet spot for us. I&rsquo;m mostly happy with it, and it seems to me that applying <a href="">the rule of least power</a> to project management software may not be such a bad idea after all.</p> <p>The built-in workflows are a bit boring and limited; especially the fact that it seems impossible to automatically add issues to the project when using multiple repositories. Luckily, <a href="">actions/add-to-project</a> exists so that&rsquo;s not really a big problem.</p> <h2>To cloud or not</h2> <p>I had a long discussion with a colleague about containerization, Kubernetes, self-hosting, etc. etc. and I still don&rsquo;t know where I stand. I can honestly say that the old way of hosting (ca. 2010) still works fine. I worry about the deterioriation of service quality we&rsquo;re seeing and sometimes I really would like to have root to apply quick fixes where now I have to jump to hoops just to get what I already know I need. Annoying. But migrations are annoying as well.</p> <h2>Scheduled publishing</h2> <p>I augmented the script generating this website with scheduled publishing support while again reducing the number of lines in the file. The code is still formatted using black and ruff, while only ignoring line-length errors (I do this everywhere now to avoid breaking up long strings, not to put much code onto single lines) and allowing named lambdas. The weeknotes from two weeks ago where published by GitHub actions&rsquo; cron scheduling support.</p> <h2>I like programming more than writing (even though I like writing)</h2> <p>I notice that writing is the first thing I start skipping when I have to prioritize. Programming, biking, gardening come first. That&rsquo;s fine, really. But I&rsquo;m still a bit sad that I do not manage to at least put out a short weekly weeknotes entry.</p>Weeknotes (2023 week 24)<h1>Weeknotes (2023 week 24)</h1><p>Life happened and I missed a month of weeknotes. Oh well.</p> <h2>django-debug-toolbar 4.1</h2> <p>We have released <a href="">django-debug-toolbar 4.1</a>. Another cycle where I mostly contributed reviews and not much else. Feels great :-)</p> <h2>Going all in on hatch and hatchling</h2> <p>I got to know hatch because django-debug-toolbar was converted to it. I was confused as probably anyone else with the new state of packaging in Python world. After listening to a few Podcasts (for example <a href="">Hatch: A Modern Python Workflow</a>) I did bite the bullet and started converting projects to hatch as mentioned <a href="">some time ago</a>. I have converted a few other projects in the meantime because the development experience is nicer. Not much, but enough to make it worthwile. <a href="">feincms3-sites</a> is the latest package I converted.</p> <h2>CKEditor 5&rsquo;s new license and django-ckeditor</h2> <p>The pressure is on to maybe switch away from CKEditor 4 since it probably will not be supported after <a href="">June 2023</a>. It&rsquo;s totally understandable that the CKEditor 5 license isn&rsquo;t the same as before, but I&rsquo;m not sure what that means for the Django integration <a href="">django-ckeditor</a> which I&rsquo;m maintaining since a few years. I don&rsquo;t actually like the new capabilities of CKEditor all that much and don&rsquo;t intend to use them; maybe it would be better to use a build of <a href="">ProseMirror</a> in the CMS since <a href="">we&rsquo;re intentionally only using a very small subset of the features most rich text editors offer</a>.</p> <h2>Mountain biking.</h2> <p>My mountain bike is repaired, I&rsquo;m back on the trail.</p>Weeknotes (2023 week 18 and 19)<h1>Weeknotes (2023 week 18 and 19)</h1> <p>Not much programming this week :-(</p> <h2>oEmbed</h2> <p><a href="">Still occupying myself with oEmbed.</a> I have been looking at a few libraries and have rediscovered <a href="">micawber</a> which probably does everything I need. Yay, another reinvented wheel avoided. I haven&rsquo;t tested it yet but I&rsquo;m quite sure that replacing the <a href="">oEmbed functionality in feincms3&rsquo;s external plugin</a> with micawber would be a good idea.</p> <h2>Vacation</h2> <p>Vacation last week. Was nice. We went for a few hikes. I have learned that I&rsquo;m not totally free from giddiness anymore. Oh well.</p>Weeknotes (2023 week 17)<h1>Weeknotes (2023 week 17)</h1><h2>Birthday</h2> <p>Another year achieved. Feels the same as last year. I&rsquo;m glad.</p> <h2>feincms3-cookiecontrol</h2> <p>I have released <a href="">feincms3-cookiecontrol 1.3</a>. Mostly cleanups since 1.2, but also a new translation (already announced here). The script size has been reduced from 4519 bytes to 4228 bytes (-6.5%) while keeping all features intact. The reduction is totally meaningless but it was fun to do.</p> <h2>oEmbed</h2> <p>I have been digging into the oEmbed spec a bit. I didn&rsquo;t even know that a central list of <a href="">providers</a> exists. <a href="">Noembed</a> still works great to embed many different types of content but I worry more and more about its maintenance state. Reimplementing the interesting parts shouldn&rsquo;t be that hard, but maybe I don&rsquo;t have to do this myself. <a href="">oEmbedPy</a> looks nice, I hope I get a chance to play around with it.</p>