Hello Simon,
I'm going to paste a trimmed-down version of the involved classes:
class CeleryTask(models.Model):
celery_task_id = models.CharField(max_length=50, primary_key=True)
task_type = models.ForeignKey(ContentType)
task_id = models.PositiveIntegerField()
task = GenericForeignKey('task_type', 'task_id')
class AccountManagementTask(models.Model):
account = models.ForeignKey(Account, null=True, editable=False)
task_content_type = models.ForeignKey(ContentType)
task_content_id = models.PositiveIntegerField()
task_content = GenericForeignKey('task_content_type', 'task_content_id')
celery_task = GenericRelation(CeleryTask, content_type_field='task_type', object_id_field='task_id',
related_query_name='account_management_tasks')
(the task_content thing is involved in a follow-up question that will be asked in a short while)
This is the code triggering the weirdness:
previous_tasks = AccountManagementTask.objects.filter(account=account)\
.prefetch_related(
Prefetch('celery_task',
to_attr='celery_task'))\
.prefetch_related(
Prefetch('task_content',
to_attr='task_content'))\
.annotate(created_on=F('celery_task__created_on'))\
Immediately after that, the QuerySet is sent off to a simple DRF serializer - which doesn't even touch the issue since the relevant piece of information is annotated:
class AccountManagementTaskSerializer(serializers.ModelSerializer):
def to_representation(self, instance):
'created_on': instance.created_on,
'date_from': instance.task_content.date_from,
'date_to': instance.task_content.date_to}
class Meta:
model = AccountManagementTask
Now the follow-up, that you might already have guessed: if I *do* use the same name for following the GenericForeignKey relation (task_content), the content of the relationship does not get deleted(no surprise there..?) and I can go with my naïve serialization over there, while if I specify a different to_attr name I get back a list and I have to deal differently with that.
How do these prefetch_related / Prefetch to_attr / Generic* things really work?
Merci beaucoup,
Michele