How to show fields from another serializer in Django rest framework - django

I want to show extra fields in response, showing similar products or related products in the category while am in a product detail page.
Eg:
If am viewing a single product detail page and in the bottom of page the related products list must be also show there. So while in response of related products, I want to showhighest_offer_price, product_offer_discount, category_offer_discount of ProductDetailserilaizer.
#Serializer.py
class RelatedProductSerializer(ModelSerializer):
class Meta:
model = Products
fields = ['product_name', 'slug', 'base_price', 'images']
class ProductDetailserializer(ModelSerializer):
product_offer_discount = SerializerMethodField()
category_offer_discount = SerializerMethodField()
highest_offer_price = SerializerMethodField()
description = ProductDescription()
extra_images = SerializerMethodField()
related_products = SerializerMethodField()
class Meta:
model = Products
fields = [
"id",
"product_name",
"slug",
"highest_offer_price",
"category_offer_discount",
"product_offer_discount",
"description",
"base_price",
"stock",
"is_available",
"images",
"extra_images",
"related_products"
]
def to_representation(self, instance):
print('INSTANCE', instance)
rep = super().to_representation(instance)
rep['description'] = ProductDescriptionSerializer(instance.description, many=True).data
return rep
def get_related_products(self, obj):
products= Products.objects.filter(category=obj.category).exclude(id=obj.id)
return RelatedProductSerializer(products, many=True, context=self.context).data
def get_extra_images(self, obj):
images = obj.extra_images.all()
return ProductImageSerializer(images, many=True, context=self.context).data
#Views.py
class ProductDetailView(APIView):
def get(self, request, category_slug, product_slug):
try:
single_product = Products.objects.get(
category__slug=category_slug, slug=product_slug
)
except:
raise exceptions.NotFoundError()
serializer = ProductDetailserializer(
single_product, context={
"request": request,
}
)
return Response(serializer.data)
#Response
{
"id": 1,
"product_name": "Pendant 1",
"slug": "pendant-1",
"highest_offer_price": null,
"category_offer_discount": null,
"product_offer_discount": null,
"description": [
{
"title": "First title",
"description": "First description pendant 1"
},
{
"title": "second title",
"description": "second description pendant 1"
}
],
"base_price": 2500,
"stock": 97,
"is_available": true,
"images": "http://127.0.0.1:8000/media/photos/products/pendant3.webp",
"extra_images": [
{
"images": "http://127.0.0.1:8000/media/photos/product-images/pendant3.webp"
},
{
"images": "http://127.0.0.1:8000/media/photos/product-images/pendant3_BQJRObf.webp"
},
{
"images": "http://127.0.0.1:8000/media/photos/product-images/pendant3_QGmLbXC.webp"
}
],
"related_products": [
{
"product_name": "Pendant 2",
"slug": "pendant-2",
"base_price": 3500,
"images": "http://127.0.0.1:8000/media/photos/products/pendant2.webp"
},
{
"product_name": "Pendant 3",
"slug": "pendant-3",
"base_price": 1500,
"images": "http://127.0.0.1:8000/media/photos/products/281031cw114n.webp"
},
{
"product_name": "pendant 4",
"slug": "pendant-4",
"base_price": 1500,
"images": "http://127.0.0.1:8000/media/photos/products/281031cw114n_Nxbx7lT.webp"
}
]
Am new to this and am complicating it too much i guess Because I have already wrote multiple serializers for Product model.

It's perfectly fine to have multiple serializers for the same model if the data differs between them.
If you're worrying about re-writing the same code multiple times, on different serializers, you could always make a base serializer for your Products model and then extend it as needed.
Like this:
# Make a BaseProductSerializer that inherits from Modelserializer and contains all fields and methods that all Products serializers need.
class BaseProductSerializer(Modelserializer):
product_offer_discount = SerializerMethodField()
category_offer_discount = SerializerMethodField()
highest_offer_price = SerializerMethodField()
def get_product_offer_discount(self):
return # whatever this method should do...
def get_category_offer_discount(self):
return # whatever this method should do...
def get_highest_offer_price(self):
return # whatever this method should do...
# Make a serializer for related products that inherits from BaseProductSerializer and specify the Meta data.
class RelatedProductSerializer(BaseProductSerializer):
class Meta:
model = Products
fields = [
'product_name',
'slug',
'base_price',
'images',
'highest_offer_price',
'product_offer_discount',
'category_offer_discount'
]
# Make a serializer for product details that inherits from BaseProductSerializer and add any extra fields/methods that you need.
class ProductDetailserializer(BaseProductSerializer):
description = ProductDescription()
extra_images = SerializerMethodField()
related_products = SerializerMethodField()
class Meta:
model = Products
fields = [
"id",
"product_name",
"slug",
"highest_offer_price",
"category_offer_discount",
"product_offer_discount",
"description",
"base_price",
"stock",
"is_available",
"images",
"extra_images",
"related_products"
]
def to_representation(self, instance):
print('INSTANCE', instance)
rep = super().to_representation(instance)
rep['description'] = ProductDescriptionSerializer(instance.description, many=True).data
return rep
def get_related_products(self, obj):
products= Products.objects.filter(category=obj.category).exclude(id=obj.id)
return RelatedProductSerializer(products, many=True, context=self.context).data
def get_extra_images(self, obj):
images = obj.extra_images.all()
return ProductImageSerializer(images, many=True, context=self.context).data
Hope this helps.

Related

How to iterate ManyToMany filed in serializer class

I have this Event model:
# models.py
class Event(models.Model):
name = models.CharField(max_length=200))
user = models.ManyToManyField(User))
This is my ListCreateAPIView class:
class EventListView(LoginRequiredMixin, generic.ListView):
model = Event
This is my ListCreateAPIView class:
class Events(generics.ListCreateAPIView):
permission_classes = (IsAuthenticated,)
queryset = Event.objects.all()
serializer_class = EventSerializer
This is my serialiser class:
#serializers,py
class EventSerializer(serializers.ModelSerializer):
class Meta:
fields = (
‘id',
'name',
'user',
)
model = Event
And this is my REST request response:
{
"count": 2,
"next": null,
"previous": null,
"results": [
{
"id": 1,
"name": "My event1",
"user": [
1,
4
],
"registered": true // <—- I NEED THIS
},
{
"id": 2,
"name": "Other event",
"user": [
2,
4,
6
],
"registered": false // <—- I NEED THIS
}
]
}
What I am gonna need in REST response is property “registered”, which will contain true or false if current user is registered on particular event or not.
My approach was to control if current user is in list of users of event. I tried to get this information in serialiser class this way:
#serializers,py
class EventSerializer(serializers.ModelSerializer):
registered = serializers.SerializerMethodField(‘_user’)
def _user(self, obj):
request = getattr(self.context, 'request', None)
if request.user in self.user:
return True
else:
return False
class Meta:
fields = (
‘id',
'name',
'user',
)
model = Event
But I get AttributeError: 'NoneType' object has no attribute 'user'
How can I solve this problem?
You can try like this using exists() with filter method:
class EventSerializer(serializers.ModelSerializer):
registered = serializers.SerializerMethodField(‘_user’)
def _user(self, obj):
request = self.context.get('request', None)
if request and obj.user.filter(pk=request.user.pk).exists():
return True
else:
return False
In view.py add
For This "registered": true // <—- I NEED THIS
model_name.object.filter(column='required value')

