web/lib/django/core/serializers/python.py
changeset 29 cc9b7e14412b
parent 0 0d40e90630ef
equal deleted inserted replaced
28:b758351d191f 29:cc9b7e14412b
     4 other serializers.
     4 other serializers.
     5 """
     5 """
     6 
     6 
     7 from django.conf import settings
     7 from django.conf import settings
     8 from django.core.serializers import base
     8 from django.core.serializers import base
     9 from django.db import models
     9 from django.db import models, DEFAULT_DB_ALIAS
    10 from django.utils.encoding import smart_unicode, is_protected_type
    10 from django.utils.encoding import smart_unicode, is_protected_type
    11 
    11 
    12 class Serializer(base.Serializer):
    12 class Serializer(base.Serializer):
    13     """
    13     """
    14     Serializes a QuerySet to basic Python objects.
    14     Serializes a QuerySet to basic Python objects.
    45             self._current[field.name] = field.value_to_string(obj)
    45             self._current[field.name] = field.value_to_string(obj)
    46 
    46 
    47     def handle_fk_field(self, obj, field):
    47     def handle_fk_field(self, obj, field):
    48         related = getattr(obj, field.name)
    48         related = getattr(obj, field.name)
    49         if related is not None:
    49         if related is not None:
    50             if field.rel.field_name == related._meta.pk.name:
    50             if self.use_natural_keys and hasattr(related, 'natural_key'):
    51                 # Related to remote object via primary key
    51                 related = related.natural_key()
    52                 related = related._get_pk_val()
       
    53             else:
    52             else:
    54                 # Related to remote object via other field
    53                 if field.rel.field_name == related._meta.pk.name:
    55                 related = getattr(related, field.rel.field_name)
    54                     # Related to remote object via primary key
    56         self._current[field.name] = smart_unicode(related, strings_only=True)
    55                     related = related._get_pk_val()
       
    56                 else:
       
    57                     # Related to remote object via other field
       
    58                     related = smart_unicode(getattr(related, field.rel.field_name), strings_only=True)
       
    59         self._current[field.name] = related
    57 
    60 
    58     def handle_m2m_field(self, obj, field):
    61     def handle_m2m_field(self, obj, field):
    59         if field.creates_table:
    62         if field.rel.through._meta.auto_created:
    60             self._current[field.name] = [smart_unicode(related._get_pk_val(), strings_only=True)
    63             if self.use_natural_keys and hasattr(field.rel.to, 'natural_key'):
       
    64                 m2m_value = lambda value: value.natural_key()
       
    65             else:
       
    66                 m2m_value = lambda value: smart_unicode(value._get_pk_val(), strings_only=True)
       
    67             self._current[field.name] = [m2m_value(related)
    61                                for related in getattr(obj, field.name).iterator()]
    68                                for related in getattr(obj, field.name).iterator()]
    62 
    69 
    63     def getvalue(self):
    70     def getvalue(self):
    64         return self.objects
    71         return self.objects
    65 
    72 
    68     Deserialize simple Python objects back into Django ORM instances.
    75     Deserialize simple Python objects back into Django ORM instances.
    69 
    76 
    70     It's expected that you pass the Python objects themselves (instead of a
    77     It's expected that you pass the Python objects themselves (instead of a
    71     stream or a string) to the constructor
    78     stream or a string) to the constructor
    72     """
    79     """
       
    80     db = options.pop('using', DEFAULT_DB_ALIAS)
    73     models.get_apps()
    81     models.get_apps()
    74     for d in object_list:
    82     for d in object_list:
    75         # Look up the model and starting build a dict of data for it.
    83         # Look up the model and starting build a dict of data for it.
    76         Model = _get_model(d["model"])
    84         Model = _get_model(d["model"])
    77         data = {Model._meta.pk.attname : Model._meta.pk.to_python(d["pk"])}
    85         data = {Model._meta.pk.attname : Model._meta.pk.to_python(d["pk"])}
    84 
    92 
    85             field = Model._meta.get_field(field_name)
    93             field = Model._meta.get_field(field_name)
    86 
    94 
    87             # Handle M2M relations
    95             # Handle M2M relations
    88             if field.rel and isinstance(field.rel, models.ManyToManyRel):
    96             if field.rel and isinstance(field.rel, models.ManyToManyRel):
    89                 m2m_convert = field.rel.to._meta.pk.to_python
    97                 if hasattr(field.rel.to._default_manager, 'get_by_natural_key'):
    90                 m2m_data[field.name] = [m2m_convert(smart_unicode(pk)) for pk in field_value]
    98                     def m2m_convert(value):
       
    99                         if hasattr(value, '__iter__'):
       
   100                             return field.rel.to._default_manager.db_manager(db).get_by_natural_key(*value).pk
       
   101                         else:
       
   102                             return smart_unicode(field.rel.to._meta.pk.to_python(value))
       
   103                 else:
       
   104                     m2m_convert = lambda v: smart_unicode(field.rel.to._meta.pk.to_python(v))
       
   105                 m2m_data[field.name] = [m2m_convert(pk) for pk in field_value]
    91 
   106 
    92             # Handle FK fields
   107             # Handle FK fields
    93             elif field.rel and isinstance(field.rel, models.ManyToOneRel):
   108             elif field.rel and isinstance(field.rel, models.ManyToOneRel):
    94                 if field_value is not None:
   109                 if field_value is not None:
    95                     data[field.attname] = field.rel.to._meta.get_field(field.rel.field_name).to_python(field_value)
   110                     if hasattr(field.rel.to._default_manager, 'get_by_natural_key'):
       
   111                         if hasattr(field_value, '__iter__'):
       
   112                             obj = field.rel.to._default_manager.db_manager(db).get_by_natural_key(*field_value)
       
   113                             value = getattr(obj, field.rel.field_name)
       
   114                             # If this is a natural foreign key to an object that
       
   115                             # has a FK/O2O as the foreign key, use the FK value
       
   116                             if field.rel.to._meta.pk.rel:
       
   117                                 value = value.pk
       
   118                         else:
       
   119                             value = field.rel.to._meta.get_field(field.rel.field_name).to_python(field_value)
       
   120                         data[field.attname] = value
       
   121                     else:
       
   122                         data[field.attname] = field.rel.to._meta.get_field(field.rel.field_name).to_python(field_value)
    96                 else:
   123                 else:
    97                     data[field.attname] = None
   124                     data[field.attname] = None
    98 
   125 
    99             # Handle all other fields
   126             # Handle all other fields
   100             else:
   127             else: