0

EDIT: I just noticed that the below described behavior only appears on my dev machine and not on the production server. On the productin server it is ordered as desired. It must be something in the settings of my PostgreSQL servers.

I have a Django app with the following models that have the ordering set with class Meta:

class Akutsomatik(models.Model):
    bereichname = models.CharField(max_length=200)

    class Meta:
        ordering = ['bereichname']

    def __str__(self):
        return self.name

# This model is only included in the example for better understanding
class Klinik(models.Model):

    name = models.CharField(max_length=200)
    akutsomatik = models.ManyToManyField(Akutsomatik, blank=True)

    def __str__(self):
        return self.name

And my template:

{% if klinik.akutsomatik.all %}
    <ul>
      {% for akutsomatik in klinik.akutsomatik.all %}
      <li>{{ akutsomatik }}</li>
      {% endfor %}
    </ul>
{% endif %}

The problem is that the data of my app is in German and the ordering is set to UTF-8. The output would look something like that:

Augenchirurgie / Ophtalmologie
Brustchirurgie
Viszeralchirurgie
Wiederherstellende Chirurgie
Ästhetische Chirurgie

but in German it should be like:

Ästhetische Chirurgie
Augenchirurgie / Ophtalmologie
Brustchirurgie
Viszeralchirurgie
Wiederherstellende Chirurgie

Note that Ästhetische Chirurgie should come before Augenchirurgie / Ophtalmologie.

Does anyone know if there is a way to set the collation in class Meta? I tried the following as decribed here:

from django.db.models import Func

class Meta:
        ordering = [Func('bereichname',
                         function='utf8_general_ci',
                         template='(%(expressions)s) COLLATE "%(function)s"')
        ]

But I get the following template error:

collation "utf8_general_ci" for encoding "UTF8" does not exist
LINE 1: ...ER BY ("klinik_finder_akutsomatik"."bereichname") COLLATE "u...

I also tried to set functionto function='de_DE'. It gives me no error but the ordering also does not change (after makemigrations and migrate).

Maybe someone can guide me in the right direction. Thanks.

didierCH
  • 378
  • 2
  • 17
  • Added as edit: I just noticed that the below described behavior only appears on my dev machine and not on the production server. On the productin server it is ordered as desired. It must be something in the settings of my PostgreSQL servers. – didierCH Apr 21 '21 at 09:18

1 Answers1

1

From Django version 3.2 onwards you can specify the collation for a CharField or a TextField directly in the field itself using the kwarg db_collation [Django docs]:

class Akutsomatik(models.Model):
    bereichname = models.CharField(max_length=200, db_collation='utf8_general_ci')
    ...

Moving on it seems your error is because the collation you use is not present in PostgreSQL, and its equivalent collation that you can use is und-x-icu, as noted in this question: Install utf8 collation in PostgreSQL. So if you replace utf8_general_ci with und-x-icu your solution should work.

Abdul Aziz Barkat
  • 19,475
  • 3
  • 20
  • 33
  • Can not use Django 3.2 on this project, but thanks for pointing to the new options. The second hint, setting `und-x-icu`, worked. Thanks. – didierCH Apr 21 '21 at 13:49