Skip to content

Instantly share code, notes, and snippets.

@srgrn
Created February 28, 2018 11:35
Show Gist options
  • Save srgrn/ff34995b58a57b699b628753ee09ee25 to your computer and use it in GitHub Desktop.
Save srgrn/ff34995b58a57b699b628753ee09ee25 to your computer and use it in GitHub Desktop.
django_dyamic_field_serializer
from rest_framework import serializers
from rest_framework.utils import model_meta
from django.db.models.fields import Field as DjangoModelField
from django.db.models.fields import FieldDoesNotExist
class DynamicAppendFieldsModelSerializer(serializers.ModelSerializer):
"""
A ModelSerializer that takes an additional `fields` argument that
controls which fields should be displayed.
"""
def __init__(self, *args, **kwargs):
# Don't pass the 'fields' arg up to the superclass
fields = kwargs.pop('fields', None)
# Instantiate the superclass normally
super(DynamicFieldsModelSerializer, self).__init__(*args, **kwargs)
if fields:
# Drop any fields that are not specified in the `fields` argument.
appended_fields = set(fields)
default_fields = set(self.fields.keys())
model = getattr(self.Meta, 'model')
info = model_meta.get_field_info(model)
for field_name in appended_fields - default_fields:
try:
field = model._meta.get_field(field_name)
if isinstance(field, DjangoModelField):
field_class, field_kwargs = self.build_field(field_name, info, model, 0)
self.fields[field_name] = field_class(**field_kwargs)
except FieldDoesNotExist:
pass
class DynamicFieldsModelSerializer(serializers.ModelSerializer):
"""
A ModelSerializer that takes an additional `fields` argument that
controls which fields should be displayed.
"""
def __init__(self, *args, **kwargs):
# Don't pass the 'fields' arg up to the superclass
fields = kwargs.pop('fields', None)
# Instantiate the superclass normally
super(DynamicFieldsModelSerializer, self).__init__(*args, **kwargs)
if fields:
# Drop any fields that are not specified in the `fields` argument.
allowed = set(fields)
existing = set(self.fields.keys())
for field_name in existing - allowed:
self.fields.pop(field_name)
class DynamicFieldsSerializer(serializers.Serializer):
"""
A Serializer that takes an additional `fields` argument that
controls which fields should be displayed.
"""
def __init__(self, *args, **kwargs):
# Don't pass the 'fields' arg up to the superclass
fields = kwargs.pop('fields', None)
# Instantiate the superclass normally
super(DynamicFieldsSerializer, self).__init__(*args, **kwargs)
if fields:
# Drop any fields that are not specified in the `fields` argument.
allowed = set(fields)
existing = set(self.fields.keys())
for field_name in existing - allowed:
self.fields.pop(field_name)
from __future__ import unicode_literals
from rest_framework.response import Response
class DyanmicListModelMixin(object):
"""
List a queryset.
"""
def list(self, request, *args, **kwargs):
queryset = self.filter_queryset(self.get_queryset())
fields = request.query_params.get('fields', None)
if fields is not None:
fields = fields.split(',')
page = self.paginate_queryset(queryset)
if page is not None:
serializer = self.get_serializer(page, many=True, fields=fields)
return self.get_paginated_response(serializer.data)
serializer = self.get_serializer(queryset, many=True, fields=fields)
return Response(serializer.data)
class DynamicRetrieveModelMixin(object):
"""
Retrieve a model instance.
"""
def retrieve(self, request, *args, **kwargs):
fields = request.query_params.get('fields', None)
if fields is not None:
fields = fields.split(',')
instance = self.get_object()
serializer = self.get_serializer(instance, fields=fields)
return Response(serializer.data)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment