Skip to content

Sortierung in Textfeldern mit Zahlen sollte natural-sort nutzen

Textfelder, die Zahlen enthalten (wie topic_code), werden aktuell nicht korrekt sortiert.

Die aktuelle Sortierung sieht z.B. so aus.

  1. 1
  2. 10
  3. 2

Sollte aber folgendermaßen aussehen:

  1. 1
  2. 2
  3. 10

Das Problem lässt sich wahrscheinlich gut über eine andere Collation lösen. Django unterstützt seit v3.2 das db_collation-Argument bei CharField.

Hier sind ein paar Hinweise zu passenden Collations:

Die Namen der Collations sind allerdings nicht genormt, sodass wir wahrscheinlich Datenbank-spezifische Migrationen brauchen, um sie zu konfigurieren. Außerdem müssen wir ggf. schauen, ob wir überhaupt für alle Datenbanken passende Collations wählen können. PostgreSQL ist unabdingbar, SQLite wäre schön.

Datenbank-spezifische Migrationen habe ich bereits früher einmal folgenderweise gelöst:

class DatabaseEngineMigrationSelector:
    """
    Database Router implementation that skips migrations if the migration specifies
    a required database engine and the currently configured database does not match.
    Can be controlled through the hints dictionary in any migration like this:
        # only run on PostgreSQL
        migrations.RunSQL(
            ...,
            hints=dict(required_database_engine='postgresql'),
        )
    """

    def allow_migrate(
        self,
        db,
        app_label,
        required_database_engine: typing.Union[set[str], str, None] = None,
        **hints,
    ):
        if required_database_engine is not None:
            from django.conf import settings

            if isinstance(required_database_engine, str):
                required_database_engine = {required_database_engine}
            used_engine_name = settings.DATABASES[db]["ENGINE"].rsplit(".", 1)[1]
            should_execute = any(engine in used_engine_name for engine in required_database_engine)
            if not should_execute:
                logging.warning(
                    f"Skipping a migration because the current database engine "
                    f"does not match the database engine required for its execution. "
                    f"{' or '.join(required_database_engine)} was required, "
                    f"but {used_engine_name} is configured."
                )
                return False
        return None

# in django settings
DATABASE_ROUTERS = ["path.to.module.DatabaseEngineMigrationSelector"]
Edited by Konrad Mohrfeldt