<file_sep>from __future__ import print_function

try:
    import json
except ImportError:
    from django.utils import simplejson as json

from django.core.management.base import BaseCommand
try:
    from django.db.models import loading
except ImportError:
    from django.apps import apps as loading
from django.core.serializers import serialize
from django.conf import settings

from fixture_magic.utils import (
    add_to_serialize_list,
    reorder_json,
    serialize_fully
)


def process_dep(parent, dep, serialize_me, seen):
    parts = dep.split('.')
    current = parts.pop(0)
    leftover = '.'.join(parts)

    try:
        thing = getattr(parent, current)
    except AttributeError:
        pass  # related object not found
    else:
        if hasattr(thing, 'all'):
            children = thing.all()
        else:
            children = [thing]
        add_to_serialize_list(children, serialize_me, seen)

        if leftover:
            for child in children:
                process_dep(child, leftover, serialize_me, seen)


class Command(BaseCommand):
    help = 'Dump multiple pre-defined sets of objects into a JSON fixture.'

    def add_arguments(self, parser):
        parser.add_argument('dump_name')
        parser.add_argument('pk', nargs='*')
        parser.add_argument('--natural', default=False, action='store_true', dest='natural',
                            help='Use natural keys if they are available.')

    def handle(self, *args, **options):
        serialize_me = []
        seen = set()
        # Get the primary object
        dump_name = options['dump_name']
        pks = options['pk']
        dump_settings = settings.CUSTOM_DUMPS[dump_name]
        app_label, model_name, *manager_method = dump_settings['primary'].split('.')
        include_primary = dump_settings.get("include_primary", False)

        default_manager = loading.get_model(app_label, model_name).objects
        if manager_method:
            queryset = getattr(default_manager, manager_method[0])()
        else:
            queryset = default_manager.all()
        if pks:
            queryset = queryset.filter(pk__in=pks)

        deps = dump_settings.get('dependents', [])
        for obj in queryset:
            # get the dependent objects and add to serialize list
            for dep in deps:
                process_dep(obj, dep, serialize_me, seen)
            if include_primary or not deps:
                add_to_serialize_list([obj], serialize_me, seen)

        serialize_fully(serialize_me, seen)
        data = serialize(
            'json', [o for o in serialize_me if o is not None],
            indent=4,
            use_natural_foreign_keys=options.get('natural', False),
            use_natural_primary_keys=options.get('natural', False),
        )

        data = reorder_json(
            json.loads(data),
            dump_settings.get('order', []),
            ordering_cond=dump_settings.get('order_cond', {})
        )

        self.stdout.write(json.dumps(data, indent=4))
<file_sep>from __future__ import print_function

from django.core.exceptions import FieldError, ObjectDoesNotExist
from django.core.management.base import CommandError
from django.core.serializers import serialize

from fixture_magic.compat import get_all_related_objects, get_all_generic_foreign_keys

try:
    from django.db.models import loading
except ImportError:
    from django.apps import apps as loading
import json

from fixture_magic.utils import (add_to_serialize_list, serialize_fully, reorder_json)

from django.contrib.contenttypes.models import ContentType
from django.core.serializers.json import Serializer as JsonSerializer


class CustomJsonSerializer(JsonSerializer):
    def handle_fk_field(self, obj, field):
        is_content_type = True if hasattr(field, "related_model") and \
                                  field.related_model.__name__ == "ContentType" else False

        related_model = hasattr(field, "related_model")
        ct = isinstance(field.related_model, ContentType)

        if is_content_type or (self.use_natural_foreign_keys and hasattr(field.remote_field.model, 'natural_key')):
            related = getattr(obj, field.name)
            if related:
                value = related.natural_key()
            else:
                value = None
        else:
            value = self._value_from_field(obj, field)
        self._current[field.name] = value


def dump_object(model,
                query,
                ids,
                order=[],
                ignore=[],
                related_ignore={},
                additional_serialization_objects_fnc=None,
                format='json',
                kitchensink=True,
                follow_fk=True,
                natural=False,
                natural_foreign=False,
                natural_primary=False):
    serialize_me = []
    seen = set()
    error_text = ('Error\n')

    try:
        # verify input is valid
        try:
            (app_label, model_name) = model.split('.')
        except AttributeError:
            raise CommandError("Specify model as `appname.modelname")

        if ids and query:
            raise CommandError(error_text % 'either use query or id list, not both')
        if not (ids or query):
            raise CommandError(error_text % 'must pass list of --ids or a json --query')
    except IndexError:
        raise CommandError(error_text % 'No object_class or filter clause supplied.')
    except ValueError as e:
        raise CommandError(
            error_text %
            "object_class must be provided in the following format: app_name.model_name"
        )
    except AssertionError:
        raise CommandError(error_text % 'No filter argument supplied.')

    dump_me = loading.get_model(app_label, model_name)
    if query:
        objs = dump_me.objects.filter(**json.loads(query))
    else:
        if ids[0] == '*':
            objs = dump_me.objects.all()
        else:
            try:
                parsers = int, long, str
            except NameError:
                parsers = int, str
            for parser in parsers:
                try:
                    objs = dump_me.objects.filter(pk__in=map(parser, ids))
                except ValueError:
                    pass
                else:
                    break

    if kitchensink:
        fields = get_all_related_objects(dump_me)

        # if there are no related ignores for this model include the field
        # or if this related field is not in the related ignores include the field
        related_fields = [rel.get_accessor_name() for rel in fields if
                          model_name not in related_ignore or
                          rel.name not in related_ignore[model_name]]

        generic_foreign_key_fields = get_all_generic_foreign_keys(dump_me)

        for field in generic_foreign_key_fields:
            if model_name not in related_ignore or field.name not in related_ignore[model_name]:
                related_fields.append(field.name)
        for obj in objs:
            for rel in related_fields:
                try:
                    if hasattr(getattr(obj, rel), 'all'):
                        add_to_serialize_list(getattr(obj, rel).all(), serialize_me, seen, ignore=ignore)
                    else:
                        add_to_serialize_list([getattr(obj, rel)], serialize_me, seen, ignore=ignore)

                        # allow user to add additional data apart from standard foreign keys
                        if additional_serialization_objects_fnc and \
                                callable(additional_serialization_objects_fnc):
                            extra_objs = additional_serialization_objects_fnc(getattr(obj, rel))
                            if extra_objs:
                                add_to_serialize_list(extra_objs, serialize_me, seen, ignore=ignore)

                except FieldError:
                    pass
                except ObjectDoesNotExist:
                    pass

    add_to_serialize_list(objs, serialize_me, seen, prepend=True, ignore=ignore)

    if follow_fk:
        serialize_fully(serialize_me, seen, ignore, additional_serialization_objects_fnc)
    else:
        # reverse list to match output of serializez_fully
        serialize_me.reverse()

    natural_foreign = (natural or
                       natural_foreign)
    natural_primary = (natural or
                       natural_primary)

    if format:
        if format == "json":
            data = CustomJsonSerializer().serialize(
                [o for o in serialize_me if o is not None],
                indent=4,
                use_natural_foreign_keys=natural_foreign,
                use_natural_primary_keys=natural_primary)

        else:
            data = serialize(format,
                             [o for o in serialize_me if o is not None],
                             indent=4,
                             use_natural_foreign_keys=natural_foreign,
                             use_natural_primary_keys=natural_primary)

        data = reorder_json(
            json.loads(data),
            order,
        )

        return json.dumps(data, indent=4)

    # return unserialized objs
    return [o for o in serialize_me if o is not None]
