'Convert a Python type to a MongoDB-compatible type.'

def to_mongo(self, value, use_db_field=True, fields=None):

    Document = _import_class('Document')
    EmbeddedDocument = _import_class('EmbeddedDocument')
    GenericReferenceField = _import_class('GenericReferenceField')
    if isinstance(value, six.string_types):
        return value
    if hasattr(value, 'to_mongo'):
        if isinstance(value, Document):
            return GenericReferenceField().to_mongo(value)
        cls = value.__class__
        val = value.to_mongo(use_db_field, fields)
        if isinstance(value, EmbeddedDocument):
            val['_cls'] = cls.__name__
        return val
    is_list = False
    if (not hasattr(value, 'items')):
        try:
            is_list = True
            value = {k: v for (k, v) in enumerate(value)}
        except TypeError:
            return value
    if self.field:
        value_dict = {key: self.field._to_mongo_safe_call(item, use_db_field, fields) for (key, item) in value.iteritems()}
    else:
        value_dict = {}
        for (k, v) in value.iteritems():
            if isinstance(v, Document):
                if (v.pk is None):
                    self.error('You    can    only    reference    documents    once    they    have    been    saved    to    the    database')
                meta = getattr(v, '_meta', {})
                allow_inheritance = meta.get('allow_inheritance')
                if ((not allow_inheritance) and (not self.field)):
                    value_dict[k] = GenericReferenceField().to_mongo(v)
                else:
                    collection = v._get_collection_name()
                    value_dict[k] = DBRef(collection, v.pk)
            elif hasattr(v, 'to_mongo'):
                cls = v.__class__
                val = v.to_mongo(use_db_field, fields)
                if isinstance(v, (Document, EmbeddedDocument)):
                    val['_cls'] = cls.__name__
                value_dict[k] = val
            else:
                value_dict[k] = self.to_mongo(v, use_db_field, fields)
    if is_list:
        return [v for (_, v) in sorted(value_dict.items(), key=operator.itemgetter(0))]
    return value_dict
