Fixed #2611 -- Fixed XML serializer to handle null datetime fields. Thanks for reporting, csdurfee@gmail.com
git-svn-id: http://code.djangoproject.com/svn/django/trunk@3687 bcc190cf-cafb-0310-a4f2-bffc1f526a37
This commit is contained in:
parent
452847a659
commit
22303d6c7d
|
@ -11,7 +11,7 @@ from django.db import models
|
||||||
class SerializationError(Exception):
|
class SerializationError(Exception):
|
||||||
"""Something bad happened during serialization."""
|
"""Something bad happened during serialization."""
|
||||||
pass
|
pass
|
||||||
|
|
||||||
class DeserializationError(Exception):
|
class DeserializationError(Exception):
|
||||||
"""Something bad happened during deserialization."""
|
"""Something bad happened during deserialization."""
|
||||||
pass
|
pass
|
||||||
|
@ -20,15 +20,15 @@ class Serializer(object):
|
||||||
"""
|
"""
|
||||||
Abstract serializer base class.
|
Abstract serializer base class.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def serialize(self, queryset, **options):
|
def serialize(self, queryset, **options):
|
||||||
"""
|
"""
|
||||||
Serialize a queryset.
|
Serialize a queryset.
|
||||||
"""
|
"""
|
||||||
self.options = options
|
self.options = options
|
||||||
|
|
||||||
self.stream = options.get("stream", StringIO())
|
self.stream = options.get("stream", StringIO())
|
||||||
|
|
||||||
self.start_serialization()
|
self.start_serialization()
|
||||||
for obj in queryset:
|
for obj in queryset:
|
||||||
self.start_object(obj)
|
self.start_object(obj)
|
||||||
|
@ -44,61 +44,65 @@ class Serializer(object):
|
||||||
self.end_object(obj)
|
self.end_object(obj)
|
||||||
self.end_serialization()
|
self.end_serialization()
|
||||||
return self.getvalue()
|
return self.getvalue()
|
||||||
|
|
||||||
def get_string_value(self, obj, field):
|
def get_string_value(self, obj, field):
|
||||||
"""
|
"""
|
||||||
Convert a field's value to a string.
|
Convert a field's value to a string.
|
||||||
"""
|
"""
|
||||||
if isinstance(field, models.DateTimeField):
|
if isinstance(field, models.DateTimeField):
|
||||||
value = getattr(obj, field.name).strftime("%Y-%m-%d %H:%M:%S")
|
value = getattr(obj, field.name)
|
||||||
|
if value is None:
|
||||||
|
value = ''
|
||||||
|
else:
|
||||||
|
value = value.strftime("%Y-%m-%d %H:%M:%S")
|
||||||
elif isinstance(field, models.FileField):
|
elif isinstance(field, models.FileField):
|
||||||
value = getattr(obj, "get_%s_url" % field.name, lambda: None)()
|
value = getattr(obj, "get_%s_url" % field.name, lambda: None)()
|
||||||
else:
|
else:
|
||||||
value = field.flatten_data(follow=None, obj=obj).get(field.name, "")
|
value = field.flatten_data(follow=None, obj=obj).get(field.name, "")
|
||||||
return str(value)
|
return str(value)
|
||||||
|
|
||||||
def start_serialization(self):
|
def start_serialization(self):
|
||||||
"""
|
"""
|
||||||
Called when serializing of the queryset starts.
|
Called when serializing of the queryset starts.
|
||||||
"""
|
"""
|
||||||
raise NotImplementedError
|
raise NotImplementedError
|
||||||
|
|
||||||
def end_serialization(self):
|
def end_serialization(self):
|
||||||
"""
|
"""
|
||||||
Called when serializing of the queryset ends.
|
Called when serializing of the queryset ends.
|
||||||
"""
|
"""
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def start_object(self, obj):
|
def start_object(self, obj):
|
||||||
"""
|
"""
|
||||||
Called when serializing of an object starts.
|
Called when serializing of an object starts.
|
||||||
"""
|
"""
|
||||||
raise NotImplementedError
|
raise NotImplementedError
|
||||||
|
|
||||||
def end_object(self, obj):
|
def end_object(self, obj):
|
||||||
"""
|
"""
|
||||||
Called when serializing of an object ends.
|
Called when serializing of an object ends.
|
||||||
"""
|
"""
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def handle_field(self, obj, field):
|
def handle_field(self, obj, field):
|
||||||
"""
|
"""
|
||||||
Called to handle each individual (non-relational) field on an object.
|
Called to handle each individual (non-relational) field on an object.
|
||||||
"""
|
"""
|
||||||
raise NotImplementedError
|
raise NotImplementedError
|
||||||
|
|
||||||
def handle_fk_field(self, obj, field):
|
def handle_fk_field(self, obj, field):
|
||||||
"""
|
"""
|
||||||
Called to handle a ForeignKey field.
|
Called to handle a ForeignKey field.
|
||||||
"""
|
"""
|
||||||
raise NotImplementedError
|
raise NotImplementedError
|
||||||
|
|
||||||
def handle_m2m_field(self, obj, field):
|
def handle_m2m_field(self, obj, field):
|
||||||
"""
|
"""
|
||||||
Called to handle a ManyToManyField.
|
Called to handle a ManyToManyField.
|
||||||
"""
|
"""
|
||||||
raise NotImplementedError
|
raise NotImplementedError
|
||||||
|
|
||||||
def getvalue(self):
|
def getvalue(self):
|
||||||
"""
|
"""
|
||||||
Return the fully serialized queryset.
|
Return the fully serialized queryset.
|
||||||
|
@ -109,7 +113,7 @@ class Deserializer(object):
|
||||||
"""
|
"""
|
||||||
Abstract base deserializer class.
|
Abstract base deserializer class.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, stream_or_string, **options):
|
def __init__(self, stream_or_string, **options):
|
||||||
"""
|
"""
|
||||||
Init this serializer given a stream or a string
|
Init this serializer given a stream or a string
|
||||||
|
@ -123,39 +127,39 @@ class Deserializer(object):
|
||||||
# deserialization starts (otherwise subclass calls to get_model()
|
# deserialization starts (otherwise subclass calls to get_model()
|
||||||
# and friends might fail...)
|
# and friends might fail...)
|
||||||
models.get_apps()
|
models.get_apps()
|
||||||
|
|
||||||
def __iter__(self):
|
def __iter__(self):
|
||||||
return self
|
return self
|
||||||
|
|
||||||
def next(self):
|
def next(self):
|
||||||
"""Iteration iterface -- return the next item in the stream"""
|
"""Iteration iterface -- return the next item in the stream"""
|
||||||
raise NotImplementedError
|
raise NotImplementedError
|
||||||
|
|
||||||
class DeserializedObject(object):
|
class DeserializedObject(object):
|
||||||
"""
|
"""
|
||||||
A deserialzed model.
|
A deserialzed model.
|
||||||
|
|
||||||
Basically a container for holding the pre-saved deserialized data along
|
Basically a container for holding the pre-saved deserialized data along
|
||||||
with the many-to-many data saved with the object.
|
with the many-to-many data saved with the object.
|
||||||
|
|
||||||
Call ``save()`` to save the object (with the many-to-many data) to the
|
Call ``save()`` to save the object (with the many-to-many data) to the
|
||||||
database; call ``save(save_m2m=False)`` to save just the object fields
|
database; call ``save(save_m2m=False)`` to save just the object fields
|
||||||
(and not touch the many-to-many stuff.)
|
(and not touch the many-to-many stuff.)
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, obj, m2m_data=None):
|
def __init__(self, obj, m2m_data=None):
|
||||||
self.object = obj
|
self.object = obj
|
||||||
self.m2m_data = m2m_data
|
self.m2m_data = m2m_data
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return "<DeserializedObject: %s>" % str(self.object)
|
return "<DeserializedObject: %s>" % str(self.object)
|
||||||
|
|
||||||
def save(self, save_m2m=True):
|
def save(self, save_m2m=True):
|
||||||
self.object.save()
|
self.object.save()
|
||||||
if self.m2m_data and save_m2m:
|
if self.m2m_data and save_m2m:
|
||||||
for accessor_name, object_list in self.m2m_data.items():
|
for accessor_name, object_list in self.m2m_data.items():
|
||||||
setattr(self.object, accessor_name, object_list)
|
setattr(self.object, accessor_name, object_list)
|
||||||
|
|
||||||
# prevent a second (possibly accidental) call to save() from saving
|
# prevent a second (possibly accidental) call to save() from saving
|
||||||
# the m2m data twice.
|
# the m2m data twice.
|
||||||
self.m2m_data = None
|
self.m2m_data = None
|
||||||
|
|
Loading…
Reference in New Issue