interfaces for serializing django objects usage from django core import serializers json serializers serializejson somequeryset objects listserializers deserializejson json to add your own serializers use the serializationmodules setting serializationmodules csv path to csv serializer txt path to txt serializer builtin serializers stub serializer to hold exception raised during registration this allows the serializer registration to cache serializers and if there is an error raised in the process of creating a serializer it will be raised and passed along to the caller when the serializer is used register a new serializer serializermodule should be the fully qualified module name for the serializer if serializers is provided the registration will be added to the provided dictionary if serializers is not provided the registration will be made directly into the global register of serializers adding serializers directly is not a threadsafe operation serialize a queryset or any iterator that returns database objects using a certain serializer deserialize a stream or a string return an iterator that yields obj m2mrelationdict where obj is an instantiated but unsaved object and m2mrelationdict is a dictionary of m2mfieldname listofrelatedobjects register builtin and settingsdefined serializers this is done lazily so that user code has a chance to e g set up custom settings without needing to be careful of import order sort a list of appconfig models pairs into a single list of models the single list of models is sorted so that any model with a natural key is serialized before a normal model and any model with a natural key dependency has it s dependencies serialized first if allowcycles is true return the besteffort ordering that will respect most of dependencies but ignore some of them to break the cycles process the list of models and get the list of dependencies add any explicitly defined dependencies now add a dependency for any fk relation with a model that defines a natural key also add a dependency for any simple m2m relation with a model that defines a natural key m2m relations with explicit through models don t count as dependencies now sort the models to ensure that dependencies are met this is done by repeatedly iterating over the input list of models if all the dependencies of a given model are in the final list that model is promoted to the end of the final list this process continues until the input list is empty or we do a full iteration over the input models without promoting a model to the final list if we do a full iteration without a promotion that means there are circular dependencies in the list if all of the models in the dependency list are either already on the final model list or not on the original serialization list then we ve found another model with all it s dependencies satisfied if cycles are allowed add the last skipped model and ignore its dependencies this could be improved by some graph analysis to ignore as few dependencies as possible built in serializers stub serializer to hold exception raised during registration this allows the serializer registration to cache serializers and if there is an error raised in the process of creating a serializer it will be raised and passed along to the caller when the serializer is used register a new serializer serializer_module should be the fully qualified module name for the serializer if serializers is provided the registration will be added to the provided dictionary if serializers is not provided the registration will be made directly into the global register of serializers adding serializers directly is not a thread safe operation serialize a queryset or any iterator that returns database objects using a certain serializer deserialize a stream or a string return an iterator that yields obj m2m_relation_dict where obj is an instantiated but unsaved object and m2m_relation_dict is a dictionary of m2m_field_name list_of_related_objects register built in and settings defined serializers this is done lazily so that user code has a chance to e g set up custom settings without needing to be careful of import order sort a list of app_config models pairs into a single list of models the single list of models is sorted so that any model with a natural key is serialized before a normal model and any model with a natural key dependency has it s dependencies serialized first if allow_cycles is true return the best effort ordering that will respect most of dependencies but ignore some of them to break the cycles process the list of models and get the list of dependencies add any explicitly defined dependencies now add a dependency for any fk relation with a model that defines a natural key also add a dependency for any simple m2m relation with a model that defines a natural key m2m relations with explicit through models don t count as dependencies now sort the models to ensure that dependencies are met this is done by repeatedly iterating over the input list of models if all the dependencies of a given model are in the final list that model is promoted to the end of the final list this process continues until the input list is empty or we do a full iteration over the input models without promoting a model to the final list if we do a full iteration without a promotion that means there are circular dependencies in the list if all of the models in the dependency list are either already on the final model list or not on the original serialization list then we ve found another model with all it s dependencies satisfied if cycles are allowed add the last skipped model and ignore its dependencies this could be improved by some graph analysis to ignore as few dependencies as possible
import importlib

from django.apps import apps
from django.conf import settings
from django.core.serializers.base import SerializerDoesNotExist


BUILTIN_SERIALIZERS = {
    "xml": "django.core.serializers.xml_serializer",
    "python": "django.core.serializers.python",
    "json": "django.core.serializers.json",
    "yaml": "django.core.serializers.pyyaml",
    "jsonl": "django.core.serializers.jsonl",
}

