Ticket #13252: 13252-natural-key-serializing-r16406.diff
File 13252-natural-key-serializing-r16406.diff, 39.1 KB (added by , 13 years ago) |
---|
-
django/core/management/commands/dumpdata.py
diff --git a/django/core/management/commands/dumpdata.py b/django/core/management/commands/dumpdata.py index 706bf60..8d8b63e 100644
a b class Command(BaseCommand): 19 19 help='An appname or appname.ModelName to exclude (use multiple --exclude to exclude multiple apps/models).'), 20 20 make_option('-n', '--natural', action='store_true', dest='use_natural_keys', default=False, 21 21 help='Use natural keys if they are available.'), 22 make_option('--natural-foreign', action='store_true', dest='use_natural_foreign_keys', default=False, 23 help='Use natural foreign keys if they are available.'), 24 make_option('--natural-primary', action='store_true', dest='use_natural_primary_keys', default=False, 25 help='Use natural primary keys if they are available.'), 22 26 make_option('-a', '--all', action='store_true', dest='use_base_manager', default=False, 23 27 help="Use Django's base manager to dump all models stored in the database, including those that would otherwise be filtered or modified by a custom manager."), 24 28 ) … … class Command(BaseCommand): 37 41 excludes = options.get('exclude',[]) 38 42 show_traceback = options.get('traceback', False) 39 43 use_natural_keys = options.get('use_natural_keys', False) 44 if use_natural_keys: 45 # raise pending deprecation warning. 46 pass 47 use_natural_foreign_keys = options.get('use_natural_foreign_keys', False) or use_natural_keys 48 use_natural_primary_keys = options.get('use_natural_primary_keys', False) 40 49 use_base_manager = options.get('use_base_manager', False) 41 50 42 51 excluded_apps = set() … … class Command(BaseCommand): 111 120 112 121 try: 113 122 return serializers.serialize(format, objects, indent=indent, 114 use_natural_keys=use_natural_keys) 123 use_natural_foreign_keys=use_natural_foreign_keys, 124 use_natural_primary_keys=use_natural_primary_keys) 115 125 except Exception, e: 116 126 if show_traceback: 117 127 raise -
django/core/serializers/base.py
diff --git a/django/core/serializers/base.py b/django/core/serializers/base.py index 6afaf21..e9b0f42 100644
a b class Serializer(object): 38 38 self.stream = options.pop("stream", StringIO()) 39 39 self.selected_fields = options.pop("fields", None) 40 40 self.use_natural_keys = options.pop("use_natural_keys", False) 41 if self.use_natural_keys: 42 # raise pending deprecation warning. 43 pass 44 self.use_natural_foreign_keys = options.pop('use_natural_foreign_keys', False) 45 self.use_natural_primary_keys = options.pop('use_natural_primary_keys', False) 41 46 42 47 self.start_serialization() 43 48 for obj in queryset: … … class DeserializedObject(object): 174 179 # prevent a second (possibly accidental) call to save() from saving 175 180 # the m2m data twice. 176 181 self.m2m_data = None 182 183 def build_instance(Model, data, db): 184 """ 185 Build a model instance. 186 187 If the model instance doesn't have a primary key and the model supports 188 natural keys, try to retrieve it from the database. 189 """ 190 obj = Model(**data) 191 if obj.pk is None and hasattr(Model, 'natural_key') and\ 192 hasattr(Model._default_manager, 'get_by_natural_key'): 193 pk = obj.natural_key() 194 try: 195 obj.pk = Model._default_manager.db_manager(db)\ 196 .get_by_natural_key(*pk).pk 197 except Model.DoesNotExist: 198 pass 199 return obj -
django/core/serializers/python.py
diff --git a/django/core/serializers/python.py b/django/core/serializers/python.py index a68ea21..7b839f0 100644
a b class Serializer(base.Serializer): 27 27 self._current = {} 28 28 29 29 def end_object(self, obj): 30 self.objects.append({ 31 "model" : smart_unicode(obj._meta), 32 "pk" : smart_unicode(obj._get_pk_val(), strings_only=True), 33 "fields" : self._current 34 }) 30 if not self.use_natural_primary_keys or not hasattr(obj, 'natural_key'): 31 data = { 32 "model": smart_unicode(obj._meta), 33 "pk": smart_unicode(obj._get_pk_val(), strings_only=True), 34 "fields": self._current, 35 } 36 else: 37 data = { 38 "model": smart_unicode(obj._meta), 39 "fields": self._current 40 } 41 self.objects.append(data) 35 42 self._current = None 36 43 37 44 def handle_field(self, obj, field): … … class Serializer(base.Serializer): 47 54 def handle_fk_field(self, obj, field): 48 55 related = getattr(obj, field.name) 49 56 if related is not None: 50 if self.use_natural_ keys and hasattr(related, 'natural_key'):57 if self.use_natural_foreign_keys and hasattr(related, 'natural_key'): 51 58 related = related.natural_key() 52 59 else: 53 60 if field.rel.field_name == related._meta.pk.name: … … class Serializer(base.Serializer): 60 67 61 68 def handle_m2m_field(self, obj, field): 62 69 if field.rel.through._meta.auto_created: 63 if self.use_natural_ keys and hasattr(field.rel.to, 'natural_key'):70 if self.use_natural_foreign_keys and hasattr(field.rel.to, 'natural_key'): 64 71 m2m_value = lambda value: value.natural_key() 65 72 else: 66 73 m2m_value = lambda value: smart_unicode(value._get_pk_val(), strings_only=True) … … def Deserializer(object_list, **options): 82 89 for d in object_list: 83 90 # Look up the model and starting build a dict of data for it. 84 91 Model = _get_model(d["model"]) 85 data = {Model._meta.pk.attname : Model._meta.pk.to_python(d["pk"])} 92 data = {} 93 if 'pk' in d: 94 data[Model._meta.pk.attname] = Model._meta.pk.to_python(d['pk']) 86 95 m2m_data = {} 87 96 88 97 # Handle each field … … def Deserializer(object_list, **options): 127 136 else: 128 137 data[field.name] = field.to_python(field_value) 129 138 130 yield base.DeserializedObject(Model(**data), m2m_data) 139 obj = base.build_instance(Model, data, db) 140 141 yield base.DeserializedObject(obj, m2m_data) 131 142 132 143 def _get_model(model_identifier): 133 144 """ -
django/core/serializers/xml_serializer.py
diff --git a/django/core/serializers/xml_serializer.py b/django/core/serializers/xml_serializer.py index bcf5631..22205d9 100644
a b class Serializer(base.Serializer): 42 42 raise base.SerializationError("Non-model object (%s) encountered during serialization" % type(obj)) 43 43 44 44 self.indent(1) 45 obj_pk = obj._get_pk_val() 46 if obj_pk is None: 47 attrs = {"model": smart_unicode(obj._meta),} 48 else: 49 attrs = { 50 "pk": smart_unicode(obj._get_pk_val()), 51 "model": smart_unicode(obj._meta), 52 } 53 54 self.xml.startElement("object", attrs) 45 object_data = {"model": smart_unicode(obj._meta)} 46 if not self.use_natural_primary_keys or not hasattr(obj, 'natural_key'): 47 obj_pk = obj._get_pk_val() 48 if obj_pk is not None: 49 object_data['pk'] = smart_unicode(obj_pk) 50 self.xml.startElement("object", object_data) 55 51 56 52 def end_object(self, obj): 57 53 """ … … class Serializer(base.Serializer): 87 83 self._start_relational_field(field) 88 84 related = getattr(obj, field.name) 89 85 if related is not None: 90 if self.use_natural_ keys and hasattr(related, 'natural_key'):86 if self.use_natural_foreign_keys and hasattr(related, 'natural_key'): 91 87 # If related object has a natural key, use it 92 88 related = related.natural_key() 93 89 # Iterable natural keys are rolled out as subelements … … class Serializer(base.Serializer): 115 111 """ 116 112 if field.rel.through._meta.auto_created: 117 113 self._start_relational_field(field) 118 if self.use_natural_ keys and hasattr(field.rel.to, 'natural_key'):114 if self.use_natural_foreign_keys and hasattr(field.rel.to, 'natural_key'): 119 115 # If the objects in the m2m have a natural key, use it 120 116 def handle_m2m(value): 121 117 natural = value.natural_key() … … class Deserializer(base.Deserializer): 173 169 Model = self._get_model_from_node(node, "model") 174 170 175 171 # Start building a data dictionary from the object. 176 # If the node is missing the pk set it to None 177 if node.hasAttribute("pk"): 178 pk = node.getAttribute("pk") 179 else: 180 pk = None 181 182 data = {Model._meta.pk.attname : Model._meta.pk.to_python(pk)} 172 data = {} 173 if node.hasAttribute('pk'): 174 data[Model._meta.pk.attname] = Model._meta.pk.to_python( 175 node.getAttribute('pk')) 183 176 184 177 # Also start building a dict of m2m data (this is saved as 185 178 # {m2m_accessor_attribute : [list_of_related_objects]}) … … class Deserializer(base.Deserializer): 210 203 value = field.to_python(getInnerText(field_node).strip()) 211 204 data[field.name] = value 212 205 206 obj = base.build_instance(Model, data, self.db) 207 213 208 # Return a DeserializedObject so that the m2m data has a place to live. 214 return base.DeserializedObject( Model(**data), m2m_data)209 return base.DeserializedObject(obj, m2m_data) 215 210 216 211 def _handle_fk_field_node(self, node, field): 217 212 """ -
docs/topics/serialization.txt
diff --git a/docs/topics/serialization.txt b/docs/topics/serialization.txt index f0f17b2..06ac347 100644
a b into the primary key of an actual ``Person`` object. 313 313 fields will be effectively unique, you can still use those fields 314 314 as a natural key. 315 315 316 .. versionadded:: 1.4 317 318 Deserialization of objects with no primary key will always check whether the 319 model's manager has a ``get_by_natural_key()`` method and if so, use it to 320 populate the deserialized object's primary key. 321 316 322 Serialization of natural keys 317 323 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 318 324 … … Firstly, you need to add another method -- this time to the model itself:: 335 341 336 342 That method should always return a natural key tuple -- in this 337 343 example, ``(first name, last name)``. Then, when you call 338 ``serializers.serialize()``, you provide a ``use_natural_keys=True`` 339 argument:: 340 341 >>> serializers.serialize('json', [book1, book2], indent=2, use_natural_keys=True) 342 343 When ``use_natural_keys=True`` is specified, Django will use the 344 ``natural_key()`` method to serialize any reference to objects of the 345 type that defines the method. 344 ``serializers.serialize()``, you provide ``use_natural_foreign_keys=True`` 345 or ``use_natural_primary_keys=True`` arguments:: 346 347 >>> serializers.serialize('json', [book1, book2], indent=2, use_natural_foreign_keys=True, use_natural_primary_keys=True) 348 349 When ``use_natural_foreign_keys=True`` is specified, Django will use the 350 ``natural_key()`` method to serialize any foreign key reference to objects 351 of the type that defines the method. 352 353 When ``use_natural_primary_keys=True``is specified, Django will not provide the 354 primary key in the serialized data of this object since it can be calculated 355 during deserialization:: 356 357 ... 358 { 359 "model": "store.person", 360 "fields": { 361 "first_name": "Douglas", 362 "last_name": "Adams", 363 "birth_date": "1952-03-11", 364 } 365 } 366 ... 367 368 This can be useful when you need to load serialized data into an existing 369 database and you cannot guarantee that the serialized primary key value is not 370 already in use, and do not need to ensure that deserialized objects retain the 371 same primary keys. 346 372 347 373 If you are using :djadmin:`dumpdata` to generate serialized data, you 348 use the `--natural` command line flag to generate natural keys. 374 use the `--natural-foreign` and `--natural-primary` command line flags to 375 generate natural keys. 349 376 350 377 .. note:: 351 378 … … use the `--natural` command line flag to generate natural keys. 359 386 natural keys during serialization, but *not* be able to load those 360 387 key values, just don't define the ``get_by_natural_key()`` method. 361 388 389 .. versionchanged:: 1.4 390 391 Previously there was only a ``use_natural_keys`` argument for 392 ``serializers.serialize()`` and the `-n` or `--natural` command line flags. 393 These have been deprecated in favor of the ``use_natural_foreign_keys`` and 394 ``use_natural_primary_keys`` arguments, and the corresponding 395 `--natural-foreign` and `--natural-primary` command line flags. 396 397 The original argument and command line flags remain for backwards 398 compatibility, and map to the new ``use_natural_foreign_keys`` argument and 399 `--natural-foreign` command line flag. 400 362 401 Dependencies during serialization 363 402 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 364 403 -
tests/modeltests/fixtures/tests.py
diff --git a/tests/modeltests/fixtures/tests.py b/tests/modeltests/fixtures/tests.py index 31f72f0..8d1adb7 100644
a b class TestCaseFixtureLoadingTests(TestCase): 25 25 26 26 class FixtureLoadingTests(TestCase): 27 27 28 def _dumpdata_assert(self, args, output, format='json', natural_keys=False, 28 def _dumpdata_assert(self, args, output, format='json', 29 natural_foreign_keys=False, natural_primary_keys=False, 29 30 use_base_manager=False, exclude_list=[]): 30 31 new_io = StringIO.StringIO() 31 32 management.call_command('dumpdata', *args, **{'format':format, 32 33 'stdout':new_io, 33 34 'stderr':new_io, 34 'use_natural_keys':natural_keys, 35 'use_natural_foreign_keys':natural_foreign_keys, 36 'use_natural_primary_keys':natural_primary_keys, 35 37 'use_base_manager':use_base_manager, 36 38 'exclude': exclude_list}) 37 39 command_output = new_io.getvalue().strip() … … class FixtureLoadingTests(TestCase): 149 151 # By default, you get raw keys on dumpdata 150 152 self._dumpdata_assert(['fixtures.book'], '[{"pk": 1, "model": "fixtures.book", "fields": {"name": "Music for all ages", "authors": [3, 1]}}]') 151 153 152 # But you can get natural keys if you ask for them and they are available 153 self._dumpdata_assert(['fixtures.book'], '[{"pk": 1, "model": "fixtures.book", "fields": {"name": "Music for all ages", "authors": [["Artist formerly known as \\"Prince\\""], ["Django Reinhardt"]]}}]', natural_keys=True) 154 # But you can get natural foreign keys if you ask for them and they are available 155 self._dumpdata_assert(['fixtures.book'], '[{"pk": 1, "model": "fixtures.book", "fields": {"name": "Music for all ages", "authors": [["Artist formerly known as \\"Prince\\""], ["Django Reinhardt"]]}}]', natural_foreign_keys=True) 156 157 # You can also omit the primary keys for models that we can get later with natural keys. 158 self._dumpdata_assert(['fixtures.person'], '[{"fields": {"name": "Artist formerly known as \\"Prince\\""}, "model": "fixtures.person"}, {"fields": {"name": "Django Reinhardt"}, "model": "fixtures.person"}, {"fields": {"name": "Stephane Grappelli"}, "model": "fixtures.person"}]', natural_primary_keys=True) 154 159 155 160 # Dump the current contents of the database as a JSON fixture 156 self._dumpdata_assert(['fixtures'], '[{"pk": 1, "model": "fixtures.category", "fields": {"description": "Latest news stories", "title": "News Stories"}}, {"pk": 5, "model": "fixtures.article", "fields": {"headline": "XML identified as leading cause of cancer", "pub_date": "2006-06-16 16:00:00"}}, {"pk": 4, "model": "fixtures.article", "fields": {"headline": "Django conquers world!", "pub_date": "2006-06-16 15:00:00"}}, {"pk": 3, "model": "fixtures.article", "fields": {"headline": "Copyright is fine the way it is", "pub_date": "2006-06-16 14:00:00"}}, {"pk": 2, "model": "fixtures.article", "fields": {"headline": "Poker on TV is great!", "pub_date": "2006-06-16 11:00:00"}}, {"pk": 1, "model": "fixtures.article", "fields": {"headline": "Python program becomes self aware", "pub_date": "2006-06-16 11:00:00"}}, {"pk": 1, "model": "fixtures.tag", "fields": {"tagged_type": ["fixtures", "article"], "name": "copyright", "tagged_id": 3}}, {"pk": 2, "model": "fixtures.tag", "fields": {"tagged_type": ["fixtures", "article"], "name": "legal", "tagged_id": 3}}, {"pk": 3, "model": "fixtures.tag", "fields": {"tagged_type": ["fixtures", "article"], "name": "django", "tagged_id": 4}}, {"pk": 4, "model": "fixtures.tag", "fields": {"tagged_type": ["fixtures", "article"], "name": "world domination", "tagged_id": 4}}, {"pk": 3, "model": "fixtures.person", "fields": {"name": "Artist formerly known as \\"Prince\\""}}, {"pk": 1, "model": "fixtures.person", "fields": {"name": "Django Reinhardt"}}, {"pk": 2, "model": "fixtures.person", "fields": {"name": "Stephane Grappelli"}}, {"pk": 1, "model": "fixtures.visa", "fields": {"person": ["Django Reinhardt"], "permissions": [["add_user", "auth", "user"], ["change_user", "auth", "user"], ["delete_user", "auth", "user"]]}}, {"pk": 2, "model": "fixtures.visa", "fields": {"person": ["Stephane Grappelli"], "permissions": [["add_user", "auth", "user"], ["delete_user", "auth", "user"]]}}, {"pk": 3, "model": "fixtures.visa", "fields": {"person": ["Artist formerly known as \\"Prince\\""], "permissions": [["change_user", "auth", "user"]]}}, {"pk": 1, "model": "fixtures.book", "fields": {"name": "Music for all ages", "authors": [["Artist formerly known as \\"Prince\\""], ["Django Reinhardt"]]}}]', natural_ keys=True)161 self._dumpdata_assert(['fixtures'], '[{"pk": 1, "model": "fixtures.category", "fields": {"description": "Latest news stories", "title": "News Stories"}}, {"pk": 5, "model": "fixtures.article", "fields": {"headline": "XML identified as leading cause of cancer", "pub_date": "2006-06-16 16:00:00"}}, {"pk": 4, "model": "fixtures.article", "fields": {"headline": "Django conquers world!", "pub_date": "2006-06-16 15:00:00"}}, {"pk": 3, "model": "fixtures.article", "fields": {"headline": "Copyright is fine the way it is", "pub_date": "2006-06-16 14:00:00"}}, {"pk": 2, "model": "fixtures.article", "fields": {"headline": "Poker on TV is great!", "pub_date": "2006-06-16 11:00:00"}}, {"pk": 1, "model": "fixtures.article", "fields": {"headline": "Python program becomes self aware", "pub_date": "2006-06-16 11:00:00"}}, {"pk": 1, "model": "fixtures.tag", "fields": {"tagged_type": ["fixtures", "article"], "name": "copyright", "tagged_id": 3}}, {"pk": 2, "model": "fixtures.tag", "fields": {"tagged_type": ["fixtures", "article"], "name": "legal", "tagged_id": 3}}, {"pk": 3, "model": "fixtures.tag", "fields": {"tagged_type": ["fixtures", "article"], "name": "django", "tagged_id": 4}}, {"pk": 4, "model": "fixtures.tag", "fields": {"tagged_type": ["fixtures", "article"], "name": "world domination", "tagged_id": 4}}, {"pk": 3, "model": "fixtures.person", "fields": {"name": "Artist formerly known as \\"Prince\\""}}, {"pk": 1, "model": "fixtures.person", "fields": {"name": "Django Reinhardt"}}, {"pk": 2, "model": "fixtures.person", "fields": {"name": "Stephane Grappelli"}}, {"pk": 1, "model": "fixtures.visa", "fields": {"person": ["Django Reinhardt"], "permissions": [["add_user", "auth", "user"], ["change_user", "auth", "user"], ["delete_user", "auth", "user"]]}}, {"pk": 2, "model": "fixtures.visa", "fields": {"person": ["Stephane Grappelli"], "permissions": [["add_user", "auth", "user"], ["delete_user", "auth", "user"]]}}, {"pk": 3, "model": "fixtures.visa", "fields": {"person": ["Artist formerly known as \\"Prince\\""], "permissions": [["change_user", "auth", "user"]]}}, {"pk": 1, "model": "fixtures.book", "fields": {"name": "Music for all ages", "authors": [["Artist formerly known as \\"Prince\\""], ["Django Reinhardt"]]}}]', natural_foreign_keys=True) 157 162 158 163 # Dump the current contents of the database as an XML fixture 159 164 self._dumpdata_assert(['fixtures'], """<?xml version="1.0" encoding="utf-8"?> 160 <django-objects version="1.0"><object pk="1" model="fixtures.category"><field type="CharField" name="title">News Stories</field><field type="TextField" name="description">Latest news stories</field></object><object pk="5" model="fixtures.article"><field type="CharField" name="headline">XML identified as leading cause of cancer</field><field type="DateTimeField" name="pub_date">2006-06-16 16:00:00</field></object><object pk="4" model="fixtures.article"><field type="CharField" name="headline">Django conquers world!</field><field type="DateTimeField" name="pub_date">2006-06-16 15:00:00</field></object><object pk="3" model="fixtures.article"><field type="CharField" name="headline">Copyright is fine the way it is</field><field type="DateTimeField" name="pub_date">2006-06-16 14:00:00</field></object><object pk="2" model="fixtures.article"><field type="CharField" name="headline">Poker on TV is great!</field><field type="DateTimeField" name="pub_date">2006-06-16 11:00:00</field></object><object pk="1" model="fixtures.article"><field type="CharField" name="headline">Python program becomes self aware</field><field type="DateTimeField" name="pub_date">2006-06-16 11:00:00</field></object><object pk="1" model="fixtures.tag"><field type="CharField" name="name">copyright</field><field to="contenttypes.contenttype" name="tagged_type" rel="ManyToOneRel"><natural>fixtures</natural><natural>article</natural></field><field type="PositiveIntegerField" name="tagged_id">3</field></object><object pk="2" model="fixtures.tag"><field type="CharField" name="name">legal</field><field to="contenttypes.contenttype" name="tagged_type" rel="ManyToOneRel"><natural>fixtures</natural><natural>article</natural></field><field type="PositiveIntegerField" name="tagged_id">3</field></object><object pk="3" model="fixtures.tag"><field type="CharField" name="name">django</field><field to="contenttypes.contenttype" name="tagged_type" rel="ManyToOneRel"><natural>fixtures</natural><natural>article</natural></field><field type="PositiveIntegerField" name="tagged_id">4</field></object><object pk="4" model="fixtures.tag"><field type="CharField" name="name">world domination</field><field to="contenttypes.contenttype" name="tagged_type" rel="ManyToOneRel"><natural>fixtures</natural><natural>article</natural></field><field type="PositiveIntegerField" name="tagged_id">4</field></object><object pk="3" model="fixtures.person"><field type="CharField" name="name">Artist formerly known as "Prince"</field></object><object pk="1" model="fixtures.person"><field type="CharField" name="name">Django Reinhardt</field></object><object pk="2" model="fixtures.person"><field type="CharField" name="name">Stephane Grappelli</field></object><object pk="1" model="fixtures.visa"><field to="fixtures.person" name="person" rel="ManyToOneRel"><natural>Django Reinhardt</natural></field><field to="auth.permission" name="permissions" rel="ManyToManyRel"><object><natural>add_user</natural><natural>auth</natural><natural>user</natural></object><object><natural>change_user</natural><natural>auth</natural><natural>user</natural></object><object><natural>delete_user</natural><natural>auth</natural><natural>user</natural></object></field></object><object pk="2" model="fixtures.visa"><field to="fixtures.person" name="person" rel="ManyToOneRel"><natural>Stephane Grappelli</natural></field><field to="auth.permission" name="permissions" rel="ManyToManyRel"><object><natural>add_user</natural><natural>auth</natural><natural>user</natural></object><object><natural>delete_user</natural><natural>auth</natural><natural>user</natural></object></field></object><object pk="3" model="fixtures.visa"><field to="fixtures.person" name="person" rel="ManyToOneRel"><natural>Artist formerly known as "Prince"</natural></field><field to="auth.permission" name="permissions" rel="ManyToManyRel"><object><natural>change_user</natural><natural>auth</natural><natural>user</natural></object></field></object><object pk="1" model="fixtures.book"><field type="CharField" name="name">Music for all ages</field><field to="fixtures.person" name="authors" rel="ManyToManyRel"><object><natural>Artist formerly known as "Prince"</natural></object><object><natural>Django Reinhardt</natural></object></field></object></django-objects>""", format='xml', natural_ keys=True)165 <django-objects version="1.0"><object pk="1" model="fixtures.category"><field type="CharField" name="title">News Stories</field><field type="TextField" name="description">Latest news stories</field></object><object pk="5" model="fixtures.article"><field type="CharField" name="headline">XML identified as leading cause of cancer</field><field type="DateTimeField" name="pub_date">2006-06-16 16:00:00</field></object><object pk="4" model="fixtures.article"><field type="CharField" name="headline">Django conquers world!</field><field type="DateTimeField" name="pub_date">2006-06-16 15:00:00</field></object><object pk="3" model="fixtures.article"><field type="CharField" name="headline">Copyright is fine the way it is</field><field type="DateTimeField" name="pub_date">2006-06-16 14:00:00</field></object><object pk="2" model="fixtures.article"><field type="CharField" name="headline">Poker on TV is great!</field><field type="DateTimeField" name="pub_date">2006-06-16 11:00:00</field></object><object pk="1" model="fixtures.article"><field type="CharField" name="headline">Python program becomes self aware</field><field type="DateTimeField" name="pub_date">2006-06-16 11:00:00</field></object><object pk="1" model="fixtures.tag"><field type="CharField" name="name">copyright</field><field to="contenttypes.contenttype" name="tagged_type" rel="ManyToOneRel"><natural>fixtures</natural><natural>article</natural></field><field type="PositiveIntegerField" name="tagged_id">3</field></object><object pk="2" model="fixtures.tag"><field type="CharField" name="name">legal</field><field to="contenttypes.contenttype" name="tagged_type" rel="ManyToOneRel"><natural>fixtures</natural><natural>article</natural></field><field type="PositiveIntegerField" name="tagged_id">3</field></object><object pk="3" model="fixtures.tag"><field type="CharField" name="name">django</field><field to="contenttypes.contenttype" name="tagged_type" rel="ManyToOneRel"><natural>fixtures</natural><natural>article</natural></field><field type="PositiveIntegerField" name="tagged_id">4</field></object><object pk="4" model="fixtures.tag"><field type="CharField" name="name">world domination</field><field to="contenttypes.contenttype" name="tagged_type" rel="ManyToOneRel"><natural>fixtures</natural><natural>article</natural></field><field type="PositiveIntegerField" name="tagged_id">4</field></object><object pk="3" model="fixtures.person"><field type="CharField" name="name">Artist formerly known as "Prince"</field></object><object pk="1" model="fixtures.person"><field type="CharField" name="name">Django Reinhardt</field></object><object pk="2" model="fixtures.person"><field type="CharField" name="name">Stephane Grappelli</field></object><object pk="1" model="fixtures.visa"><field to="fixtures.person" name="person" rel="ManyToOneRel"><natural>Django Reinhardt</natural></field><field to="auth.permission" name="permissions" rel="ManyToManyRel"><object><natural>add_user</natural><natural>auth</natural><natural>user</natural></object><object><natural>change_user</natural><natural>auth</natural><natural>user</natural></object><object><natural>delete_user</natural><natural>auth</natural><natural>user</natural></object></field></object><object pk="2" model="fixtures.visa"><field to="fixtures.person" name="person" rel="ManyToOneRel"><natural>Stephane Grappelli</natural></field><field to="auth.permission" name="permissions" rel="ManyToManyRel"><object><natural>add_user</natural><natural>auth</natural><natural>user</natural></object><object><natural>delete_user</natural><natural>auth</natural><natural>user</natural></object></field></object><object pk="3" model="fixtures.visa"><field to="fixtures.person" name="person" rel="ManyToOneRel"><natural>Artist formerly known as "Prince"</natural></field><field to="auth.permission" name="permissions" rel="ManyToManyRel"><object><natural>change_user</natural><natural>auth</natural><natural>user</natural></object></field></object><object pk="1" model="fixtures.book"><field type="CharField" name="name">Music for all ages</field><field to="fixtures.person" name="authors" rel="ManyToManyRel"><object><natural>Artist formerly known as "Prince"</natural></object><object><natural>Django Reinhardt</natural></object></field></object></django-objects>""", format='xml', natural_foreign_keys=True) 161 166 162 167 def test_dumpdata_with_excludes(self): 163 168 # Load fixture1 which has a site, two articles, and a category … … class FixtureLoadingTests(TestCase): 289 294 ]) 290 295 291 296 # Dump the current contents of the database as a JSON fixture 292 self._dumpdata_assert(['fixtures'], '[{"pk": 1, "model": "fixtures.category", "fields": {"description": "Latest news stories", "title": "News Stories"}}, {"pk": 3, "model": "fixtures.article", "fields": {"headline": "Time to reform copyright", "pub_date": "2006-06-16 13:00:00"}}, {"pk": 2, "model": "fixtures.article", "fields": {"headline": "Poker has no place on ESPN", "pub_date": "2006-06-16 12:00:00"}}, {"pk": 1, "model": "fixtures.article", "fields": {"headline": "Python program becomes self aware", "pub_date": "2006-06-16 11:00:00"}}, {"pk": 1, "model": "fixtures.tag", "fields": {"tagged_type": ["fixtures", "article"], "name": "copyright", "tagged_id": 3}}, {"pk": 2, "model": "fixtures.tag", "fields": {"tagged_type": ["fixtures", "article"], "name": "law", "tagged_id": 3}}, {"pk": 1, "model": "fixtures.person", "fields": {"name": "Django Reinhardt"}}, {"pk": 3, "model": "fixtures.person", "fields": {"name": "Prince"}}, {"pk": 2, "model": "fixtures.person", "fields": {"name": "Stephane Grappelli"}}]', natural_ keys=True)297 self._dumpdata_assert(['fixtures'], '[{"pk": 1, "model": "fixtures.category", "fields": {"description": "Latest news stories", "title": "News Stories"}}, {"pk": 3, "model": "fixtures.article", "fields": {"headline": "Time to reform copyright", "pub_date": "2006-06-16 13:00:00"}}, {"pk": 2, "model": "fixtures.article", "fields": {"headline": "Poker has no place on ESPN", "pub_date": "2006-06-16 12:00:00"}}, {"pk": 1, "model": "fixtures.article", "fields": {"headline": "Python program becomes self aware", "pub_date": "2006-06-16 11:00:00"}}, {"pk": 1, "model": "fixtures.tag", "fields": {"tagged_type": ["fixtures", "article"], "name": "copyright", "tagged_id": 3}}, {"pk": 2, "model": "fixtures.tag", "fields": {"tagged_type": ["fixtures", "article"], "name": "law", "tagged_id": 3}}, {"pk": 1, "model": "fixtures.person", "fields": {"name": "Django Reinhardt"}}, {"pk": 3, "model": "fixtures.person", "fields": {"name": "Prince"}}, {"pk": 2, "model": "fixtures.person", "fields": {"name": "Stephane Grappelli"}}]', natural_foreign_keys=True) 293 298 294 299 # Dump the current contents of the database as an XML fixture 295 300 self._dumpdata_assert(['fixtures'], """<?xml version="1.0" encoding="utf-8"?> 296 <django-objects version="1.0"><object pk="1" model="fixtures.category"><field type="CharField" name="title">News Stories</field><field type="TextField" name="description">Latest news stories</field></object><object pk="3" model="fixtures.article"><field type="CharField" name="headline">Time to reform copyright</field><field type="DateTimeField" name="pub_date">2006-06-16 13:00:00</field></object><object pk="2" model="fixtures.article"><field type="CharField" name="headline">Poker has no place on ESPN</field><field type="DateTimeField" name="pub_date">2006-06-16 12:00:00</field></object><object pk="1" model="fixtures.article"><field type="CharField" name="headline">Python program becomes self aware</field><field type="DateTimeField" name="pub_date">2006-06-16 11:00:00</field></object><object pk="1" model="fixtures.tag"><field type="CharField" name="name">copyright</field><field to="contenttypes.contenttype" name="tagged_type" rel="ManyToOneRel"><natural>fixtures</natural><natural>article</natural></field><field type="PositiveIntegerField" name="tagged_id">3</field></object><object pk="2" model="fixtures.tag"><field type="CharField" name="name">law</field><field to="contenttypes.contenttype" name="tagged_type" rel="ManyToOneRel"><natural>fixtures</natural><natural>article</natural></field><field type="PositiveIntegerField" name="tagged_id">3</field></object><object pk="1" model="fixtures.person"><field type="CharField" name="name">Django Reinhardt</field></object><object pk="3" model="fixtures.person"><field type="CharField" name="name">Prince</field></object><object pk="2" model="fixtures.person"><field type="CharField" name="name">Stephane Grappelli</field></object></django-objects>""", format='xml', natural_ keys=True)301 <django-objects version="1.0"><object pk="1" model="fixtures.category"><field type="CharField" name="title">News Stories</field><field type="TextField" name="description">Latest news stories</field></object><object pk="3" model="fixtures.article"><field type="CharField" name="headline">Time to reform copyright</field><field type="DateTimeField" name="pub_date">2006-06-16 13:00:00</field></object><object pk="2" model="fixtures.article"><field type="CharField" name="headline">Poker has no place on ESPN</field><field type="DateTimeField" name="pub_date">2006-06-16 12:00:00</field></object><object pk="1" model="fixtures.article"><field type="CharField" name="headline">Python program becomes self aware</field><field type="DateTimeField" name="pub_date">2006-06-16 11:00:00</field></object><object pk="1" model="fixtures.tag"><field type="CharField" name="name">copyright</field><field to="contenttypes.contenttype" name="tagged_type" rel="ManyToOneRel"><natural>fixtures</natural><natural>article</natural></field><field type="PositiveIntegerField" name="tagged_id">3</field></object><object pk="2" model="fixtures.tag"><field type="CharField" name="name">law</field><field to="contenttypes.contenttype" name="tagged_type" rel="ManyToOneRel"><natural>fixtures</natural><natural>article</natural></field><field type="PositiveIntegerField" name="tagged_id">3</field></object><object pk="1" model="fixtures.person"><field type="CharField" name="name">Django Reinhardt</field></object><object pk="3" model="fixtures.person"><field type="CharField" name="name">Prince</field></object><object pk="2" model="fixtures.person"><field type="CharField" name="name">Stephane Grappelli</field></object></django-objects>""", format='xml', natural_foreign_keys=True) 297 302 298 303 class FixtureTransactionTests(TransactionTestCase): 299 304 def _dumpdata_assert(self, args, output, format='json'): -
tests/regressiontests/fixtures_regress/tests.py
diff --git a/tests/regressiontests/fixtures_regress/tests.py b/tests/regressiontests/fixtures_regress/tests.py index 3dc4ede..b43f4c8 100644
a b class NaturalKeyFixtureTests(TestCase): 451 451 'fixtures_regress.store', 452 452 verbosity=0, 453 453 format='json', 454 use_natural_keys=True, 454 use_natural_foreign_keys=True, 455 use_natural_primary_keys=True, 455 456 stdout=stdout, 456 457 ) 457 458 self.assertEqual( 458 459 stdout.getvalue(), 459 """[{" pk": 2, "model": "fixtures_regress.store", "fields": {"name": "Amazon"}}, {"pk": 3, "model": "fixtures_regress.store", "fields": {"name": "Borders"}}, {"pk": 4, "model": "fixtures_regress.person", "fields": {"name": "Neal Stephenson"}}, {"pk": 1, "model": "fixtures_regress.book", "fields": {"stores": [["Amazon"], ["Borders"]], "name": "Cryptonomicon", "author": ["Neal Stephenson"]}}]"""460 """[{"fields": {"name": "Amazon"}, "model": "fixtures_regress.store"}, {"fields": {"name": "Borders"}, "model": "fixtures_regress.store"}, {"fields": {"name": "Neal Stephenson"}, "model": "fixtures_regress.person"}, {"pk": 1, "model": "fixtures_regress.book", "fields": {"stores": [["Amazon"], ["Borders"]], "name": "Cryptonomicon", "author": ["Neal Stephenson"]}}]""" 460 461 ) 461 462 462 463 def test_dependency_sorting(self): -
tests/regressiontests/serializers_regress/models.py
diff --git a/tests/regressiontests/serializers_regress/models.py b/tests/regressiontests/serializers_regress/models.py index b3ae1fe..780c0cd 100644
a b class LengthModel(models.Model): 264 264 265 265 def __len__(self): 266 266 return self.data 267 268 #Tests for natural keys. 269 class BookManager(models.Manager): 270 def get_by_natural_key(self, isbn13): 271 return self.get(isbn13=isbn13) 272 273 class Book(models.Model): 274 isbn13 = models.CharField(max_length=14) 275 title = models.CharField(max_length=100) 276 277 objects = BookManager() 278 279 def natural_key(self): 280 return (self.isbn13,) -
tests/regressiontests/serializers_regress/tests.py
diff --git a/tests/regressiontests/serializers_regress/tests.py b/tests/regressiontests/serializers_regress/tests.py index 90a438c..116a8f7 100644
a b def streamTest(format, self): 436 436 self.assertEqual(string_data, stream.getvalue()) 437 437 stream.close() 438 438 439 def naturalKeyTest(format, self): 440 book1 = {'isbn13': '978-1590597255', 'title': 'The Definitive Guide to ' 441 'Django: Web Development Done Right'} 442 book2 = {'isbn13':'978-1590599969', 'title': 'Practical Django Projects'} 443 444 # Create the books. 445 adrian = Book.objects.create(**book1) 446 james = Book.objects.create(**book2) 447 448 # Serialize the books. 449 string_data = serializers.serialize(format, Book.objects.all(), indent=2, 450 use_natural_foreign_keys=True, 451 use_natural_primary_keys=True) 452 453 # Delete one book (to prove that the natural key generation will only 454 # restore the primary keys of books found in the database via the 455 # get_natural_key manager method). 456 james.delete() 457 458 # Deserialize and test. 459 books = list(serializers.deserialize(format, string_data)) 460 self.assertEqual(len(books), 2) 461 self.assertEqual(books[0].object.title, book1['title']) 462 self.assertEqual(books[0].object.pk, adrian.pk) 463 self.assertEqual(books[1].object.title, book2['title']) 464 self.assertEqual(books[1].object.pk, None) 465 439 466 for format in serializers.get_serializer_formats(): 440 467 setattr(SerializerTests, 'test_' + format + '_serializer', curry(serializerTest, format)) 441 468 setattr(SerializerTests, 'test_' + format + '_serializer_fields', curry(fieldsTest, format)) 469 setattr(SerializerTests, 'test_' + format + '_serializer_natural_keys', curry(naturalKeyTest, format)) 442 470 if format != 'python': 443 471 setattr(SerializerTests, 'test_' + format + '_serializer_stream', curry(streamTest, format))