Return list of values of one column grouped by another column in Django viewset

Let's say I have a model:
class Entry(models.Model):
content = models.CharField(max_length=140)
email = models.EmailField()
upload_date = models.DateTimeField(default=timezone.now)
class Meta:
db_table = 'entries'
What I want to achieve is the viewset to return list of content and upload_date values per single email (since many entries can have the same email value), like that:
[
{
"email": "address1#test.test",
"entries": [
{
"upload_date": "2020-09-03",
"content": "test content 1"
},
{
"upload_date": "2020-09-02",
"content": "test content 2"
},
...
]
},
{
"email": "address2#test.test",
"entries": [
{
"upload_date": "2020-09-03",
"content": "test content 11"
},
{
"upload_date": "2020-09-02",
"content": "test content 12"
},
...
]
},
...
]
I tried messing around with .values() and .annotate(), but with no luck.
Quick answer with groupby itertools function :
def entry_converter(entry):
return {'upload_date': entry.upload_date, 'content': entry.content}
def grouping_key(entry):
return entry.email
from itertools import groupby
entries = Entry.objects.order_by('email')
grouped_entries = [dict(email=key, entries=list(map(entry_converter, group))) for key, group in groupby(entries, key=grouping_key)]
Update 1
Integration with DRF ViewSet
def entry_converter(entry):
return {'upload_date': entry.id, 'content': entry.id}
def grouping_key(entry):
return entry.email
def group_entries(entries):
return [
dict(email=key, entries=list(map(entry_converter, group))) for key, group in groupby(entries, key=grouping_key)
]
class EntrySerializer(ModelSerializer):
class Meta:
model = Entry
fields = '__all__'
class EntryViewSet(ModelViewSet):
queryset = Entry.objects.all()
serializer_class = EntrySerializer
def list(self, request, *args, **kwargs):
queryset = self.get_queryset().order_by('email')
data = group_entries(queryset)
page = self.paginate_queryset(data)
if page is not None:
return self.get_paginated_response(page)
return Response(data)
Keep in mind that I haven't used .filter_queryset() method of ModelViewSet as it may modify the queryset by adding wrong ordering or wrong filtering. Because groupby function needs sorted data as an input. Also, I have not overridden ModelSerializer class for generalizing .list() method of ModelViewSet as it may create extra complexity.

