MattBroach / DjangoRestMultipleModels

View (and mixin) for serializing multiple models or querysets in Django Rest Framework
MIT License
549 stars 67 forks source link

Is there a way to add post method? #30

Closed OwenwLi closed 6 years ago

OwenwLi commented 7 years ago

Hello. Is there a way to add post method in MultipleAPIView? I really like this project but I need to method for my project. I try to add post and create method in MultipleAPIView class as :

class MultipleModelAPIView(MultipleModelMixin, GenericAPIView):

def get_queryset(self):
    return

def get(self, request, *args, **kwargs):
    return self.list(request, *args, **kwargs)

# here is my part
def post(self, request, *args, **kwargs):
    return self.create(request, *args, **kwargs)

def create(self, request, *args, **kwargs):
    serializer = self.get_serializer(data=request.data)
    serializer.is_valid(raise_exception=True)
    self.perform_create(serializer)
    headers = self.get_success_headers(serializer.data)
    return Response(serializer.data, status=status.HTTP_201_CREATED, headers=headers)

def perform_create(self, serializer):
    serializer.save()

def get_success_headers(self, data):
    try:
        return {'Location': data[api_settings.URL_FIELD_NAME]}
    except (TypeError, KeyError):
        return {}

But it would have a bug ask about serializer_class :

should either include a serializer_class attribute, or override the get_serializer_class() method.

Does it have a better way to add post method?

MattBroach commented 6 years ago

Hey @OwenwLi, sorry for a super delayed response. Out of the box, the MultipleModelAPIViews do not support POST/PUT/DELETE, etc, because POST/PUT/DELETE requests are usually (though by no means exclusively) per-object, whereas the MultipleModelAPIView is meant to handle multiple objects (and models) simultaneously. You could, in theory, add the mixin along with some of the the DRF generic mixins, but you would have to provide all the tools for handling a single queryset/serializer combo (because those mixins aren't set up for handling multiple querysets), whic would look something like this:

from drf_multiple_model.mixins import ObjectMultipleModelMixin
from rest_framework.mixins import CreateModelMixin
from rest_framework.generics import GenericAPIView

class MyMultipleModelAndCreateView(
        ObjectMultipleModelMixin, CreateModelMixin, GenericAPIView
):
    querylist = [
        {'queryset': Play.objects.all(), 'serializer_class': PlaySerializer},
        {'queryset': Poem.objects.filter(style='Sonnet'), 'serializer_class': PoemSerializer},
    ]
    queryset = Play.objects.all()
    serializer_class = PlaySerializer

But that's a little awkward, right? The code duplication of the serializer and queryset parameters has a bad smell.

(Also, as an aside, not the changes in the code from earlier versions of the library. drf_multiple_model has undergone a number of interface changes in the most recent release)

My usual solution to this problem is to simply create an entirely different view for handling POST/PUT/DELETE/etc. Since I basically never am updating or creating multiple objects at a time, I have dedicated endpoints for updating individual objects from each model type that I need, and leave the MultipleModelAPIViews for mono-directional information transfer. For example:

from drf_multiple_model.mixins import ObjectMultipleModelMixin
from rest_framework.generics import RetreiveUpdateDestroyAPIView

class TextAPIView(ObjectMultipleModelAPIView):
    querylist = [
        {'queryset': Play.objects.all(), 'serializer_class': PlaySerializer},
        {'queryset': Poem.objects.filter(style='Sonnet'), 'serializer_class': PoemSerializer},
    ]

class PlayAPIView(RetrieveUpdateDestoryAPIView):
    queryset = Play.objects.all()
    serializer_class = PlaySerializer