Albin Larsson: Blog

Culture, Climate, and Code

Quick Links in Django Admin

12th January 2023

Whenever you are viewing a model-page in Django’s admin-interface there is a sidebar to the left giving you quick access to other models:

Screenshot of the default sidebar on a model page.

This sidebar, however, isn’t utilized on the start/index page. By enabeling the sidebar we can get space for various types of shortcuts and links that can be useful to admins. The sidebar will also fit right into Django’s structure and style.

Screenshot of a sidebar with quick links on Django's admin index.

By creating templates/admin/index.html in our ocal project we can override the default admin index from Django an replace it with our own. Because the default page contains the template block hosting the navbar, even through it’s unused we can extend the existing Django’s template and reuse the pattern/semantics used by the sidebar eslewhere.

Here is an example creating two sidebar sections with two links each:

{% extends "admin/index.html" %}

{% block nav-sidebar %}
{% load i18n %}
<button class="sticky toggle-nav-sidebar" id="toggle-nav-sidebar" aria-label="{% translate 'Toggle navigation' %}"></button>
<nav class="sticky" id="nav-sidebar">
    <input type="search" id="nav-filter"
         placeholder="{% translate 'Start typing to filter…' %}"
         aria-label="{% translate 'Filter navigation items' %}">
    <div class="module">
                <th scope="row"><a href="#">Email</a></th>
                <th scope="row"><a href="#">Report Bug</a></th>
    <div class="module">
                <th scope="row"><a href="#">Repository</a></th>
                <th scope="row"><a href="#">Backlog</a></th>
{% endblock %}

Python Dependencies and Flatpak

7th November 2022

I’m learning how to create responsive Gnome applications with Python, GTK4, and Flatpak. One of the early issues I ran into after I generated a new Python project using Gnome Builder’s built in template was how to make Python dependencies from the Python package index aviable to my app.

I’m currently lacking a good resource describing the solution for my development log, so here is my take.


If you generated your project using Gnome Builder, you likley have a JSON file in the root of your project directory it bears the name of your application identifier. This file, it turns out, is called a Flatpak mainfest.

It contains a section called “modules” which in my case is an array containing a single object(module for the application itself). This array, however, does not only take objects. It also takes strings/paths to other manifests.

For each of one’s PIP dependecies we need a module definations. Once generated, module sections might remind you of lock-files. It would be cubersome to create these “manually” or induvidually. So there is a “Flatpak PIP Generator” script that among, other things, that can generate these module definations given a requirements.txt file.

Put the flatpak-pip-generator script in the root of your project(you might want to add it to your .gitignore). Then create a requirements.txt file containing all your direct dependecies and then run:

./flatpak-pip-generator -r requirements.txt -o python-deps

The above should have generated a Flatpak manifest file named python-deps.json in the root of your project, containing one module defination for each dependency.

In the “modules” section in the initial Flatpak maifest one can then add a new entry python-deps.json. Now your app should build and run with all the dependecies avaible. If it dosn’t run make sure you clean and rebuild the project as the module configs might be cached.

Final notes

Here are some of the resources that I used while tinkering with the above: Flatpak documentation, a StackOverflow question and a Gnome Discourse question.

Incognito User Agents

16th October 2022

User Agent spoofing isn’t news and is necessary for many Internet users. Today, however, I noticed something I hadn’t earlier. User Agent spoofing causing analytics and security services to report the wrong operating system and browser altogether.

I logged into Twitter from GNOME Web on a PostmarketOS device, and the login notice I received a while later told me I had logged in from an Android device using Google Chrome.

Mozilla/5.0 (Linux;Android 10; Pixel) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.96 Mobile Safari/537.36

It turns out that GNOME Web doesn’t expose Linux distro or what browser I’m using by default. That’s all good, as it reduces the ability for webpages to successfully sniff user agents in the first place. Tor Browser and others uses this approach for improved privacy.

I can’t resist wondering to what extent this cements the notion of Chrome and Edge having all of the browser market. Possibly not so much as my case is a very uncommon one. It’s still interesting to think about.

Wikimedia Commons Upload Campaigns for Cultural Heritage

13th April 2022

Since the first Swedish edition of Wiki Loves Monuments in 2011, participants have uploaded almost 30 000 images of heritage sites, protected buildings, ships, and working life museums.

Wiki Loves Monuments (WLM) goes on for 30 days per year. While many experienced users take images all year round for the event, many new contributors are introduced to WLM and the broader Wikimedia community for the first time through the 30-day event. What if there was a just as engaging effort for documenting heritage environments that would go on not for 30 days a year, but for 365?

Wiki Loves Monuments builds to an extent upon a Wikimedia Commons called Campaigns. Campaigns make it possible to construct upload forms with a set of predefined values or have default values passed through Campaigns URLs.

Much of the Wiki Loves Monuments tooling (maps, lists, etc) uses WLM specific Campaigns to define values for things like the identifiers of monuments and sites. It’s super easy to create these links:<museum-identifier>

However, it’s not that easy to reuse these Campaigns for non-WLM usage. The help texts are WLM specific, they set WLM-specific categories, etc. Nor is it easy to create a new Campaign. You will need special user rights and experience with JSON and Wikitext.

So rather than to set up tool-specific Campaigns, what if we had generic ones that any tool could integrate without needing to worry about set up and help texts?

Such Campaigns now exist thanks to Wikimedia Sverige’s community support! It doesn’t matter if you want to crowdsource images from a spreadsheet or if you are a programmer wanting to integrate uploading into your tool or app. You can use these Campaigns.

Two tools already utilizing these Campaigns are Kyrksö (database of churches in Sweden) and (FornPunkt is a citizen-science platform for historic sites).

You can create upload links for these Campaigns similarly to how one does it for WLM:<monument-identifier>

The 30 000 images contributed through Wiki Loves Monuments add to the tens of thousands of images uploaded by individual contributors and cultural heritage institutions. Today Wikimedia Commons has the largest public collection of images depicting Swedish heritage sites. Wikimedia Commons is, therefore, an important and open piece of infrastructure for cultural heritage in Sweden. It’s utilized by various organizations, including the Swedish National Heritage Board and its website “Kringla” which indexes Wikimedia Commons once every week.

By creating these generic and easy-to-use Campaigns, the hope is to lower the barrier for integrations to contribute to this public collection of information. Your aim does not need to be to create the next Wiki Loves Monuments.

Older Posts