Usage

Basic Usage

drf-multiple-model comes with the MultipleModelAPIView generic class-based-view for serializing multiple models. MultipleModelAPIView requires a queryList attribute, which is a list or tuple of queryset/serializer pairs (in that order). For example, let’s say you have the following models and serializers:

# Models
class Play(models.Model):
    genre = models.CharField(max_length=100)
    title = models.CharField(max_length=200)
    pages = models.IntegerField()

class Poem(models.Model):
    title = models.CharField(max_length=200)
    style = models.CharField(max_length=100)
    lines = models.IntegerField()
    stanzas = models.IntegerField()

# Serializers
class PlaySerializer(serializers.ModelSerializer):
    class Meta:
        model = Play
        fields = ('genre','title','pages')

class PoemSerializer(serializers.ModelSerializer):
    class Meta:
        model = Poem
        fields = ('title','stanzas')

Then you might use the MultipleModelAPIView as follows:

from drf_multiple_model.views import MultipleModelAPIView

class TextAPIView(MultipleModelAPIView):
    queryList = [
        (Play.objects.all(),PlaySerializer),
        (Poem.objects.filter(style='Sonnet'),PoemSerializer),
        ....
    ]

which would return:

[
    {
        'play' : [
                {'genre': 'Comedy', 'title': "A Midsummer Night's Dream", 'pages': 350},
                {'genre': 'Tragedy', 'title': "Romeo and Juliet", 'pages': 300},
                ....
            ],
    },
    {
        'poem' : [
                {'title': 'Shall I compare thee to a summer's day?', 'stanzas': 1},
                {'title': 'As a decrepit father takes delight', 'stanzas': 1},
                ....
            ],
    }
]

Configuration Options

Objectify

When using the results of the MultipleModelAPIView, it’s often easier to parse the results as a JSON object rather than as an array. To facilitate this, MultipleModelAPIView has the objectify property, which when set to True returns the results as an object. For example, the following:

from drf_multiple_model.views import MultipleModelAPIView

class TextAPIView(MultipleModelAPIView):
    objectify = True
    queryList = [
        (Play.objects.all(),PlaySerializer),
        (Poem.objects.filter(style='Sonnet'),PoemSerializer),
        ....
    ]

would return:

{
    'play' : [
            {'genre': 'Comedy', 'title': "A Midsummer Night's Dream", 'pages': 350},
            {'genre': 'Tragedy', 'title': "Romeo and Juliet", 'pages': 300},
            ....
        ],
    'poem' : [
            {'title': 'Shall I compare thee to a summer's day?', 'stanzas': 1},
            {'title': 'As a decrepit father takes delight', 'stanzas': 1},
            ....
        ],
}

Labels

By default, MultipleModelAPIView uses the model name as a label. If you want to use a custom label, you can add a third string attribute to the queryList tuples, like so:

from drf_multiple_model.views import MultipleModelAPIView

class TextAPIView(MultipleModelAPIView):
    queryList = [
        (Play.objects.all(),PlaySerializer,'plays'),
        (Poem.objects.filter(style='Sonnet'),PoemSerializer,'sonnets'),
        ....
    ]

which would return:

[
    {
        'plays': [
            {'genre': 'Comedy', 'title': "A Midsummer Night's Dream", 'pages': 350},
            {'genre': 'Tragedy', 'title': "Romeo and Juliet", 'pages': 300},
            ....
        ]
    },
    {
        'sonnets':[
            {'title': 'Shall I compare thee to a summer's day?', 'stanzas': 1},
            {'title': 'As a decrepit father takes delight', 'stanzas': 1},
            ....
        ],
    }
]

Flat

Add the attribute flat = True to return a single JSON array with all of the objects mixed together. For example:

class TextAPIView(MultipleModelAPIView):
    flat = True

    queryList = [
        (Play.objects.all(),PlaySerializer,'plays'),
        (Poem.objects.filter(style='Sonnet'),PoemSerializer,'sonnets'),
        ....
    ]

would return:

[
    {'genre': 'Comedy', 'title': "A Midsummer Night's Dream", 'pages': 350},
    {'genre': 'Tragedy', 'title': "Romeo and Juliet", 'pages': 300},
    ....
    {'title': 'Shall I compare thee to a summer's day?', 'stanzas': 1},
    {'title': 'As a decrepit father takes delight', 'stanzas': 1},
    ....
]

sorting_field

When using flat=True, by default the objects will be arranged by the order in which the querysets were listed in your queryList attribute. However, you can specify a different ordering by adding the sorting_field to your view:

class TextAPIView(MultipleModelAPIView):
    flat = True
    sorting_field = 'title'

    queryList = [
        (Play.objects.all(),PlaySerializer,'plays'),
        (Poem.objects.filter(style='Sonnet'),PoemSerializer,'sonnets'),
        ....
    ]

would return:

[
    {'genre': 'Comedy', 'title': "A Midsummer Night's Dream", 'pages': 350},
    {'title': 'As a decrepit father takes delight', 'stanzas': 1},
    {'genre': 'Tragedy', 'title': "Romeo and Juliet", 'pages': 300},
    {'title': 'Shall I compare thee to a summer's day?', 'stanzas': 1},
    ....
]

As with django field ordering, add ‘-‘ to the beginning of the field to enable reverse sorting. Setting sorting_field='-title' would sort the title fields in __descending__ order.

WARNING: the field chosen for ordering must be shared by all models/serializers in your queryList. Any attempt to sort objects along non_shared fields will throw a KeyError.

add_model_type

If no label is explicitly specified in your queryList, MultipleModelAPIView will use the model from each queryset a label. If you don’t want any extra labeling and just want your data as is, set add_model_type = False:

class TextAPIView(MultipleModelAPIView):
    add_model_type = False

    queryList = [
        (Play.objects.all(),PlaySerializer,'plays'),
        (Poem.objects.filter(style='Sonnet'),PoemSerializer,'sonnets'),
        ....
    ]

would return:

[
    [
        {'genre': 'Comedy', 'title': "A Midsummer Night's Dream", 'pages': 350},
        {'genre': 'Tragedy', 'title': "Romeo and Juliet", 'pages': 300},
        ....
    ],
    [
        {'title': 'Shall I compare thee to a summer's day?', 'stanzas': 1},
        {'title': 'As a decrepit father takes delight', 'stanzas': 1},
        ....
    ]
]

This works with flat = True set as well – the 'type':'myModel' won’t be appended to each data point in that case. Note: adding a custom label to your queryList elements will always override add_model_type. However, labels are taken on an element-by-element basis, so you can add labels for some of your models/querysets, but not others.

Mixin

If you want to combine MultipleModelAPIView’s list() function with other views, you can use the included MultipleModelMixin instead.