Reverting r14994 (at request of SmileyChris) because of some backwards compatibility issues that need to be resolved.
git-svn-id: http://code.djangoproject.com/svn/django/trunk@14995 bcc190cf-cafb-0310-a4f2-bffc1f526a37
This commit is contained in:
parent
b60d5df072
commit
e299ac0cae
|
@ -170,21 +170,3 @@ class DeserializedObject(object):
|
||||||
# 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
|
||||||
|
|
||||||
def build_instance(Model, data, db):
|
|
||||||
"""
|
|
||||||
Build a model instance.
|
|
||||||
|
|
||||||
If the model instance doesn't have a primary key and the model supports
|
|
||||||
natural keys, try to retrieve it from the database.
|
|
||||||
"""
|
|
||||||
obj = Model(**data)
|
|
||||||
if obj.pk is None and hasattr(Model, 'natural_key') and\
|
|
||||||
hasattr(Model._default_manager, 'get_by_natural_key'):
|
|
||||||
pk = obj.natural_key()
|
|
||||||
try:
|
|
||||||
obj.pk = Model._default_manager.db_manager(db)\
|
|
||||||
.get_by_natural_key(*pk).pk
|
|
||||||
except Model.DoesNotExist:
|
|
||||||
pass
|
|
||||||
return obj
|
|
||||||
|
|
|
@ -27,13 +27,11 @@ class Serializer(base.Serializer):
|
||||||
self._current = {}
|
self._current = {}
|
||||||
|
|
||||||
def end_object(self, obj):
|
def end_object(self, obj):
|
||||||
data = {
|
self.objects.append({
|
||||||
"model": smart_unicode(obj._meta),
|
"model" : smart_unicode(obj._meta),
|
||||||
"fields": self._current
|
"pk" : smart_unicode(obj._get_pk_val(), strings_only=True),
|
||||||
}
|
"fields" : self._current
|
||||||
if not self.use_natural_keys or not hasattr(obj, 'natural_key'):
|
})
|
||||||
data['pk'] = smart_unicode(obj._get_pk_val(), strings_only=True)
|
|
||||||
self.objects.append(data)
|
|
||||||
self._current = None
|
self._current = None
|
||||||
|
|
||||||
def handle_field(self, obj, field):
|
def handle_field(self, obj, field):
|
||||||
|
@ -84,9 +82,7 @@ def Deserializer(object_list, **options):
|
||||||
for d in object_list:
|
for d in object_list:
|
||||||
# Look up the model and starting build a dict of data for it.
|
# Look up the model and starting build a dict of data for it.
|
||||||
Model = _get_model(d["model"])
|
Model = _get_model(d["model"])
|
||||||
data = {}
|
data = {Model._meta.pk.attname : Model._meta.pk.to_python(d["pk"])}
|
||||||
if 'pk' in d:
|
|
||||||
data[Model._meta.pk.attname] = Model._meta.pk.to_python(d['pk'])
|
|
||||||
m2m_data = {}
|
m2m_data = {}
|
||||||
|
|
||||||
# Handle each field
|
# Handle each field
|
||||||
|
@ -131,9 +127,7 @@ def Deserializer(object_list, **options):
|
||||||
else:
|
else:
|
||||||
data[field.name] = field.to_python(field_value)
|
data[field.name] = field.to_python(field_value)
|
||||||
|
|
||||||
obj = base.build_instance(Model, data, db)
|
yield base.DeserializedObject(Model(**data), m2m_data)
|
||||||
|
|
||||||
yield base.DeserializedObject(obj, m2m_data)
|
|
||||||
|
|
||||||
def _get_model(model_identifier):
|
def _get_model(model_identifier):
|
||||||
"""
|
"""
|
||||||
|
|
|
@ -42,12 +42,16 @@ class Serializer(base.Serializer):
|
||||||
raise base.SerializationError("Non-model object (%s) encountered during serialization" % type(obj))
|
raise base.SerializationError("Non-model object (%s) encountered during serialization" % type(obj))
|
||||||
|
|
||||||
self.indent(1)
|
self.indent(1)
|
||||||
object_data = {"model": smart_unicode(obj._meta)}
|
|
||||||
if not self.use_natural_keys or not hasattr(obj, 'natural_key'):
|
|
||||||
obj_pk = obj._get_pk_val()
|
obj_pk = obj._get_pk_val()
|
||||||
if obj_pk is not None:
|
if obj_pk is None:
|
||||||
object_data['pk'] = smart_unicode(obj_pk)
|
attrs = {"model": smart_unicode(obj._meta),}
|
||||||
self.xml.startElement("object", object_data)
|
else:
|
||||||
|
attrs = {
|
||||||
|
"pk": smart_unicode(obj._get_pk_val()),
|
||||||
|
"model": smart_unicode(obj._meta),
|
||||||
|
}
|
||||||
|
|
||||||
|
self.xml.startElement("object", attrs)
|
||||||
|
|
||||||
def end_object(self, obj):
|
def end_object(self, obj):
|
||||||
"""
|
"""
|
||||||
|
@ -169,10 +173,13 @@ class Deserializer(base.Deserializer):
|
||||||
Model = self._get_model_from_node(node, "model")
|
Model = self._get_model_from_node(node, "model")
|
||||||
|
|
||||||
# Start building a data dictionary from the object.
|
# Start building a data dictionary from the object.
|
||||||
data = {}
|
# If the node is missing the pk set it to None
|
||||||
if node.hasAttribute('pk'):
|
if node.hasAttribute("pk"):
|
||||||
data[Model._meta.pk.attname] = Model._meta.pk.to_python(
|
pk = node.getAttribute("pk")
|
||||||
node.getAttribute('pk'))
|
else:
|
||||||
|
pk = None
|
||||||
|
|
||||||
|
data = {Model._meta.pk.attname : Model._meta.pk.to_python(pk)}
|
||||||
|
|
||||||
# Also start building a dict of m2m data (this is saved as
|
# Also start building a dict of m2m data (this is saved as
|
||||||
# {m2m_accessor_attribute : [list_of_related_objects]})
|
# {m2m_accessor_attribute : [list_of_related_objects]})
|
||||||
|
@ -203,10 +210,8 @@ class Deserializer(base.Deserializer):
|
||||||
value = field.to_python(getInnerText(field_node).strip())
|
value = field.to_python(getInnerText(field_node).strip())
|
||||||
data[field.name] = value
|
data[field.name] = value
|
||||||
|
|
||||||
obj = base.build_instance(Model, data, self.db)
|
|
||||||
|
|
||||||
# Return a DeserializedObject so that the m2m data has a place to live.
|
# Return a DeserializedObject so that the m2m data has a place to live.
|
||||||
return base.DeserializedObject(obj, m2m_data)
|
return base.DeserializedObject(Model(**data), m2m_data)
|
||||||
|
|
||||||
def _handle_fk_field_node(self, node, field):
|
def _handle_fk_field_node(self, node, field):
|
||||||
"""
|
"""
|
||||||
|
|
|
@ -307,12 +307,6 @@ into the primary key of an actual ``Person`` object.
|
||||||
fields will be effectively unique, you can still use those fields
|
fields will be effectively unique, you can still use those fields
|
||||||
as a natural key.
|
as a natural key.
|
||||||
|
|
||||||
.. versionchanged:: 1.3
|
|
||||||
|
|
||||||
Deserialization of objects with no primary key will always check whether the
|
|
||||||
model's manager has a ``get_by_natural_key()`` method and if so, use it to
|
|
||||||
populate the deserialized object's primary key.
|
|
||||||
|
|
||||||
Serialization of natural keys
|
Serialization of natural keys
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
@ -359,23 +353,6 @@ use the `--natural` command line flag to generate natural keys.
|
||||||
natural keys during serialization, but *not* be able to load those
|
natural keys during serialization, but *not* be able to load those
|
||||||
key values, just don't define the ``get_by_natural_key()`` method.
|
key values, just don't define the ``get_by_natural_key()`` method.
|
||||||
|
|
||||||
.. versionchanged:: 1.3
|
|
||||||
|
|
||||||
When ``use_natural_keys=True`` is specified, the primary key is no longer
|
|
||||||
provided in the serialized data of this object since it can be calculated
|
|
||||||
during deserialization::
|
|
||||||
|
|
||||||
...
|
|
||||||
{
|
|
||||||
"model": "store.person",
|
|
||||||
"fields": {
|
|
||||||
"first_name": "Douglas",
|
|
||||||
"last_name": "Adams",
|
|
||||||
"birth_date": "1952-03-11",
|
|
||||||
}
|
|
||||||
}
|
|
||||||
...
|
|
||||||
|
|
||||||
Dependencies during serialization
|
Dependencies during serialization
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
|
|
@ -264,17 +264,3 @@ class LengthModel(models.Model):
|
||||||
|
|
||||||
def __len__(self):
|
def __len__(self):
|
||||||
return self.data
|
return self.data
|
||||||
|
|
||||||
#Tests for natural keys.
|
|
||||||
class BookManager(models.Manager):
|
|
||||||
def get_by_natural_key(self, isbn13):
|
|
||||||
return self.get(isbn13=isbn13)
|
|
||||||
|
|
||||||
class Book(models.Model):
|
|
||||||
isbn13 = models.CharField(max_length=14)
|
|
||||||
title = models.CharField(max_length=100)
|
|
||||||
|
|
||||||
objects = BookManager()
|
|
||||||
|
|
||||||
def natural_key(self):
|
|
||||||
return (self.isbn13,)
|
|
||||||
|
|
|
@ -414,36 +414,8 @@ def streamTest(format, self):
|
||||||
self.assertEqual(string_data, stream.getvalue())
|
self.assertEqual(string_data, stream.getvalue())
|
||||||
stream.close()
|
stream.close()
|
||||||
|
|
||||||
def naturalKeyTest(format, self):
|
|
||||||
book1 = {'isbn13': '978-1590597255', 'title': 'The Definitive Guide to '
|
|
||||||
'Django: Web Development Done Right'}
|
|
||||||
book2 = {'isbn13':'978-1590599969', 'title': 'Practical Django Projects'}
|
|
||||||
|
|
||||||
# Create the books.
|
|
||||||
adrian = Book.objects.create(**book1)
|
|
||||||
james = Book.objects.create(**book2)
|
|
||||||
|
|
||||||
# Serialize the books.
|
|
||||||
string_data = serializers.serialize(format, Book.objects.all(), indent=2,
|
|
||||||
use_natural_keys=True)
|
|
||||||
|
|
||||||
# Delete one book (to prove that the natural key generation will only
|
|
||||||
# restore the primary keys of books found in the database via the
|
|
||||||
# get_natural_key manager method).
|
|
||||||
james.delete()
|
|
||||||
|
|
||||||
# Deserialize and test.
|
|
||||||
books = list(serializers.deserialize(format, string_data))
|
|
||||||
self.assertEqual(len(books), 2)
|
|
||||||
self.assertEqual(books[0].object.title, book1['title'])
|
|
||||||
self.assertEqual(books[0].object.pk, adrian.pk)
|
|
||||||
self.assertEqual(books[1].object.title, book2['title'])
|
|
||||||
self.assertEqual(books[1].object.pk, None)
|
|
||||||
|
|
||||||
for format in serializers.get_serializer_formats():
|
for format in serializers.get_serializer_formats():
|
||||||
setattr(SerializerTests, 'test_' + format + '_serializer', curry(serializerTest, format))
|
setattr(SerializerTests, 'test_' + format + '_serializer', curry(serializerTest, format))
|
||||||
setattr(SerializerTests, 'test_' + format + '_serializer_fields', curry(fieldsTest, format))
|
setattr(SerializerTests, 'test_' + format + '_serializer_fields', curry(fieldsTest, format))
|
||||||
setattr(SerializerTests, 'test_' + format + '_serializer_natural_key',
|
|
||||||
curry(naturalKeyTest, format))
|
|
||||||
if format != 'python':
|
if format != 'python':
|
||||||
setattr(SerializerTests, 'test_' + format + '_serializer_stream', curry(streamTest, format))
|
setattr(SerializerTests, 'test_' + format + '_serializer_stream', curry(streamTest, format))
|
||||||
|
|
Loading…
Reference in New Issue