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(
            full_name=Coalesce(
                F('preferred_name'),
                Concat(F('given_name'), Value(' '), F('family_name')),
                output_field=CharField()
            )
        )
        
# … 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)
```

```
Restaurant.objects.first().owner.full_name
# 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
Julian








-- 
You received this message because you are subscribed to the Google Groups 
"Django users" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To view this discussion on the web visit 
https://groups.google.com/d/msgid/django-users/8ba00d6b-c7a2-43cf-9f0f-4bbe6293ecf7n%40googlegroups.com.

Reply via email to