I have a class that has multiple references to the same generic class for different information:
class Resort(models.Model):
id = models.PositiveIntegerField(_('HapNr.'), primary_key=True)
symbol = models.CharField(_('Kurzzeichen'), max_length=3, blank=True)
short_description = GenericRelation('MultiLingualText',
verbose_name=_('Beschreibung (ML)'),
related_query_name='resortshortdescriptions')
long_description = GenericRelation('MultiLingualText',
verbose_name=_('Einleitung (ML)'),
related_query_name='resortlongdescription')
class MultiLingualText(models.Model):
language = models.ForeignKey(hmodels.LanguageCode, verbose_name=_('Sprache'))
valid_from = models.DateField(_('Gültig ab'), default=timezone.now)
text = models.TextField(_('Text'))
content_type = models.ForeignKey(ContentType, verbose_name=_('Typ'))
object_id = models.PositiveIntegerField()
content_object = GenericForeignKey()
atu_id = models.CharField(_('ATU Text Id'), max_length=12, editable=False, blank=True)
atu_context = models.CharField(_('ATU Kontext'), max_length=1, editable=False, blank=True)
When I need to work with this class using the Django Admin I have two Inlines, each with a queryset selecting the correct texts for that relation. This works fine.
I tried doing something similar by using individual serializers and viewsets for each relation, but when I retrieve a resort, it still shows all texts with each relation.
class ResortSerializer(serializers.HyperlinkedModelSerializer):
short_description = MultiLingualTextSerializerRSD(many=True, read_only=True)
long_description = MultiLingualTextSerializerRLD(many=True, read_only=True)
class Meta:
model = Resort
class MultiLingualTextSerializerRSD(serializers.HyperlinkedModelSerializer):
language = serializers.PrimaryKeyRelatedField(read_only=True)
class Meta:
model = MultiLingualText
class MultiLingualTextViewSetRSD(viewsets.ModelViewSet):
serializer_class = MultiLingualTextSerializerRSD
queryset = MultiLingualText.objects.exclude(atu_id='').order_by('resort', 'content_type', 'object_id',
'-valid_from')
class ResortViewSet(viewsets.ModelViewSet):
queryset = Resort.objects.all().order_by('id')
serializer_class = ResortSerializer
filter_backends = (filters.DjangoFilterBackend,)
filter_fields = ('id', 'sihot_nr')
So basically my question is, how can I use different querysets for each set of texts? Or is this at all possible?
Correct implementation (Thanks to @lucasnadalutti)
class ResortSerializer(serializers.HyperlinkedModelSerializer):
short_description = serializers.SerializerMethodField()
long_description = serializers.SerializerMethodField()
def get_short_description(self, obj):
qs = MultiLingualText.objects.exclude(atu_id='').order_by('-valid_from', 'language__code')
return MultiLingualTextSerializer(qs, many=True, read_only=True).data
def get_long_description(self, obj):
qs = MultiLingualText.objects.filter(atu_id='').order_by('-valid_from', 'language__code')
return MultiLingualTextSerializer(qs, many=True, read_only=True).data
MultiLingualTextViewSetRSD
does not make much sense in this context, as what you want is to send the resorts and their descriptions in one request only, as it should be. In ordinary ForeignKey
model field relations, I'm pretty sure that ResortSerializer
would serialize only its related records as you expected, but I'm not sure about how DRF serializers work with generic relations.
That said, one solution would be to replace:
short_description = MultiLingualTextSerializerRSD(many=True, read_only=True)
long_description = MultiLingualTextSerializerRLD(many=True, read_only=True)
with:
short_description = SerializerMethodField()
long_description = SerializerMethodField()
And implement your filtering-and-serialization inside get_short_description
and get_long_description
methods. Another solution is to remove both attributes and place this logic inside your serializer's to_representation
method.