_serializers = {}


class BadSerializer:
    

    internal_use_only = False

    def __init__(self, exception):
        self.exception = exception

    def __call__(self, *args, **kwargs):
        raise self.exception


def register_serializer(format, serializer_module, serializers=None):
    
    if serializers is None and not _serializers:
        _load_serializers()

    try:
        module = importlib.import_module(serializer_module)
    except ImportError as exc:
        bad_serializer = BadSerializer(exc)

        module = type(
            "BadSerializerModule",
            (),
            {
                "Deserializer": bad_serializer,
                "Serializer": bad_serializer,
            },
        )

    if serializers is None:
        _serializers[format] = module
    else:
        serializers[format] = module


def unregister_serializer(format):
    "Unregister a given serializer. This is not a thread-safe operation."
    if not _serializers:
        _load_serializers()
    if format not in _serializers:
        raise SerializerDoesNotExist(format)
    del _serializers[format]


def get_serializer(format):
    if not _serializers:
        _load_serializers()
    if format not in _serializers:
        raise SerializerDoesNotExist(format)
    return _serializers[format].Serializer


def get_serializer_formats():
    if not _serializers:
        _load_serializers()
    return list(_serializers)


def get_public_serializer_formats():
    if not _serializers:
        _load_serializers()
    return [k for k, v in _serializers.items() if not v.Serializer.internal_use_only]


def get_deserializer(format):
    if not _serializers:
        _load_serializers()
    if format not in _serializers:
        raise SerializerDoesNotExist(format)
    return _serializers[format].Deserializer


def serialize(format, queryset, **options):
    
    s = get_serializer(format)()
    s.serialize(queryset, **options)
    return s.getvalue()


def deserialize(format, stream_or_string, **options):
    
    d = get_deserializer(format)
    return d(stream_or_string, **options)


def _load_serializers():
    
    global _serializers
    serializers = {}
    for format in BUILTIN_SERIALIZERS:
        register_serializer(format, BUILTIN_SERIALIZERS[format], serializers)
    if hasattr(settings, "SERIALIZATION_MODULES"):
        for format in settings.SERIALIZATION_MODULES:
            register_serializer(
                format, settings.SERIALIZATION_MODULES[format], serializers
            )
    _serializers = serializers


def sort_dependencies(app_list, allow_cycles=False):
    
    
    model_dependencies = []
    models = set()
    for app_config, model_list in app_list:
        if model_list is None:
            model_list = app_config.get_models()

        for model in model_list:
            models.add(model)
            
            if hasattr(model, "natural_key"):
                deps = getattr(model.natural_key, "dependencies", [])
                if deps:
                    deps = [apps.get_model(dep) for dep in deps]
            else:
                deps = []

            
            
            for field in model._meta.fields:
                if field.remote_field:
                    rel_model = field.remote_field.model
                    if hasattr(rel_model, "natural_key") and rel_model != model:
                        deps.append(rel_model)
            
            
            
            for field in model._meta.many_to_many:
                if field.remote_field.through._meta.auto_created:
                    rel_model = field.remote_field.model
                    if hasattr(rel_model, "natural_key") and rel_model != model:
                        deps.append(rel_model)
            model_dependencies.append((model, deps))

    model_dependencies.reverse()
    
    
    
    
    
    
    
    
    model_list = []
    while model_dependencies:
        skipped = []
        changed = False
        while model_dependencies:
            model, deps = model_dependencies.pop()

            
            
            
            if all(d not in models or d in model_list for d in deps):
                model_list.append(model)
                changed = True
            else:
                skipped.append((model, deps))
        if not changed:
            if allow_cycles:
                
                
                
                model, _ = skipped.pop()
                model_list.append(model)
            else:
                raise RuntimeError(
                    "Can't resolve dependencies for %s in serialized app list."
                    % ", ".join(
                        model._meta.label
                        for model, deps in sorted(
                            skipped, key=lambda obj: obj[0].__name__
                        )
                    ),
                )
        model_dependencies = skipped

    return model_list