Annotated model fields – consistent access in model meta, reverse foreign keys

Skip to first unread message


Aug 5, 2022, 5:11:30 AM8/5/22
to Django users
Dear community,

here’s a question/thought about how you handle annotated fields.

Here’s my use case:

from django import models

class Person(models.Model):
    given_name = models.CharField(max_length=100)
    family_name = models.CharField(max_length=100)
    # Some people prefer a different name
    preferred_name = models.CharField(max_length=200, blank=True, null=True)    

I’d like to have a field `full_name` that is annotated whenever I fetch data from the database (`@property def full_name(self): …` doesn’t work for me).

It should return the `preferred_name` (if present) or join `given_name` and `family_name`.

I was happy to accomplish this by using a custom manager:

from django.db.models.functions import Coalesce, Concat
from django.db.models import CharField, Value

class PersonManager(models.Manager):
    def get_queryset(self):
        qs = super().get_queryset()
        # The annotation details don’t matter, actually.
        return qs.annotate(
                Concat(F('given_name'), Value(' '), F('family_name')),
# … and add `objects = PersonManager()` to person model.

When querying directly, this works nicely: `Person.objects.first().full_name` returns the full name.

Though, when following a reverse foreign key relation, things go wrong:

class Restaurant(models.Model):
    name = models.CharField(max_length=100)
    owner = models.ForeignKey(Person, on_delete=models.SET_NULL)

# gives an exception, because the custom manager’s code isn't executed.
I read that you can set the `base_manager_name` on the `Person`’s meta class, but I didn’t have luck with that either.
Moreover, you can’t use the `full_name` for ordering on the Person’s meta class.

Long story short: What’s your preferred way that allows access to annotated properties consistently?
(I was thinking about custom `AnnotatedCharField`s, `AnnotatedTextField`s etc. that allow defining annotated fields on the model itself. Tempting, huh?)

Looking forward to your comments!

Best regards


Aug 5, 2022, 5:20:27 AM8/5/22
to Django users
Reply all
Reply to author
0 new messages