Sirion
Sirion

Reputation: 929

Id, url and natural key in django rest framework

Consider these models in Django:

class ModelA(models.Model):
    name = models.CharField()

class ModelB(models.Model):
    model_a = models.ForeignKey(ModelA)

Now suppose you have created an API using Django Rest Framework to access these models. When accessing http://my.site.com/api/model_b/1 to retrieve a ModelB instance, sometimes you'll want the id of related ModelA instance, i.e.:

{'id': 1, 'model_a': 17}

sometimes you'll want to get its url, i.e.:

{'id': 1, 'model_a': 'http://my.site.com/api/model_a/17'}

and other times its so called natural key, i.e.:

{'id': 1, 'model_a': 'some_representative_string_describing_the_instance'}

My question: is there a built-in feature that can handle the type of reference to model_a according to a get parameter, e.g.:

http://my.site.com/api/model_b/1?fk_type=id
http://my.site.com/api/model_b/1?fk_type=url
http://my.site.com/api/model_b/1?fk_type=natural_key

UPDATE: Also, I'd like to have finer control when ModelB has two or more foreign keys, allowing me to decide the type of encoding independently. Something like:

ModelBSerializer(model_b_instance, fk_encoding={'model_a': 'url', 'model_c': 'natural_key'})

Upvotes: 3

Views: 788

Answers (1)

Todor
Todor

Reputation: 16050

You need to define a different serializers for each type of serialization you want to use. And then override the get_serializer_class. Something like the following:

#by default django serializes FK by id
class ModelBIdSerializer(serializers.ModelSerializer):
    class Meta:
        model = ModelB


class ModelBUrlSerializer(serializers.ModelSerializer):
    model_a = serializers.HyperlinkedRelatedField(view_name='model-a-detail')

    class Meta:
        model = ModelB


class ModelBNaturalSerializer(serializers.ModelSerializer):
    model_a = serializers.StringRelatedField()

    class Meta:
        model = ModelB

And then inside ModelBViewSet

class ModelBViewSet():
    #...

    def get_serializer_class(self):
        if self.request.GET.get('fk_type') == 'url':
            return ModelBUrlSerializer
        elif self.request.GET.get('fk_type') == 'natural_key':
            return ModelBNaturalSerializer
        else:
            return ModelBIdSerializer

Upvotes: 1

Related Questions