Direct assignment to the reverse side issue with multiple nested serializer

I have this issue while running some test on my django project:
TypeError: Direct assignment to the reverse side of a related set is prohibited. Use files.set() instead.
Here is what I try to post
{
"daily_hash": "w54c6w546w5v46w5v4",
"modules": [
{
"module": "main",
"commits": [
{
"commit_hash": "11feb543f016114c700046d42b912910321230da",
"author": "Test name 1",
"subject": "[TICKET] Subject of the issue",
"files": []
},
{
"commit_hash": "093b19f710c6d2358b0812434dfcf1549c9c6fbb",
"author": "Test name 1",
"subject": "[TICKET] Subject of the issue",
"files": []
}
]
},
{
"module": "submodule",
"commits": [
{
"commit_hash": "dce22dea52a6a4b7160034d3f84a7af7b389ee96",
"author": "Test name 3",
"subject": "[TICKET] Subject of the issue",
"files": [
{
"name": "my_file_1.c"
},
{
"name": "my_file_2.c"
}
]
},
{
"commit_hash": "cee433fc4ab46464afb96d6ecae2839409fe0313",
"author": "Test name 4",
"subject": "[TICKET] Subject of the issue",
"files": []
},
{
"commit_hash": "4534f511b2a6a8c1632a1ab97b598d8e4dedada7",
"author": "Test name 1",
"subject": "[TICKET] Subject of the issue",
"files": []
}
]
}
]
}
You can find below my models.py:
from django.db import models
from status.models import Daily
class Component(models.Model):
"""
Component model
"""
module = models.CharField(max_length=40)
daily = models.ForeignKey(Daily, on_delete=models.CASCADE)
class Meta:
db_table = 'gds_component'
class Commit(models.Model):
"""
Commits model
"""
commit_hash = models.CharField(max_length=40)
author = models.CharField(max_length=60)
subject = models.CharField(max_length=250)
component = models.ForeignKey(
Component, related_name='commits',
on_delete=models.CASCADE)
class Meta:
db_table = 'gds_commit'
class File(models.Model):
"""
Commit files model
"""
name = models.CharField(max_length=250)
commit = models.ForeignKey(
Commit, related_name='files',
on_delete=models.CASCADE)
class Meta:
db_table = 'gds_commit_file'
My serializer here:
class FileSerializer(serializers.ModelSerializer):
class Meta:
model = models.File
exclude = ['commit']
class CommitSerializer(serializers.ModelSerializer):
files = FileSerializer(
required=False,
allow_null=True,
many=True
)
class Meta:
model = models.Commit
fields = ('commit_hash', 'author', 'subject', 'files')
def create(self, validated_data):
files_valid_data = validated_data.pop('files')
commit = models.Commit.objects.create(**validated_data)
for file_data in files_valid_data:
models.File.objects.create(commit=commit, **file_data)
return commit
class CompoSerializer(serializers.ModelSerializer):
commits = CommitSerializer(
required=False,
allow_null=True,
many=True
)
class Meta:
model = models.Component
fields = ('module', 'daily', 'commits')
def create(self, validated_data):
commits_valid_data = validated_data.pop('commits')
component = models.Component.objects.create(**validated_data)
for commit_data in commits_valid_data:
models.Commit.objects.create(component=component, **commit_data)
return component
And finally my view.py
#api_view(['POST'])
def post_commit(request):
if request.method == 'POST':
# Get the md5 hash to get it's id
valid_data = request.data
hash_data = valid_data.pop('daily_hash')
try:
daily_obj = Daily.objects.get(daily_key=hash_data)
except Daily.DoesNotExist:
return Response(status=status.HTTP_404_NOT_FOUND)
# Add daily_id to all modules
serializer_data = valid_data.pop('modules')
for elem in serializer_data:
elem['daily'] = daily_obj.id
# Serialize the data
serializer = serializers.CompoSerializer(data=serializer_data, many=True)
if serializer.is_valid():
serializer.save()
return Response(serializer.data, status=status.HTTP_201_CREATED)
# throw an error if something wrong hapen
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
I tried so many things and now i'm totally lost. I think the issue is because I have multiple nested serializer but I'm not sure. Can anyone tell me the right direction to take ?
Best regards
Steph

