Get document for model_instance.

        redefine dump rule for field x: def dump_document_x

        :param django.db.models.Model instance: model instance
        :param list<Field> or None fields: model_instance field to dump
        :return dict: document

        Related documents are not included to current one. In case of to-many
        field serialization ensure that models_instance has been select_related
        so, no database calls would be executed.

        Method ensures that document has cls.Meta.fieldnames_include and does
        not have cls.Meta.fieldnames_exclude

        Steps:
        1) fieldnames_include could be properties, but not related models.
        Add them to fields_own.

def dump_document(cls, instance, fields_own=None, fields_to_many=None):
        """ Get document for model_instance.

        redefine dump rule for field x: def dump_document_x

        :param django.db.models.Model instance: model instance
        :param list<Field> or None fields: model_instance field to dump
        :return dict: document

        Related documents are not included to current one. In case of to-many
        field serialization ensure that models_instance has been select_related
        so, no database calls would be executed.

        Method ensures that document has cls.Meta.fieldnames_include and does
        not have cls.Meta.fieldnames_exclude

        Steps:
        1) fieldnames_include could be properties, but not related models.
        Add them to fields_own.

        """
        if fields_own is not None:
            fields_own = {f.name for f in fields_own}
        else:
            fields_own = {
                f.name for f in instance._meta.fields
                if f.rel is None and f.serialize
            }
        fields_own.add('id')

        fields_own = (fields_own | set(cls.Meta.fieldnames_include))\
            - set(cls.Meta.fieldnames_exclude)

        document = {}
        # Include own fields
        for fieldname in fields_own:
            field_serializer = getattr(
                cls, "dump_document_{}".format(fieldname), None)

            if field_serializer is not None:
                value = field_serializer(instance)
            else:
                value = getattr(instance, fieldname)
                try:
                    field = instance._meta.get_field(fieldname)
                except models.fields.FieldDoesNotExist:
                    # Field is property, value already calculated
                    pass
                else:
                    if isinstance(field, models.fields.files.FileField):
                        # TODO: Serializer depends on API here.
                        value = cls.Meta.api.base_url + value.url
                    elif isinstance(field, models.CommaSeparatedIntegerField):
                        value = [v for v in value]

            document[fieldname] = value

        # Include to-one fields. It does not require database calls
        for field in instance._meta.fields:
            fieldname = "{}_id".format(field.name)
            # NOTE: check field is not related to parent model to exclude
            # <class>_ptr fields. OneToOne relationship field.rel.multiple =
            # False. Here make sure relationship is to parent model.
            if field.rel and not field.rel.multiple \
                    and isinstance(instance, field.rel.to):
                continue

            if field.rel and fieldname not in cls.Meta.fieldnames_exclude:
                document["links"] = document.get("links") or {}
                document["links"][field.name] = getattr(instance, fieldname)

        # Include to-many fields. It requires database calls. At this point we
        # assume that model was prefetch_related with child objects, which would
        # be included into 'linked' attribute. Here we need to add ids of linked
        # objects. To avoid database calls, iterate over objects manually and
        # get ids.
        fields_to_many = fields_to_many or []
        for field in fields_to_many:
            document["links"] = document.get("links") or {}
            document["links"][field.related_resource_name] = [
                obj.id for obj in getattr(instance, field.name).all()]

        return document