Where does the self.get_serializer method come from in the Django REST Framework?

CreateModelMixin along with all other mixin classes (Eg. ListModelMixin, UpdateModelMixin etc) are defined in rest_framework/mixins.py file.

These mixin classes provide all the basic CRUD operations on a model. You just need to define a serializer_class and queryset in your generic view to perform all these operations. DRF has separated out these common functionality in separate mixin classes so that they can be injected/mixed-in in a view and used as and when required.

In the DRF source code, there's a get_serializer method. It wasn't inherited from object and it's not a method in the CreateModelMixin class. Where does this method come from?

In the GenericAPIView, get_serializer method is defined. The combination of different mixin classes along with GenericAPIView class provide us different generic views for different use cases.

class GenericAPIView(views.APIView):
    """
    Base class for all other generic views.
    """

    def get_serializer(self, *args, **kwargs):
        """
        Return the serializer instance that should be used for validating and
        deserializing input, and for serializing output.
        """
        serializer_class = self.get_serializer_class()
        kwargs['context'] = self.get_serializer_context()
        return serializer_class(*args, **kwargs)

Other generic views then inherit the relevant mixin along with GenericAPIView.

Eg. CreateAPIView inherit the CreateModelMixin along with GenericAPIView to provide create-only endpoints.

# rest_framework/generics.py
class CreateAPIView(mixins.CreateModelMixin,
                    GenericAPIView):
    ...

You can see the __file__ or __module__ member of the method (if it has them) to learn that. inspect also has getsourcefile and getsourcelines that use data from the function's code object, specifically, <function>.f_code.co_filename and .co_firstline.

For example, this retrieves source information for a method inherited from DictMixin:

>>> c=ConfigParser._Chainmap()
>>> f=c.__len__
>>> dump(f.__code__)    # my custom function that dumps attributes,
                        # see https://github.com/native-api/dump
<...>
co_filename : /usr/lib/python2.7/UserDict.py
co_firstlineno : 179
<...>

# same with inspect
>>> inspect.getsourcefile(f)
'/usr/lib/python2.7/UserDict.py'
>>> inspect.getsourcelines(f)
(['    def __len__(self):\n', '        return len(self.keys())\n'], 179)
>>> inspect.getsource(f)
'    def __len__(self):\n        return len(self.keys())\n'

# same with __file__
>>> sys.modules[f.__module__].__file__
'/usr/lib/python2.7/UserDict.pyc'

It helps if you understand class inheritance (not suggesting you don't, though).

CreateModelMixin will be used by a class based view, for example:

class YourViewSet(mixins.CreateModelMixin, viewsets.GenericViewSet):

get_serializer is a method available through GenericViewSet (although there are probably other View classes that it's available on, too).

So, basically if you would use CreateModelMixin only get_serializer would not be available. (You probably wouldn't do that anyway). It's only because you inherit from another class besides CreateModelMixin that the get_serializer method is available at the moment that the create method is executed.

I could give a simple example of what's happening, while I am at it. It's just to give a more simple overview of what's happening.

disclaimer: you might want to keep in mind that I am a junior developer, so this may not be the most Pythonic code out there :P.

class MyMixin:
    def create(self):
        serializer = self.get_serializer()
        return serializer


class FakeView:
    def get_serializer(self):
        return "Sadly I am just a string, but I could've been a serializer."


class MyFakeView(MyMixin, FakeView):
    pass

view = MyFakeView()

serializer = view.create()

print(serializer)

executing this would show you:

Sadly I am just a string, but I could've been a serializer.

Where if you would define MyFakeView like below,

class MyFakeView(MyMixin):
    pass

you would receive the following error:

AttributeError: 'MyFakeView' object has no attribute 'get_serializer'