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.