Ticket #7052: lookup-dictionaries-for-fixtures.patch
File lookup-dictionaries-for-fixtures.patch, 34.8 KB (added by , 15 years ago) |
---|
-
django/contrib/auth/models.py
diff --git a/django/contrib/auth/models.py b/django/contrib/auth/models.py
a b class Permission(models.Model): 68 68 verbose_name = _('permission') 69 69 verbose_name_plural = _('permissions') 70 70 unique_together = (('content_type', 'codename'),) 71 dump_relation = unique_together[0] 71 72 ordering = ('content_type__app_label', 'codename') 72 73 73 74 def __unicode__(self): -
django/contrib/contenttypes/models.py
diff --git a/django/contrib/contenttypes/models.py b/django/contrib/contenttypes/models.py
a b class ContentType(models.Model): 73 73 db_table = 'django_content_type' 74 74 ordering = ('name',) 75 75 unique_together = (('app_label', 'model'),) 76 dump_relation = unique_together[0] 76 77 77 78 def __unicode__(self): 78 79 return self.name 80 81 def load_related(cls, value): 82 try: 83 app_label = value['app_label'] 84 model = value['model'] 85 except (KeyError, TypeError): 86 return super(ContentType, cls).load_related(value) 87 return cls.objects.get_for_model(models.get_model(app_label, model))._get_pk_val() 88 load_related = classmethod(load_related) 79 89 80 90 def model_class(self): 81 91 "Returns the Python model class for this type of content." -
django/core/serializers/python.py
diff --git a/django/core/serializers/python.py b/django/core/serializers/python.py
a b from django.db import models 9 9 from django.db import models 10 10 from django.utils.encoding import smart_unicode 11 11 from django.utils.safestring import mark_safe 12 13 class RelationDepthExceeded(RuntimeError): 14 pass 12 15 13 16 class Serializer(base.Serializer): 14 17 """ … … class Serializer(base.Serializer): 42 45 value = smart_unicode(getattr(obj, field.name), strings_only=True) 43 46 self._current[field.name] = value 44 47 48 def _handle_related(cls, related, depth, maxdepth): 49 if depth > maxdepth: 50 raise RelationDepthExceeded() 51 if hasattr(related, 'dump_related'): 52 related = related.dump_related() 53 if hasattr(related, 'iteritems'): 54 return dict([(k, cls._handle_related(v, depth+1, maxdepth)) 55 for k, v in related.iteritems()]) 56 return smart_unicode(related, strings_only=True) 57 _handle_related = classmethod(_handle_related) 58 59 def handle_related(cls, related, maxdepth=10): 60 try: 61 return cls._handle_related(related, depth=0, maxdepth=maxdepth) 62 except RelationDepthExceeded: 63 raise RelationDepthExceeded("%s has a circular dump dependency" % 64 related) 65 handle_related = classmethod(handle_related) 66 45 67 def handle_fk_field(self, obj, field): 46 68 related = getattr(obj, field.name) 47 69 if related is not None: 48 70 if field.rel.field_name == related._meta.pk.name: 49 71 # Related to remote object via primary key 50 related = related._get_pk_val()72 related = self.handle_related(related) 51 73 else: 52 74 # Related to remote object via other field 53 related = getattr(related, field.rel.field_name)54 self._current[field.name] = smart_unicode(related, strings_only=True)75 related = smart_unicode(getattr(related, field.rel.field_name), strings_only=True) 76 self._current[field.name] = related 55 77 56 78 def handle_m2m_field(self, obj, field): 57 79 if field.creates_table: 58 self._current[field.name] = [s mart_unicode(related._get_pk_val(), strings_only=True)80 self._current[field.name] = [self.handle_related(related) 59 81 for related in getattr(obj, field.name).iterator()] 60 82 61 83 def getvalue(self): … … def Deserializer(object_list, **options) 87 109 88 110 # Handle M2M relations 89 111 if field.rel and isinstance(field.rel, models.ManyToManyRel): 90 m2m_convert = field.rel.to. _meta.pk.to_python91 m2m_data[field.name] = [m2m_convert( smart_unicode(pk)) for pk in field_value]112 m2m_convert = field.rel.to.load_related 113 m2m_data[field.name] = [m2m_convert(pk) for pk in field_value] 92 114 93 115 # Handle FK fields 94 116 elif field.rel and isinstance(field.rel, models.ManyToOneRel): 95 if field_value is not None: 117 if field_value is None: 118 data[field.attname] = None 119 elif field.rel.field_name == field.rel.to._meta.pk.name: 120 data[field.attname] = field.rel.to.load_related(field_value) 121 else: 96 122 data[field.attname] = field.rel.to._meta.get_field(field.rel.field_name).to_python(field_value) 97 else:98 data[field.attname] = None99 123 100 124 # Handle all other fields 101 125 else: -
django/core/serializers/xml_serializer.py
diff --git a/django/core/serializers/xml_serializer.py b/django/core/serializers/xml_serializer.py
a b class Serializer(base.Serializer): 76 76 77 77 self.xml.endElement("field") 78 78 79 def _handle_related(self, related, depth): 80 if hasattr(related, 'iteritems'): 81 for name, value in related.iteritems(): 82 self.indent(depth) 83 self.xml.startElement("lookup", attrs={"name" : name}) 84 self._handle_related(value, depth+1) 85 self.xml.endElement("lookup") 86 if related: 87 self.indent(depth - 1) 88 else: 89 self.xml.characters(smart_unicode(related)) 90 91 79 92 def handle_fk_field(self, obj, field): 80 93 """ 81 94 Called to handle a ForeignKey (we need to treat them slightly … … class Serializer(base.Serializer): 86 99 if related is not None: 87 100 if field.rel.field_name == related._meta.pk.name: 88 101 # Related to remote object via primary key 89 related = related._get_pk_val()102 self._handle_related(related.dump_related(), depth=3) 90 103 else: 91 104 # Related to remote object via other field 92 related = getattr(related, field.rel.field_name) 93 self.xml.characters(smart_unicode(related)) 105 self.xml.characters(smart_unicode(getattr(related, field.rel.field_name))) 94 106 else: 95 107 self.xml.addQuickElement("None") 96 108 self.xml.endElement("field") … … class Serializer(base.Serializer): 104 116 if field.creates_table: 105 117 self._start_relational_field(field) 106 118 for relobj in getattr(obj, field.name).iterator(): 107 self.xml.addQuickElement("object", attrs={"pk" : smart_unicode(relobj._get_pk_val())}) 119 related = relobj.dump_related() 120 self.indent(3) 121 if hasattr(related, 'iteritems'): 122 self.xml.startElement("object", {}) 123 self._handle_related(related, depth=4) 124 self.xml.endElement("object") 125 else: 126 self.xml.addQuickElement("object", attrs={"pk" : smart_unicode(relobj._get_pk_val())}) 127 self.indent(2) 108 128 self.xml.endElement("field") 109 129 110 130 def _start_relational_field(self, field): … … class Deserializer(base.Deserializer): 185 205 # Return a DeserializedObject so that the m2m data has a place to live. 186 206 return base.DeserializedObject(Model(**data), m2m_data) 187 207 208 def _handle_lookup_node(self, node): 209 # There are <lookup> nodes inside `node` 210 value = "" 211 lookup = {} 212 for n in node.childNodes: 213 if n.nodeType in (node.TEXT_NODE, node.CDATA_SECTION_NODE): 214 value += n.data.strip() 215 elif n.nodeName == "lookup": 216 lookup[str(n.getAttribute("name"))] = self._handle_lookup_node(n) 217 else: 218 raise base.DeserializationError("Unexpected <%s> node" % n.nodeName) 219 if value and lookup: 220 raise base.DeserializationError("Unexpected primary key inside <lookup> node") 221 return lookup or value 222 223 def _handle_object_node(self, node, field, m2m): 224 lookup = self._handle_lookup_node(node) 225 if m2m: 226 # Get the "pk" attribute from the <object> nodes 227 pk = node.getAttribute("pk") 228 elif not hasattr(lookup, 'iteritems'): 229 # `node` should only contain TextNode 230 pk = getInnerText(node).strip() 231 else: 232 # 'node' contains a lookup dictionary 233 pk = False 234 if not pk and not lookup: 235 if m2m: 236 raise base.DeserializationError("<object> node is missing the 'pk' attribute") 237 else: 238 raise base.DeserializationError("Must have either primary key or <lookup> nodes") 239 if m2m and pk: 240 return pk 241 elif pk: 242 return field.rel.to._meta.get_field(field.rel.field_name).to_python(pk) 243 else: 244 return field.rel.to.load_related(lookup) 245 188 246 def _handle_fk_field_node(self, node, field): 189 247 """ 190 248 Handle a <field> node for a ForeignKey 191 249 """ 192 250 # Check if there is a child node named 'None', returning None if so. 193 if node.getElementsByTagName( 'None'):251 if node.getElementsByTagName("None"): 194 252 return None 195 else: 196 return field.rel.to._meta.get_field(field.rel.field_name).to_python( 197 getInnerText(node).strip()) 253 return self._handle_object_node(node, field, m2m=False) 198 254 199 255 def _handle_m2m_field_node(self, node, field): 200 256 """ 201 257 Handle a <field> node for a ManyToManyField. 202 258 """ 203 return [ field.rel.to._meta.pk.to_python(204 c.getAttribute("pk"))205 for c in node.getElementsByTagName("object")]259 return [self._handle_object_node(c, field, m2m=True) 260 for c in node.getElementsByTagName("object")] 261 return result 206 262 207 263 def _get_model_from_node(self, node, attr): 208 264 """ -
django/db/models/base.py
diff --git a/django/db/models/base.py b/django/db/models/base.py
a b class Model(object): 295 295 return setattr(self, self._meta.pk.attname, value) 296 296 297 297 pk = property(_get_pk_val, _set_pk_val) 298 299 def dump_related(self): 300 """ 301 Returns a Python object that is the serialization for this Model. 302 303 By default, this method just returns the primary key for this Model. 304 305 If 'Meta.dump_relation' is a tuple of field names, then this 306 method returns a dictionary of lookup fields for a QuerySet. 307 The tuple in 'dump_relation' should also appear in 308 'Meta.unique_together', so that only one object can be fetched 309 based on this lookup. 310 """ 311 dump_relation = getattr(self._meta, 'dump_relation', []) 312 if dump_relation: 313 return dict([(field_name, getattr(self, field_name)) 314 for field_name in dump_relation]) 315 return self._get_pk_val() 316 317 def load_related(cls, value): 318 """ 319 Returns the primary key for this Model, given a certain 'value'. 320 321 Use this in deserialization to handle objects that are created 322 automatically (e.g. auth.Permissions or contenttypes.ContentType). 323 324 'value' can be: 325 - None, 326 - a primary key itself, in string or integer form, 327 - a query dictionary, as generated by dump_related() above. 328 """ 329 if value is None: 330 return None 331 if hasattr(value, 'iteritems'): 332 # Case to handle query dictionaries 333 lookup = {} 334 for field_name, field_value in value.iteritems(): 335 field_name = str(field_name) 336 if hasattr(field_value, 'iteritems'): 337 # Turn subqueries into primary keys 338 field = cls._meta.get_field(field_name) 339 field_value = field.rel.to.load_related(field_value) 340 lookup[field_name] = field_value 341 return cls._default_manager.get(**lookup)._get_pk_val() 342 # Simple case for primary keys 343 return cls._meta.pk.to_python(value) 344 load_related = classmethod(load_related) 298 345 299 346 def save(self, force_insert=False, force_update=False): 300 347 """ -
django/db/models/options.py
diff --git a/django/db/models/options.py b/django/db/models/options.py
a b get_verbose_name = lambda class_name: re 19 19 get_verbose_name = lambda class_name: re.sub('(((?<=[a-z])[A-Z])|([A-Z](?![A-Z]|$)))', ' \\1', class_name).lower().strip() 20 20 21 21 DEFAULT_NAMES = ('verbose_name', 'db_table', 'ordering', 22 'unique_together', ' permissions', 'get_latest_by',22 'unique_together', 'dump_relation', 'permissions', 'get_latest_by', 23 23 'order_with_respect_to', 'app_label', 'db_tablespace', 24 24 'abstract') 25 25 … … class Options(object): 32 32 self.db_table = '' 33 33 self.ordering = [] 34 34 self.unique_together = [] 35 self.dump_relation = [] 35 36 self.permissions = [] 36 37 self.object_name, self.app_label = None, app_label 37 38 self.get_latest_by = None -
docs/ref/models/instances.txt
diff --git a/docs/ref/models/instances.txt b/docs/ref/models/instances.txt
a b More details on named URL patterns are i 360 360 More details on named URL patterns are in the :ref:`URL dispatch documentation 361 361 <topics-http-urls>`. 362 362 363 .. _lookup-dictionary: 364 365 Serializing and deserializing auto-created objects 366 ================================================== 367 368 .. versionadded:: development 369 370 In certain circumstances, a model needs to create objects based on 371 other models in an application. For instance, whenever a 372 :class:`~django.db.models.Model` is defined, Django will eventually 373 create corresponding :class:`~django.contrib.auth.models.Permission` 374 objects. 375 376 Models with a :ref:`forward relationship<related-objects>` to 377 automatically created objects, such as ``Permission``, need help when 378 serializing and deserializing these references. This happens whenever 379 you create or load a fixture. Since ``Permission`` objects can be 380 created in any order, they cannot be reliably referenced by their 381 primary keys during serialization. Instead, they are referenced by a 382 lookup dictionary. 383 384 ``dump_relation`` 385 ----------------- 386 387 When writing a class that will be referenced by a lookup dictionary, 388 you should specify :attr:`Options.dump_relation`. For more 389 information, see the :ref:`model option reference<ref-models-options>`. 390 391 Methods for handling custom relations 392 ------------------------------------- 393 394 If :attr:`dump_related` is too inflexible for a particular model, you 395 can override the following methods to serialize and deserialize custom 396 lookup dictionaries. 397 398 .. method:: Model.dump_related() 399 400 Defines a ``dump_related()`` method to tell Django how to build a lookup 401 dictionary for this model. For example:: 402 403 def dump_related(self): 404 return {'year': self.year, 'month': self.month, 'day': self.day} 405 406 Django uses this when serializing objects, which typically happens when 407 :djadmin:`dumpdata<dumpdata>` is run. 408 409 .. method:: Model.load_related(value) 410 411 Defines a ``load_related()`` method to tell Django how to find the 412 primary key for this model, when deserializing. It returns the primary 413 key associated with ``value``, which was created by 414 :meth:`Model.dump_related()`. For example:: 415 416 def load_related(cls, value): 417 year, month, day = value.year, value.month, value.day 418 return cls.objects.get(year=year, month=month, day=day).id 419 load_related = classmethod(load_related) 420 421 Django uses this method when deserializing objects which have 422 :class:`~django.db.models.ForeignKey`, 423 :class:`~django.db.models.ManyToManyField`, or 424 :class:`~django.db.models.OneToOneField` relationships to objects that 425 were created automatically, such as 426 :class:`~django.contrib.auth.models.Permission` or 427 :class:`~django.contrib.contenttypes.models.ContentType` objects. This 428 typically happens when :djadmin:`loaddata<loaddata>` is run. 429 363 430 Extra instance methods 364 431 ====================== 365 432 -
docs/ref/models/options.txt
diff --git a/docs/ref/models/options.txt b/docs/ref/models/options.txt
a b Django quotes column and table names beh 59 59 60 60 The name of the database tablespace to use for the model. If the backend doesn't 61 61 support tablespaces, this option is ignored. 62 63 ``dump_relation`` 64 ----------------- 65 66 .. attribute:: Options.dump_relation 67 68 .. versionadded:: development 69 70 Set of field names that, taken together, that define a :ref:`lookup 71 dictionary<lookup-dictionary>` for serialization:: 72 73 dump_relation = ("driver", "restaurant") 74 75 It's used by :meth:`Model.dump_related()` to build a lookup dictionary 76 when serializing a reference to this model. 77 78 Since these fields are used to fetch a single object, they should also 79 appear in :attr:`~Options.unique_together`. 62 80 63 81 ``get_latest_by`` 64 82 ----------------- -
docs/topics/db/queries.txt
diff --git a/docs/topics/db/queries.txt b/docs/topics/db/queries.txt
a b Just loop over them and call ``save()``: 749 749 for item in my_queryset: 750 750 item.save() 751 751 752 .. _related-objects: 753 752 754 Related objects 753 755 =============== 754 756 -
new file tests/modeltests/fixtures/fixtures/fixture4.json
diff --git a/tests/modeltests/fixtures/fixtures/fixture4.json b/tests/modeltests/fixtures/fixtures/fixture4.json new file mode 100644
- + 1 [ 2 { 3 "pk": "1", 4 "model": "fixtures.tag", 5 "fields": { 6 "name": "copyright", 7 "tagged_type": { 8 "app_label": "fixtures", 9 "model": "article" 10 }, 11 "tagged_id": "3" 12 } 13 }, 14 { 15 "pk": "2", 16 "model": "fixtures.tag", 17 "fields": { 18 "name": "law", 19 "tagged_type": { 20 "app_label": "fixtures", 21 "model": "article" 22 }, 23 "tagged_id": "3" 24 } 25 } 26 ] -
new file tests/modeltests/fixtures/fixtures/fixture5.xml
diff --git a/tests/modeltests/fixtures/fixtures/fixture5.xml b/tests/modeltests/fixtures/fixtures/fixture5.xml new file mode 100644
- + 1 <?xml version="1.0" encoding="utf-8"?> 2 <django-objects version="1.0"> 3 <object pk="2" model="fixtures.tag"> 4 <field type="CharField" name="name">legal</field> 5 <field to="contenttypes.contenttype" name="tagged_type" rel="ManyToOneRel"> 6 <lookup name="app_label">fixtures</lookup> 7 <lookup name="model">article</lookup> 8 </field> 9 <field type="PositiveIntegerField" name="tagged_id">3</field> 10 </object> 11 <object pk="3" model="fixtures.tag"> 12 <field type="CharField" name="name">django</field> 13 <field to="contenttypes.contenttype" name="tagged_type" rel="ManyToOneRel"> 14 <lookup name="app_label">fixtures</lookup> 15 <lookup name="model">article</lookup> 16 </field> 17 <field type="PositiveIntegerField" name="tagged_id">4</field> 18 </object> 19 <object pk="4" model="fixtures.tag"> 20 <field type="CharField" name="name">world domination</field> 21 <field to="contenttypes.contenttype" name="tagged_type" rel="ManyToOneRel"> 22 <lookup name="app_label">fixtures</lookup> 23 <lookup name="model">article</lookup> 24 </field> 25 <field type="PositiveIntegerField" name="tagged_id">4</field> 26 </object> 27 </django-objects> -
new file tests/modeltests/fixtures/fixtures/fixture6.json
diff --git a/tests/modeltests/fixtures/fixtures/fixture6.json b/tests/modeltests/fixtures/fixtures/fixture6.json new file mode 100644
- + 1 [ 2 { 3 "pk": "1", 4 "model": "fixtures.visa", 5 "fields": { 6 "name": "Django Reinhardt", 7 "permissions": [ 8 { 9 "codename": "add_user", 10 "content_type": { 11 "model": "user", 12 "app_label": "auth" 13 } 14 }, 15 { 16 "codename": "change_user", 17 "content_type": { 18 "model": "user", 19 "app_label": "auth" 20 } 21 }, 22 { 23 "codename": "delete_user", 24 "content_type": { 25 "model": "user", 26 "app_label": "auth" 27 } 28 } 29 ] 30 } 31 }, 32 { 33 "pk": "2", 34 "model": "fixtures.visa", 35 "fields": { 36 "name": "Stephane Grappelli", 37 "permissions": [ 38 { 39 "codename": "add_user", 40 "content_type": { 41 "model": "user", 42 "app_label": "auth" 43 } 44 } 45 ] 46 } 47 }, 48 { 49 "pk": "3", 50 "model": "fixtures.visa", 51 "fields": { 52 "name": "Prince", 53 "permissions": [] 54 } 55 } 56 ] -
new file tests/modeltests/fixtures/fixtures/fixture7.xml
diff --git a/tests/modeltests/fixtures/fixtures/fixture7.xml b/tests/modeltests/fixtures/fixtures/fixture7.xml new file mode 100644
- + 1 <?xml version="1.0" encoding="utf-8"?> 2 <django-objects version="1.0"> 3 <object pk="2" model="fixtures.visa"> 4 <field type="CharField" name="name">Stephane Grappelli</field> 5 <field to="auth.permission" name="permissions" rel="ManyToManyRel"> 6 <object> 7 <lookup name="codename">add_user</lookup> 8 <lookup name="content_type"> 9 <lookup name="model">user</lookup> 10 <lookup name="app_label">auth</lookup> 11 </lookup> 12 </object> 13 <object> 14 <lookup name="codename">delete_user</lookup> 15 <lookup name="content_type"> 16 <lookup name="model">user</lookup> 17 <lookup name="app_label">auth</lookup> 18 </lookup> 19 </object> 20 </field> 21 </object> 22 <object pk="3" model="fixtures.visa"> 23 <field type="CharField" name="name">Artist formerly known as "Prince"</field> 24 <field to="auth.permission" name="permissions" rel="ManyToManyRel"></field> 25 </object> 26 </django-objects> -
tests/modeltests/fixtures/models.py
diff --git a/tests/modeltests/fixtures/models.py b/tests/modeltests/fixtures/models.py
a b in the application directory, on in one 8 8 ``FIXTURE_DIRS`` setting. 9 9 """ 10 10 11 from django.contrib.auth.models import Permission 12 from django.contrib.contenttypes import generic 13 from django.contrib.contenttypes.models import ContentType 11 14 from django.db import models 12 15 from django.conf import settings 13 16 … … class Article(models.Model): 20 23 21 24 class Meta: 22 25 ordering = ('-pub_date', 'headline') 26 27 class Blog(models.Model): 28 name = models.CharField(max_length=100) 29 featured = models.ForeignKey(Article, related_name='fixtures_featured_set') 30 articles = models.ManyToManyField(Article, blank=True, 31 related_name='fixtures_articles_set') 32 33 def __unicode__(self): 34 return self.name 35 36 37 class Tag(models.Model): 38 name = models.CharField(max_length=100) 39 tagged_type = models.ForeignKey(ContentType, related_name="fixtures_tag_set") 40 tagged_id = models.PositiveIntegerField(default=0) 41 tagged = generic.GenericForeignKey(ct_field='tagged_type', 42 fk_field='tagged_id') 43 44 def __unicode__(self): 45 return '<%s: %s> tagged "%s"' % (self.tagged.__class__.__name__, 46 self.tagged, self.name) 47 48 class Visa(models.Model): 49 name = models.CharField(max_length=100) 50 permissions = models.ManyToManyField(Permission, blank=True) 51 52 def __unicode__(self): 53 return '%s %s' % (self.name, 54 ', '.join(p.name for p in self.permissions.all())) 23 55 24 56 __test__ = {'API_TESTS': """ 25 57 >>> from django.core import management … … __test__ = {'API_TESTS': """ 48 80 >>> Article.objects.all() 49 81 [<Article: XML identified as leading cause of cancer>, <Article: Django conquers world!>, <Article: Copyright is fine the way it is>, <Article: Poker on TV is great!>, <Article: Python program becomes self aware>] 50 82 83 # Load fixture 4, JSON file with dynamic ContentType fields. Testing ManyToOne. 84 >>> management.call_command('loaddata', 'fixture4.json', verbosity=0) 85 >>> Tag.objects.all() 86 [<Tag: <Article: Copyright is fine the way it is> tagged "copyright">, <Tag: <Article: Copyright is fine the way it is> tagged "law">] 87 88 # Load fixture 5, XML file with dynamic ContentType fields. Testing ManyToOne. 89 >>> management.call_command('loaddata', 'fixture5.xml', verbosity=0) 90 >>> Tag.objects.all() 91 [<Tag: <Article: Copyright is fine the way it is> tagged "copyright">, <Tag: <Article: Copyright is fine the way it is> tagged "legal">, <Tag: <Article: Django conquers world!> tagged "django">, <Tag: <Article: Django conquers world!> tagged "world domination">] 92 93 # Load fixture 6, JSON file with dynamic Permission fields. Testing ManyToMany. 94 >>> management.call_command('loaddata', 'fixture6.json', verbosity=0) 95 >>> Visa.objects.all() 96 [<Visa: Django Reinhardt Can add user, Can change user, Can delete user>, <Visa: Stephane Grappelli Can add user>, <Visa: Prince >] 97 98 # Load fixture 7, XML file with dynamic Permission fields. Testing ManyToMany. 99 >>> management.call_command('loaddata', 'fixture7.xml', verbosity=0) 100 >>> Visa.objects.all() 101 [<Visa: Django Reinhardt Can add user, Can change user, Can delete user>, <Visa: Stephane Grappelli Can add user, Can delete user>, <Visa: Artist formerly known as "Prince" >] 102 51 103 # Load a fixture that doesn't exist 52 104 >>> management.call_command('loaddata', 'unknown.json', verbosity=0) 53 105 54 106 # object list is unaffected 55 107 >>> Article.objects.all() 56 108 [<Article: XML identified as leading cause of cancer>, <Article: Django conquers world!>, <Article: Copyright is fine the way it is>, <Article: Poker on TV is great!>, <Article: Python program becomes self aware>] 109 110 # Dump the current contents of the database as a JSON fixture 111 >>> management.call_command('dumpdata', 'fixtures', format='json') 112 [{"pk": 1, "model": "fixtures.article", "fields": {"headline": "Python program becomes self aware", "pub_date": "2006-06-16 11:00:00"}}, {"pk": 2, "model": "fixtures.article", "fields": {"headline": "Poker on TV is great!", "pub_date": "2006-06-16 11: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": 4, "model": "fixtures.article", "fields": {"headline": "Django conquers world!", "pub_date": "2006-06-16 15:00:00"}}, {"pk": 5, "model": "fixtures.article", "fields": {"headline": "XML identified as leading cause of cancer", "pub_date": "2006-06-16 16:00:00"}}, {"pk": 1, "model": "fixtures.tag", "fields": {"tagged_type": {"model": "article", "app_label": "fixtures"}, "name": "copyright", "tagged_id": 3}}, {"pk": 2, "model": "fixtures.tag", "fields": {"tagged_type": {"model": "article", "app_label": "fixtures"}, "name": "legal", "tagged_id": 3}}, {"pk": 3, "model": "fixtures.tag", "fields": {"tagged_type": {"model": "article", "app_label": "fixtures"}, "name": "django", "tagged_id": 4}}, {"pk": 4, "model": "fixtures.tag", "fields": {"tagged_type": {"model": "article", "app_label": "fixtures"}, "name": "world domination", "tagged_id": 4}}, {"pk": 1, "model": "fixtures.visa", "fields": {"name": "Django Reinhardt", "permissions": [{"codename": "add_user", "content_type": {"model": "user", "app_label": "auth"}}, {"codename": "change_user", "content_type": {"model": "user", "app_label": "auth"}}, {"codename": "delete_user", "content_type": {"model": "user", "app_label": "auth"}}]}}, {"pk": 2, "model": "fixtures.visa", "fields": {"name": "Stephane Grappelli", "permissions": [{"codename": "add_user", "content_type": {"model": "user", "app_label": "auth"}}, {"codename": "delete_user", "content_type": {"model": "user", "app_label": "auth"}}]}}, {"pk": 3, "model": "fixtures.visa", "fields": {"name": "Artist formerly known as \\\"Prince\\\"", "permissions": []}}] 113 114 # Dump the current contents of the database as an XML fixture 115 >>> management.call_command('dumpdata', 'fixtures', format='xml') 116 <?xml version="1.0" encoding="utf-8"?> 117 <django-objects version="1.0"><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="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="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="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="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="1" model="fixtures.tag"><field type="CharField" name="name">copyright</field><field to="contenttypes.contenttype" name="tagged_type" rel="ManyToOneRel"><lookup name="model">article</lookup><lookup name="app_label">fixtures</lookup></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"><lookup name="model">article</lookup><lookup name="app_label">fixtures</lookup></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"><lookup name="model">article</lookup><lookup name="app_label">fixtures</lookup></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"><lookup name="model">article</lookup><lookup name="app_label">fixtures</lookup></field><field type="PositiveIntegerField" name="tagged_id">4</field></object><object pk="1" model="fixtures.visa"><field type="CharField" name="name">Django Reinhardt</field><field to="auth.permission" name="permissions" rel="ManyToManyRel"><object><lookup name="codename">add_user</lookup><lookup name="content_type">user</lookup></object><object><lookup name="codename">change_user</lookup><lookup name="content_type">user</lookup></object><object><lookup name="codename">delete_user</lookup><lookup name="content_type">user</lookup></object></field></object><object pk="2" model="fixtures.visa"><field type="CharField" name="name">Stephane Grappelli</field><field to="auth.permission" name="permissions" rel="ManyToManyRel"><object><lookup name="codename">add_user</lookup><lookup name="content_type">user</lookup></object><object><lookup name="codename">delete_user</lookup><lookup name="content_type">user</lookup></object></field></object><object pk="3" model="fixtures.visa"><field type="CharField" name="name">Artist formerly known as "Prince"</field><field to="auth.permission" name="permissions" rel="ManyToManyRel"></field></object></django-objects> 57 118 """} 58 119 59 120 # Database flushing does not work on MySQL with the default storage engine … … Multiple fixtures named 'fixture2' in '. 79 140 >>> Article.objects.all() 80 141 [<Article: Time to reform copyright>, <Article: Poker has no place on ESPN>, <Article: Python program becomes self aware>] 81 142 143 # Try to load fixture 4 using format discovery 144 >>> management.call_command('loaddata', 'fixture4', verbosity=0) 145 >>> Tag.objects.all() 146 [<Tag: <Article: Time to reform copyright> tagged "copyright">, <Tag: <Article: Time to reform copyright> tagged "law">] 147 82 148 # Dump the current contents of the database as a JSON fixture 83 149 >>> management.call_command('dumpdata', 'fixtures', format='json') 84 [{"pk": 1, "model": "fixtures.article", "fields": {"headline": "Python program becomes self aware", "pub_date": "2006-06-16 11:00:00"}}, {"pk": 2, "model": "fixtures.article", "fields": {"headline": "Poker has no place on ESPN", "pub_date": "2006-06-16 12:00:00"}}, {"pk": 3, "model": "fixtures.article", "fields": {"headline": "Time to reform copyright", "pub_date": "2006-06-16 13:00:00"}}] 150 [{"pk": 1, "model": "fixtures.article", "fields": {"headline": "Python program becomes self aware", "pub_date": "2006-06-16 11:00:00"}}, {"pk": 2, "model": "fixtures.article", "fields": {"headline": "Poker has no place on ESPN", "pub_date": "2006-06-16 12:00:00"}}, {"pk": 3, "model": "fixtures.article", "fields": {"headline": "Time to reform copyright", "pub_date": "2006-06-16 13:00:00"}}, {"pk": 1, "model": "fixtures.tag", "fields": {"tagged_type": {"model": "article", "app_label": "fixtures"}, "name": "copyright", "tagged_id": 3}}, {"pk": 2, "model": "fixtures.tag", "fields": {"tagged_type": {"model": "article", "app_label": "fixtures"}, "name": "law", "tagged_id": 3}}] 151 152 # Dump the current contents of the database as an XML fixture 153 >>> management.call_command('dumpdata', 'fixtures', format='xml') 154 <?xml version="1.0" encoding="utf-8"?> 155 <django-objects version="1.0"><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="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="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="1" model="fixtures.tag"><field type="CharField" name="name">copyright</field><field to="contenttypes.contenttype" name="tagged_type" rel="ManyToOneRel"><lookup name="model">article</lookup><lookup name="app_label">fixtures</lookup></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"><lookup name="model">article</lookup><lookup name="app_label">fixtures</lookup></field><field type="PositiveIntegerField" name="tagged_id">3</field></object></django-objects> 85 156 """ 86 157 87 158 from django.test import TestCase