Django: Serialize a list of multiple linked models
Waldemar Edward Sandel Rolfson
Given two different models, they have the same parent base class. Is it possible to serialize a linked list containing instances of two child models using the Django Rest Framework serializer or serpy?
Given some example models:
class BaseModel(models.Model):
created_at = models.DateField()
class Meta:
abstract = True
class ChildModel1(BaseModel):
field_one = models.TextField()
class ChildModel2(BaseModel):
field_two = models.TextField()
There is also an example view:
def get(self, request):
q1 = ChildModel1.objects.all()
q2 = ChildModel2.objects.all()
chained_list = sorted(
chain(q1, q2),
key=attrgetter('created_at'))
serializer = BaseModelSerializer(chained_list, many=True)
The way to link the models comes from the answer to this question .
With my current attempts, I get a pretty obvious error like:
AttributeError: 'ChildModel1' object has no attribute 'field_two'
I know it's not best practice to combine both models with different domains, but in my case I think it's necessary.
Some examples of serializers I've tested:
First example:
class BaseModelSerializer(serializers.ModelSerializer):
class Meta:
model = BaseModel
Second example:
class BaseModelSerializer(serpy.Serializer):
created_at = serpy.StrField()
field_one = serpy.StrField(required=False)
field_two = serpy.StrField(required=False)
yeast
You can define serializers that will combine two or more serializers based on the model:
class Model1Serializer(serializers.Serializer):
...
class Model2Serializer(serializers.Serializer):
...
class SummarySerializer(serializers.Serializer):
""" Serializer that renders each instance with its own specific serializer """
@classmethod
def get_serializer(cls, model):
if model == Model1:
return Model1Serializer
elif model == Model2:
return Model2Serializer
def to_representation(self, instance):
serializer = self.get_serializer(instance.__class__)
return serializer(instance, context=self.context).data
This will work on any model, not just a class of children.