Django Rest Framework - Group data by dynamic Key

I'm trying to format data when querying my API. I can retrieve my data like that :
"results": [
{
"Cat1": [
{
"job": String,
"position": Integer
}
]
},
{
"Cat1": [
{
"job": String,
"position": Integer
}
]
},
{
"Cat2": [
{
"job": String,
"position": Integer
}
]
}
]
But I want something like that:
"results": [
{
"Cat1": [
{
"job": String,
"position": Integer
},
{
"job": String,
"position": Integer
}
]
},
{
"Cat2": [
{
"job": String,
"position": Integer
}
]
}
]
I use a serializer like this:
class CustomSerializer(serializers.ModelSerializer):
category = CatSerializer()
job = JobSerializer()
class Meta:
model = MyModel
fields = '__all__'
def to_representation(self, value):
return {
value.category.name: [{"job": value.job.name,
"position": value.position, }]
cat1 and cat2 are dynamics, they are from another table. I don't understand how to create my arrays properly using those serializers. The category is a #Property field in my model who's a foreign key of job.
My models:
class MyModel(models.Model):
CHOICES = [(i, i) for i in range(4)]
partner = models.ForeignKey(Partner, on_delete=models.CASCADE)
job = models.ForeignKey(
Job, on_delete=models.CASCADE)
position = models.IntegerField(choices=CHOICES)
#property
def category(self):
return self.job.category.domain
def __str__(self):
return '%s | %s | %s | position: %s' % (self.partner.name, self.domain.name, self.job.name, self.position)
class Job(models.Model):
category = models.ForeignKey(Category, on_delete=models.CASCADE)
code = models.CharField(
max_length=255, unique=True)
name = models.CharField(
max_length=255)
class Category(models.Model):
domain = models.ForeignKey(Domain, on_delete=models.CASCADE)
code = models.CharField(
max_length=5)
name = models.CharField(max_length=255)
hourly_rate = models.FloatField(
null=True, blank=True)
How should I deal with serializers to format my data properly ?
EDIT:
I ended with something like that, except for the ListSerializer.
I used 2 ModelSerilizers
class MyModelCustomSerializer(serializers.ModelSerializer):
position = serializers.IntegerField(read_only=True)
job = serializers.CharField(source='job.name', read_only=True)
class Meta:
model = MyModel
fields = ['job', 'position']
def to_representation(self, value):
return {"position": value.position,
"job": {"name": value.job.name, "slug": value.job.slug,
"title": value.job.seo_title}
}
And
class CategoryCustomSerializer(serializers.ModelSerializer):
models = MyModelustomerSerializer(many=True)
class Meta:
model = Category
fields = ['category', 'MyModel']
def to_representation(self, value):
filters = {'job__category__domain__name': value.name}
myModels = MyModel.objects.filter(**filters)
serializer = MyModelCustomSerializer(instance=myModels, many=True,)
return {value.name: serializer.data}
But if I try to use a jobSerializer who already exist instead of
"job": {"name": value.job.name, "slug": value.job.slug,
"title": value.job.seo_title}
},
I got this error: Object of type 'Job' is not JSON serializable, but it's working anyway because i don't need all fields
I would go the direction of implementing a custom ListSerializer for the ModelSerializer and overriding its to_representation method.
from rest_framework import serializers
from collections import OrderedDict
class CustomListSerializer(serializers.ListSerializer):
def to_representation(self, data):
iterable = data.all() if isinstance(data, models.Manager) else data
list_rep = OrderedDict()
for item in iterable:
child_rep = self.child.to_representation(item)
k, v = list(child_rep.items()).pop()
list_rep.setdefault(k, []).append(v)
return [
{k: v}
for k, v in list_rep.items()
]
Then set the model Meta to use it
class CustomSerializer(serializers.ModelSerializer):
category = CatSerializer()
job = JobSerializer()
class Meta:
model = MyModel
fields = '__all__'
list_serializer_class = CustomListSerializer
def to_representation(self, value):
return {
value.category.name: [{"job": value.job.name,
"position": value.position, }]

Populating a tastypie resource for a multi-table inheritance Django model

Given the following code I was wondering how to populate RecordsResource with each real record data:
models.py
class Record(models.Model):
content_type = models.ForeignKey(ContentType, editable=False, null=True)
user = models.ForeignKey(User, related_name='records')
issued = models.DateTimeField(auto_now_add=True)
date = models.DateField()
def save(self, *args, **kwargs):
if not self.content_type:
self.content_type = ContentType.objects.get_for_model(self.__class__)
super(Record, self).save(*args, **kwargs)
def as_leaf_class(self):
model = self.content_type.model_class()
if model == self.__class__:
return self
return model.objects.get(pk=self.id)
class Record1(Record):
# some fields
# ...
class RecordN(Record):
# some fields
api.py
class BaseModelResource(ModelResource):
class Meta(object):
authentication = ApiKeyPlusWebAuthentication()
authorization= Authorization()
cache = SimpleCache()
throttle = CacheDBThrottle(
throttle_at=350,
# 1 day
expiration=86400
)
if settings.DEBUG:
serializer = PrettyJSONSerializer()
def obj_create(self, bundle, request=None, **kwargs):
return super(BaseModelResource, self).obj_create(bundle, request, user=request.user)
def apply_authorization_limits(self, request, object_list):
return object_list.filter(user=request.user)
class BaseRecordResource(BaseModelResource):
class Meta(BaseModelResource.Meta):
filtering = {
'date': ALL
}
excludes = ['issued']
class RecordsResource(BaseRecordResource):
class Meta(BaseRecordResource.Meta):
resource_name = 'records'
queryset = Record.objects.all()
class Record1Resource(BaseRecordResource):
class Meta(BaseRecordResource.Meta):
resource_name = 'record1'
queryset = Record1.objects.all()
# ...
class RecordNResource(BaseRecordResource):
class Meta(BaseRecordResource.Meta):
resource_name = 'recordn'
queryset = RecordN.objects.all()
Ok, I just solved it. I've simplified the code.
Given the following code...
models.py
from django.db import models
from model_utils.managers import InheritanceManager
class Place(models.Model):
name = models.CharField(max_length=50)
address = models.CharField(max_length=80)
# https://github.com/carljm/django-model-utils#inheritancemanager
objects = InheritanceManager()
class Restaurant(Place):
custom_field = models.BooleanField()
class Bar(Place):
custom_field = models.BooleanField()
api.py
from core.models import Place, Restaurant, Bar
# http://django-tastypie.readthedocs.org/en/latest/cookbook.html#pretty-printed-json-serialization
from core.utils import PrettyJSONSerializer
from tastypie.resources import ModelResource
class PlaceResource(ModelResource):
class Meta:
queryset = Place.objects.select_subclasses()
resource_name = 'place'
serializer = PrettyJSONSerializer()
class RestaurantResource(ModelResource):
class Meta:
queryset = Restaurant.objects.all()
resource_name = 'restaurant'
serializer = PrettyJSONSerializer()
class BarResource(ModelResource):
class Meta:
queryset = Bar.objects.all()
resource_name = 'bar'
serializer = PrettyJSONSerializer()
Output
http://localhost:8000/api/v1/bar/?format=json
{
"meta": {
"limit": 20,
"next": null,
"offset": 0,
"previous": null,
"total_count": 1
},
"objects": [
{
"address": "dawdaw",
"custom_field": true,
"id": "1",
"name": "dwdwad",
"resource_uri": "/api/v1/bar/1/"
}
]
}
OK
http://localhost:8000/api/v1/restaurant/?format=json
{
"meta": {
"limit": 20,
"next": null,
"offset": 0,
"previous": null,
"total_count": 1
},
"objects": [
{
"address": "nhnhnh",
"custom_field": true,
"id": "2",
"name": "nhnhnh",
"resource_uri": "/api/v1/restaurant/2/"
}
]
}
OK
http://localhost:8000/api/v1/place/?format=json
{
"meta": {
"limit": 20,
"next": null,
"offset": 0,
"previous": null,
"total_count": 2
},
"objects": [
{
"address": "dawdaw",
"id": "1",
"name": "dwdwad",
"resource_uri": "/api/v1/place/1/"
},
{
"address": "nhnhnh",
"id": "2",
"name": "nhnhnh",
"resource_uri": "/api/v1/place/2/"
}
]
}
What I want to achieve
{
"meta": {
"limit": 20,
"next": null,
"offset": 0,
"previous": null,
"total_count": 2
},
"objects": [
{
"address": "dawdaw",
"custom_field": true,
"id": "1",
"name": "dwdwad",
"resource_uri": "/api/v1/bar/1/"
},
{
"address": "nhnhnh",
"custom_field": true,
"id": "2",
"name": "nhnhnh",
"resource_uri": "/api/v1/restaurant/2/"
}
]
}
Solution:
from core.models import Place, Restaurant, Bar
# http://django-tastypie.readthedocs.org/en/latest/cookbook.html#pretty-printed-json-serialization
from core.utils import PrettyJSONSerializer
from tastypie.resources import ModelResource
class RestaurantResource(ModelResource):
class Meta:
queryset = Restaurant.objects.all()
resource_name = 'restaurant'
serializer = PrettyJSONSerializer()
class BarResource(ModelResource):
class Meta:
queryset = Bar.objects.all()
resource_name = 'bar'
serializer = PrettyJSONSerializer()
class PlaceResource(ModelResource):
class Meta:
queryset = Place.objects.select_subclasses()
resource_name = 'place'
serializer = PrettyJSONSerializer()
def dehydrate(self, bundle):
# bundle.data['custom_field'] = "Whatever you want"
if isinstance(bundle.obj, Restaurant):
restaurant_res = RestaurantResource()
rr_bundle = restaurant_res.build_bundle(obj=bundle.obj, request=bundle.request)
bundle.data = restaurant_res.full_dehydrate(rr_bundle).data
elif isinstance(bundle.obj, Bar):
bar_res = BarResource()
br_bundle = bar_res.build_bundle(obj=bundle.obj, request=bundle.request)
bundle.data = bar_res.full_dehydrate(br_bundle).data
return bundle
In RecordsResource class, you need to add model field as well (see https://github.com/tomchristie/django-rest-framework/blob/master/djangorestframework/resources.py#L232-234)
class RecordsResource(BaseRecordResource):
model = Record
class Meta(BaseRecordResource.Meta):
resource_name = 'records'
queryset = Record.objects.all()
Explaining from the beginning:
There are three styles of inheritance that are possible in Django.
Often, you will just want to use the parent class to hold
information that you don't want to have to type out for each child
model. This class isn't going to ever be used in isolation, so
Abstract base classes are what you're after.
If you're subclassing an existing model (perhaps something from
another application entirely) and want each model to have its own
database table, Multi-table inheritance is the way to go.
Finally, if you only want to modify the Python-level behavior of a
model, without changing the models fields in any way, you can use
Proxy models.
The choice here is Multi-table inheritance
Multi-table inheritance
The second type of model inheritance supported by Django is when each model in the hierarchy is a model all by itself. Each model corresponds to its own database table and can be queried and created individually. The inheritance relationship introduces links between the child model and each of its parents (via an automatically-created OneToOneField) Ref
To go from Record to Recordx where 1 <= x <= n you do a_example_record = Record.objects,get(pk=3) and then check what type of Recordx it is by using something like below
if hasattr(a_example_record, 'record1'):
# ...
elif hasattr(a_example_record, 'record2'):
# ...
So now that we know how to get the children from the parent and we need to provide TastyPie with a queryset in its meta, you need to write a custom queryset backed by a custom manager on the Record model that takes all your records (More here Custom QuerySet and Manager without breaking DRY?), checks what type of child it is and appends it to a queryset or a list. You can read about appending here How to combine 2 or more querysets in a Django view?