Ticket #7052: t7052-rc1.diff
File t7052-rc1.diff, 55.9 KB (added by , 15 years ago) |
---|
-
django/contrib/auth/models.py
diff -r e0fb67da6521 django/contrib/auth/models.py
a b 47 47 class SiteProfileNotAvailable(Exception): 48 48 pass 49 49 50 class PermissionManager(models.Manager): 51 def get_by_natural_key(self, codename, app_label, model): 52 return self.get( 53 codename=codename, 54 content_type=ContentType.objects.get_by_natural_key(app_label, model) 55 ) 56 50 57 class Permission(models.Model): 51 58 """The permissions system provides a way to assign permissions to specific users and groups of users. 52 59 … … 63 70 name = models.CharField(_('name'), max_length=50) 64 71 content_type = models.ForeignKey(ContentType) 65 72 codename = models.CharField(_('codename'), max_length=100) 73 objects = PermissionManager() 66 74 67 75 class Meta: 68 76 verbose_name = _('permission') … … 76 84 unicode(self.content_type), 77 85 unicode(self.name)) 78 86 87 def natural_key(self): 88 return (self.codename,) + self.content_type.natural_key() 89 natural_key.dependencies = ['contenttypes.contenttype'] 90 79 91 class Group(models.Model): 80 92 """Groups are a generic way of categorizing users to apply permissions, or some other label, to those users. A user can belong to any number of groups. 81 93 -
django/contrib/contenttypes/models.py
diff -r e0fb67da6521 django/contrib/contenttypes/models.py
a b 8 8 # This cache is shared by all the get_for_* methods. 9 9 _cache = {} 10 10 11 def get_by_natural_key(self, app_label, model): 12 try: 13 ct = self.__class__._cache[(app_label, model)] 14 except KeyError: 15 ct = self.get(app_label=app_label, model=model) 16 return ct 17 11 18 def get_for_model(self, model): 12 19 """ 13 20 Returns the ContentType object for a given model, creating the … … 93 100 so code that calls this method should catch it. 94 101 """ 95 102 return self.model_class()._default_manager.get(**kwargs) 103 104 def natural_key(self): 105 return (self.app_label, self.model) -
django/core/management/commands/dumpdata.py
diff -r e0fb67da6521 django/core/management/commands/dumpdata.py
a b 67 67 except KeyError: 68 68 raise CommandError("Unknown serialization format: %s" % format) 69 69 70 # Now collate the objects to be serialized. 70 71 objects = [] 71 for app, model_list in app_list.items(): 72 if model_list is None: 73 model_list = get_models(app) 74 75 for model in model_list: 76 if not model._meta.proxy: 77 objects.extend(model._default_manager.all()) 72 for model in sort_dependencies(app_list.items()): 73 if not model._meta.proxy: 74 objects.extend(model._default_manager.all()) 78 75 79 76 try: 80 77 return serializers.serialize(format, objects, indent=indent) … … 82 79 if show_traceback: 83 80 raise 84 81 raise CommandError("Unable to serialize database: %s" % e) 82 83 def sort_dependencies(app_list): 84 """Sort a list of app,modellist pairs into a single list of models. 85 86 The single list of models is sorted so that any model with a natural key 87 is serialized before a normal model, and any model with a natural key 88 dependency has it's dependencies serialized first. 89 """ 90 from django.db.models import get_model, get_models 91 # Process the list of models, and get the list of dependencies 92 model_dependencies = [] 93 models = set() 94 for app, model_list in app_list: 95 if model_list is None: 96 model_list = get_models(app) 97 98 for model in model_list: 99 models.add(model) 100 # Add any explicitly defined dependencies 101 if hasattr(model, 'natural_key'): 102 deps = getattr(model.natural_key, 'dependencies', []) 103 if deps: 104 deps = [get_model(*d.split('.')) for d in deps] 105 else: 106 deps = [] 107 108 # Now add a dependency for any FK or M2M relation with 109 # a model that defines a natural key 110 for field in model._meta.fields: 111 if hasattr(field.rel, 'to'): 112 rel_model = field.rel.to 113 if hasattr(rel_model, 'natural_key'): 114 deps.append(rel_model) 115 for field in model._meta.many_to_many: 116 rel_model = field.rel.to 117 if hasattr(rel_model, 'natural_key'): 118 deps.append(rel_model) 119 model_dependencies.append((model, deps)) 120 121 model_dependencies.reverse() 122 # Now sort the models to ensure that dependencies are met. This 123 # is done by repeatedly iterating over the input list of models. 124 # If all the dependencies of a given model are in the final list, 125 # that model is promoted to the end of the final list. This process 126 # continues until the input list is empty, or we do a full iteration 127 # over the input models without promoting a model to the final list. 128 # If we do a full iteration without a promotion, that means there are 129 # circular dependencies in the list. 130 model_list = [] 131 while model_dependencies: 132 skipped = [] 133 changed = False 134 while model_dependencies: 135 model, deps = model_dependencies.pop() 136 if all((d not in models or d in model_list) for d in deps): 137 # If all of the models in the dependency list are either already 138 # on the final model list, or not on the original serialization list, 139 # then we've found another model with all it's dependencies satisfied. 140 model_list.append(model) 141 changed = True 142 else: 143 skipped.append((model, deps)) 144 if not changed: 145 raise CommandError("Can't resolve dependencies for %s in serialized app list." % 146 ', '.join('%s.%s' % (model._meta.app_label, model._meta.object_name) 147 for model, deps in sorted(skipped, key=lambda obj: obj[0].__name__)) 148 ) 149 model_dependencies = skipped 150 151 return model_list -
django/core/serializers/python.py
diff -r e0fb67da6521 django/core/serializers/python.py
a b 47 47 def handle_fk_field(self, obj, field): 48 48 related = getattr(obj, field.name) 49 49 if related is not None: 50 if field.rel.field_name == related._meta.pk.name: 51 # Related to remote object via primary key 52 related = related._get_pk_val() 50 if hasattr(related, 'natural_key'): 51 related = related.natural_key() 53 52 else: 54 # Related to remote object via other field 55 related = getattr(related, field.rel.field_name) 56 self._current[field.name] = smart_unicode(related, strings_only=True) 53 if field.rel.field_name == related._meta.pk.name: 54 # Related to remote object via primary key 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 61 def handle_m2m_field(self, obj, field): 59 62 if field.rel.through._meta.auto_created: 60 self._current[field.name] = [smart_unicode(related._get_pk_val(), strings_only=True) 63 if 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 68 for related in getattr(obj, field.name).iterator()] 62 69 63 70 def getvalue(self): … … 86 93 87 94 # Handle M2M relations 88 95 if field.rel and isinstance(field.rel, models.ManyToManyRel): 89 m2m_convert = field.rel.to._meta.pk.to_python 90 m2m_data[field.name] = [m2m_convert(smart_unicode(pk)) for pk in field_value] 96 if hasattr(field.rel.to._default_manager, 'get_by_natural_key'): 97 def m2m_convert(value): 98 if hasattr(value, '__iter__'): 99 return field.rel.to._default_manager.get_by_natural_key(*value).pk 100 else: 101 return smart_unicode(field.rel.to._meta.pk.to_python(value)) 102 else: 103 m2m_convert = lambda v: smart_unicode(field.rel.to._meta.pk.to_python(v)) 104 m2m_data[field.name] = [m2m_convert(pk) for pk in field_value] 91 105 92 106 # Handle FK fields 93 107 elif field.rel and isinstance(field.rel, models.ManyToOneRel): 94 108 if field_value is not None: 95 data[field.attname] = field.rel.to._meta.get_field(field.rel.field_name).to_python(field_value) 109 if hasattr(field.rel.to._default_manager, 'get_by_natural_key'): 110 if hasattr(field_value, '__iter__'): 111 obj = field.rel.to._default_manager.get_by_natural_key(*field_value) 112 value = getattr(obj, field.rel.field_name) 113 else: 114 value = field.rel.to._meta.get_field(field.rel.field_name).to_python(field_value) 115 data[field.attname] = value 116 else: 117 data[field.attname] = field.rel.to._meta.get_field(field.rel.field_name).to_python(field_value) 96 118 else: 97 119 data[field.attname] = None 98 120 -
django/core/serializers/xml_serializer.py
diff -r e0fb67da6521 django/core/serializers/xml_serializer.py
a b 81 81 self._start_relational_field(field) 82 82 related = getattr(obj, field.name) 83 83 if related is not None: 84 if field.rel.field_name == related._meta.pk.name: 85 # Related to remote object via primary key 86 related = related._get_pk_val() 84 if hasattr(related, 'natural_key'): 85 # If related object has a natural key, use it 86 related = related.natural_key() 87 # Iterable natural keys are rolled out as subelements 88 for key_value in related: 89 self.xml.startElement("natural", {}) 90 self.xml.characters(smart_unicode(key_value)) 91 self.xml.endElement("natural") 87 92 else: 88 # Related to remote object via other field 89 related = getattr(related, field.rel.field_name) 90 self.xml.characters(smart_unicode(related)) 93 if field.rel.field_name == related._meta.pk.name: 94 # Related to remote object via primary key 95 related = related._get_pk_val() 96 else: 97 # Related to remote object via other field 98 related = getattr(related, field.rel.field_name) 99 self.xml.characters(smart_unicode(related)) 91 100 else: 92 101 self.xml.addQuickElement("None") 93 102 self.xml.endElement("field") … … 100 109 """ 101 110 if field.rel.through._meta.auto_created: 102 111 self._start_relational_field(field) 112 if hasattr(field.rel.to, 'natural_key'): 113 # If the objects in the m2m have a natural key, use it 114 def handle_m2m(value): 115 natural = value.natural_key() 116 # Iterable natural keys are rolled out as subelements 117 self.xml.startElement("object", {}) 118 for key_value in natural: 119 self.xml.startElement("natural", {}) 120 self.xml.characters(smart_unicode(key_value)) 121 self.xml.endElement("natural") 122 self.xml.endElement("object") 123 else: 124 def handle_m2m(value): 125 self.xml.addQuickElement("object", attrs={ 126 'pk' : smart_unicode(value._get_pk_val()) 127 }) 103 128 for relobj in getattr(obj, field.name).iterator(): 104 self.xml.addQuickElement("object", attrs={"pk" : smart_unicode(relobj._get_pk_val())}) 129 handle_m2m(relobj) 130 105 131 self.xml.endElement("field") 106 132 107 133 def _start_relational_field(self, field): … … 187 213 if node.getElementsByTagName('None'): 188 214 return None 189 215 else: 190 return field.rel.to._meta.get_field(field.rel.field_name).to_python( 191 getInnerText(node).strip()) 216 if hasattr(field.rel.to._default_manager, 'get_by_natural_key'): 217 keys = node.getElementsByTagName('natural') 218 if keys: 219 # If there are 'key' subelements, it must be an iterable natural key 220 field_value = [getInnerText(k).strip() for k in keys] 221 obj = field.rel.to._default_manager.get_by_natural_key(*field_value) 222 obj_pk = getattr(obj, field.rel.field_name) 223 else: 224 # Otherwise, treat like a normal PK 225 field_value = getInnerText(node).strip() 226 obj_pk = field.rel.to._meta.get_field(field.rel.field_name).to_python(field_value) 227 return obj_pk 228 else: 229 field_value = getInnerText(node).strip() 230 return field.rel.to._meta.get_field(field.rel.field_name).to_python(field_value) 192 231 193 232 def _handle_m2m_field_node(self, node, field): 194 233 """ 195 234 Handle a <field> node for a ManyToManyField. 196 235 """ 197 return [field.rel.to._meta.pk.to_python( 198 c.getAttribute("pk")) 199 for c in node.getElementsByTagName("object")] 236 if hasattr(field.rel.to._default_manager, 'get_by_natural_key'): 237 def m2m_convert(n): 238 keys = n.getElementsByTagName('natural') 239 if keys: 240 # If there are 'natural' subelements, it must be a natural key 241 field_value = [getInnerText(k).strip() for k in keys] 242 obj_pk = field.rel.to._default_manager.get_by_natural_key(*field_value).pk 243 else: 244 # Otherwise, treat like a normal PK value. 245 obj_pk = field.rel.to._meta.pk.to_python(n.getAttribute('pk')) 246 return obj_pk 247 else: 248 m2m_convert = lambda n: field.rel.to._meta.pk.to_python(n.getAttribute('pk')) 249 return [m2m_convert(c) for c in node.getElementsByTagName("object")] 200 250 201 251 def _get_model_from_node(self, node, attr): 202 252 """ -
docs/releases/1.2.txt
diff -r e0fb67da6521 docs/releases/1.2.txt
a b 130 130 :meth:`~django.core.mail.get_connection()` call:: 131 131 132 132 connection = get_connection('django.core.mail.backends.smtp', hostname='localhost', port=1234) 133 133 134 134 User Messages API 135 135 ----------------- 136 136 137 The API for storing messages in the user ``Message`` model (via 137 The API for storing messages in the user ``Message`` model (via 138 138 ``user.message_set.create``) is now deprecated and will be removed in Django 139 139 1.4 according to the standard :ref:`release process <internals-release-process>`. 140 140 … … 147 147 from django.contrib import messages 148 148 messages.add_message(request, messages.INFO, 'a message') 149 149 150 Additionally, if you make use of the method, you need to replace the 150 Additionally, if you make use of the method, you need to replace the 151 151 following:: 152 152 153 153 for message in user.get_and_delete_messages(): 154 154 ... 155 155 156 156 with:: 157 157 158 158 from django.contrib import messages 159 159 for message in messages.get_messages(request): 160 160 ... 161 162 For more information, see the full 163 :ref:`messages documentation <ref-contrib-messages>`. You should begin to 161 162 For more information, see the full 163 :ref:`messages documentation <ref-contrib-messages>`. You should begin to 164 164 update your code to use the new API immediately. 165 165 166 166 What's new in Django 1.2 … … 239 239 class="highlight" 240 240 {% endif %} 241 241 >{{ message }}</div> 242 243 Natural keys in fixtures 244 ------------------------ 245 246 Fixtures can refer to remote objects using :ref:`natural keys`. This 247 lookup scheme is an alternative to the normal primary-key based object 248 references in a fixture, improving readability, and resolving problems 249 referring to objects whose primary key value may not be predictable or 250 known. 251 -
docs/topics/serialization.txt
diff -r e0fb67da6521 docs/topics/serialization.txt
a b 154 154 .. _PyYAML: http://www.pyyaml.org/ 155 155 156 156 Notes for specific serialization formats 157 ---------------------------------------- 157 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 158 158 159 159 json 160 ~~~~ 160 ^^^^ 161 161 162 162 If you're using UTF-8 (or any other non-ASCII encoding) data with the JSON 163 163 serializer, you must pass ``ensure_ascii=False`` as a parameter to the … … 191 191 192 192 .. _special encoder: http://svn.red-bean.com/bob/simplejson/tags/simplejson-1.7/docs/index.html 193 193 194 Natural keys 195 ------------ 196 197 The default serialization strategy for foreign keys and many-to-many 198 relations is to serialize the value of the primary key(s) of the 199 objects in the relation. This strategy works well for most types of 200 object, but it can cause difficulty in some circumstances. 201 202 Consider the case of a list of objects that have foreign key on 203 :model:`ContentType`. If you're going to serialize an object that 204 refers to a content type, you need to have a way to refer to that 205 content type. Content Types are automatically created by Django as 206 part of the database synchronization process, so you don't need to 207 include content types in a fixture or other serialized data. As a 208 result, the primary key of any given content type isn't easy to 209 predict - it will depend on how and when :djadmin:`syncdb` was 210 executed to create the content types. 211 212 There is also the matter of convenience. An integer id isn't always 213 the most convenient way to refer to an object; sometimes, a 214 more natural reference would be helpful. 215 216 Deserialization of natural keys 217 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 218 219 It is for these reasons that Django provides `natural keys`. A natural 220 key is a tuple of values that can be used to uniquely identify an 221 object instance without using the primary key value itself. 222 223 Consider the following two models:: 224 225 from django.db import models 226 227 class Person(models.Model): 228 first_name = models.CharField(max_length=100) 229 last_name = models.CharField(max_length=100) 230 231 birthdate = models.DateField() 232 233 class Book(models.Model): 234 name = models.CharField(max_length=100) 235 author = models.ForeignKey(Person) 236 237 Ordinarily, serialized data for ``Book`` would use an integer to refer to 238 the author. For example, in JSON, a Book might be serialized as:: 239 240 ... 241 { 242 "pk": 1, 243 "model": "store.book", 244 "fields": { 245 "name": "Mostly Harmless", 246 "author": 42 247 } 248 } 249 ... 250 251 This isn't a particularly natural way to refer to an author. It 252 requires that you know the primary key value for the author; it also 253 requires that this primary key value is stable and predictable. 254 255 However, if we add natural key handling to Person, the fixture becomes 256 much more humane. To add natural key handling, you define a default 257 Manager for Person with a ``get_by_natural_key()`` method. In the case 258 of a Person, a good natural key might be the pair of first and last 259 name:: 260 261 from django.db import models 262 263 class PersonManager(models.Manager): 264 def get_by_natural_key(self, first_name, last_name): 265 return self.filter(first_name=first_name, last_name=last_name) 266 267 class Person(models.Model): 268 objects = PersonManager() 269 270 first_name = models.CharField(max_length=100) 271 last_name = models.CharField(max_length=100) 272 273 birthdate = models.DateField() 274 275 Now Books can use that natural key to refer to Person objects:: 276 277 ... 278 { 279 "pk": 1, 280 "model": "store.book", 281 "fields": { 282 "name": "Mostly Harmless", 283 "author": ["Douglas", "Adams"] 284 } 285 } 286 ... 287 288 When you try to load this serialized data, Django will use the 289 ``get_by_natural_key()`` method to resolve ``["Douglas", "Adams"]`` 290 into a primary key of an actual ``Person`` object. 291 292 Serialization of natural keys 293 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 294 295 So how do you get Django to emit a natural key when serializing an object? 296 You add another method -- this time to the model itself:: 297 298 class Person(models.Model): 299 objects = PersonManager() 300 301 first_name = models.CharField(max_length=100) 302 last_name = models.CharField(max_length=100) 303 304 birthdate = models.DateField() 305 306 def natural_key(self): 307 return (self.first_name, self.last_name) 308 309 When a model has a ``natural_key`` method, Django will use that method 310 to serialize any reference to objects of that type. 311 312 .. note:: 313 314 You don't need to define both ``natural_key()`` and 315 ``get_by_natural_key()``. If you don't want Django to output 316 natural keys during serialization, but you want to retain the 317 ability to load natural keys, then you can opt to not implement 318 the ``natural_key()`` method. 319 320 Conversely, if (for some strange reason) you want Django to output 321 natural keys during serialization, but *not* be able to load those 322 key values, just don't define the ``get_by_natural_key()`` method. 323 324 Dependencies during serialization 325 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 326 327 Since natural keys rely on database lookups to resolve references, it 328 is important that data exists before it is referenced. You can't make 329 a `forward reference` with natural keys - the data you are referencing 330 must exist before you include a natural key reference to that data. 331 332 To accommodate this limitation, calls to :djadmin:`dumpdata` will 333 serialize any model with a ``natural_key()`` method before it serializes 334 normal key objects. 335 336 However, this may not always be enough. If your natural key refers to 337 another object (by using a foreign key or natural key to another object 338 as part of a natural key), then you need to be able to ensure that 339 the objects on which a natural key depends occur in the serialized data 340 before the natural key requires them. 341 342 To control this ordering, you can define dependencies on your 343 ``natural_key()`` methods. You do this by setting a ``dependencies`` 344 attribute on the ``natural_key()`` method itself. 345 346 For example, consider the ``Permission`` model in ``contrib.auth``. 347 The following is a simplified version of the ``Permission`` model:: 348 349 class Permission(models.Model): 350 name = models.CharField(max_length=50) 351 content_type = models.ForeignKey(ContentType) 352 codename = models.CharField(max_length=100) 353 # ... 354 def natural_key(self): 355 return (self.codename,) + self.content_type.natural_key() 356 357 The natural key for a ``Permission`` is a combination of the codename for the 358 ``Permission``, and the ``ContentType`` to which the ``Permission`` applies. This means 359 that ``ContentType``s must be serialized before ``Permission``s. To define this 360 dependency, we add one extra line:: 361 362 class Permission(models.Model): 363 # ... 364 def natural_key(self): 365 return (self.codename,) + self.content_type.natural_key() 366 natural_key.dependencies = ['contenttypes.contenttype'] 367 368 This definition ensures that ``ContentType`` models are serialized before 369 ``Permission`` models. In turn, any object referencing ``Permission`` will 370 be serialized after both ``ContentType`` and ``Permission``. -
new file tests/modeltests/fixtures/fixtures/fixture6.json
diff -r e0fb67da6521 tests/modeltests/fixtures/fixtures/fixture6.json
- + 1 [ 2 { 3 "pk": "1", 4 "model": "fixtures.tag", 5 "fields": { 6 "name": "copyright", 7 "tagged_type": ["fixtures", "article"], 8 "tagged_id": "3" 9 } 10 }, 11 { 12 "pk": "2", 13 "model": "fixtures.tag", 14 "fields": { 15 "name": "law", 16 "tagged_type": ["fixtures", "article"], 17 "tagged_id": "3" 18 } 19 }, 20 { 21 "pk": "1", 22 "model": "fixtures.person", 23 "fields": { 24 "name": "Django Reinhardt" 25 } 26 }, 27 { 28 "pk": "2", 29 "model": "fixtures.person", 30 "fields": { 31 "name": "Stephane Grappelli" 32 } 33 }, 34 { 35 "pk": "3", 36 "model": "fixtures.person", 37 "fields": { 38 "name": "Prince" 39 } 40 } 41 ] -
new file tests/modeltests/fixtures/fixtures/fixture7.xml
diff -r e0fb67da6521 tests/modeltests/fixtures/fixtures/fixture7.xml
- + 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 <natural>fixtures</natural> 7 <natural>article</natural> 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 <natural>fixtures</natural> 15 <natural>article</natural> 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 <natural>fixtures</natural> 23 <natural>article</natural> 24 </field> 25 <field type="PositiveIntegerField" name="tagged_id">4</field> 26 </object> 27 </django-objects> -
new file tests/modeltests/fixtures/fixtures/fixture8.json
diff -r e0fb67da6521 tests/modeltests/fixtures/fixtures/fixture8.json
- + 1 [ 2 { 3 "pk": "1", 4 "model": "fixtures.visa", 5 "fields": { 6 "person": ["Django Reinhardt"], 7 "permissions": [ 8 ["add_user", "auth", "user"], 9 ["change_user", "auth", "user"], 10 ["delete_user", "auth", "user"] 11 ] 12 } 13 }, 14 { 15 "pk": "2", 16 "model": "fixtures.visa", 17 "fields": { 18 "person": ["Stephane Grappelli"], 19 "permissions": [ 20 ["add_user", "auth", "user"] 21 ] 22 } 23 }, 24 { 25 "pk": "3", 26 "model": "fixtures.visa", 27 "fields": { 28 "person": ["Prince"], 29 "permissions": [] 30 } 31 } 32 ] -
new file tests/modeltests/fixtures/fixtures/fixture9.xml
diff -r e0fb67da6521 tests/modeltests/fixtures/fixtures/fixture9.xml
- + 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="person"> 5 <natural>Stephane Grappelli</natural> 6 </field> 7 <field to="auth.permission" name="permissions" rel="ManyToManyRel"> 8 <object> 9 <natural>add_user</natural> 10 <natural>auth</natural> 11 <natural>user</natural> 12 </object> 13 <object> 14 <natural>delete_user</natural> 15 <natural>auth</natural> 16 <natural>user</natural> 17 </object> 18 </field> 19 </object> 20 <object pk="3" model="fixtures.person"> 21 <field type="CharField" name="name"> 22 <natural>Artist formerly known as "Prince"</natural> 23 </field> 24 </object> 25 <object pk="3" model="fixtures.visa"> 26 <field type="CharField" name="person"> 27 <natural>Artist formerly known as "Prince"</natural> 28 </field> 29 <field to="auth.permission" name="permissions" rel="ManyToManyRel"> 30 <object> 31 <natural>change_user</natural> 32 <natural>auth</natural> 33 <natural>user</natural> 34 </object> 35 </field> 36 </object> 37 <object pk="1" model="fixtures.book"> 38 <field type="CharField" name="name">Music for all ages</field> 39 <field to="fixtures.person" name="authors" rel="ManyToManyRel"> 40 <object> 41 <natural>Django Reinhardt</natural> 42 </object> 43 <object> 44 <natural>Artist formerly known as "Prince"</natural> 45 </object> 46 </field> 47 </object> 48 </django-objects> -
tests/modeltests/fixtures/models.py
diff -r e0fb67da6521 tests/modeltests/fixtures/models.py
a b 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 … … 31 34 class Meta: 32 35 ordering = ('-pub_date', 'headline') 33 36 37 class Blog(models.Model): 38 name = models.CharField(max_length=100) 39 featured = models.ForeignKey(Article, related_name='fixtures_featured_set') 40 articles = models.ManyToManyField(Article, blank=True, 41 related_name='fixtures_articles_set') 42 43 def __unicode__(self): 44 return self.name 45 46 47 class Tag(models.Model): 48 name = models.CharField(max_length=100) 49 tagged_type = models.ForeignKey(ContentType, related_name="fixtures_tag_set") 50 tagged_id = models.PositiveIntegerField(default=0) 51 tagged = generic.GenericForeignKey(ct_field='tagged_type', 52 fk_field='tagged_id') 53 54 def __unicode__(self): 55 return '<%s: %s> tagged "%s"' % (self.tagged.__class__.__name__, 56 self.tagged, self.name) 57 58 class PersonManager(models.Manager): 59 def get_by_natural_key(self, name): 60 return self.get(name=name) 61 62 class Person(models.Model): 63 objects = PersonManager() 64 name = models.CharField(max_length=100) 65 def __unicode__(self): 66 return self.name 67 68 class Meta: 69 ordering = ('name',) 70 71 def natural_key(self): 72 return (self.name,) 73 74 class Visa(models.Model): 75 person = models.ForeignKey(Person) 76 permissions = models.ManyToManyField(Permission, blank=True) 77 78 def __unicode__(self): 79 return '%s %s' % (self.person.name, 80 ', '.join(p.name for p in self.permissions.all())) 81 82 class Book(models.Model): 83 name = models.CharField(max_length=100) 84 authors = models.ManyToManyField(Person) 85 86 def __unicode__(self): 87 return '%s by %s' % (self.name, 88 ' and '.join(a.name for a in self.authors.all())) 89 90 class Meta: 91 ordering = ('name',) 92 34 93 __test__ = {'API_TESTS': """ 35 94 >>> from django.core import management 36 95 >>> from django.db.models import get_app … … 90 149 >>> Article.objects.all() 91 150 [<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>] 92 151 152 # Load fixture 6, JSON file with dynamic ContentType fields. Testing ManyToOne. 153 >>> management.call_command('loaddata', 'fixture6.json', verbosity=0) 154 >>> Tag.objects.all() 155 [<Tag: <Article: Copyright is fine the way it is> tagged "copyright">, <Tag: <Article: Copyright is fine the way it is> tagged "law">] 156 157 # Load fixture 7, XML file with dynamic ContentType fields. Testing ManyToOne. 158 >>> management.call_command('loaddata', 'fixture7.xml', verbosity=0) 159 >>> Tag.objects.all() 160 [<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">] 161 162 # Load fixture 8, JSON file with dynamic Permission fields. Testing ManyToMany. 163 >>> management.call_command('loaddata', 'fixture8.json', verbosity=0) 164 >>> Visa.objects.all() 165 [<Visa: Django Reinhardt Can add user, Can change user, Can delete user>, <Visa: Stephane Grappelli Can add user>, <Visa: Prince >] 166 167 # Load fixture 9, XML file with dynamic Permission fields. Testing ManyToMany. 168 >>> management.call_command('loaddata', 'fixture9.xml', verbosity=0) 169 >>> Visa.objects.all() 170 [<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" Can change user>] 171 172 >>> Book.objects.all() 173 [<Book: Music for all ages by Artist formerly known as "Prince" and Django Reinhardt>] 174 93 175 # Load a fixture that doesn't exist 94 176 >>> management.call_command('loaddata', 'unknown.json', verbosity=0) 95 177 96 178 # object list is unaffected 97 179 >>> Article.objects.all() 98 180 [<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>] 181 182 # Dump the current contents of the database as a JSON fixture 183 >>> management.call_command('dumpdata', 'fixtures', format='json') 184 [{"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"]]}}] 185 186 # Dump the current contents of the database as an XML fixture 187 >>> management.call_command('dumpdata', 'fixtures', format='xml') 188 <?xml version="1.0" encoding="utf-8"?> 189 <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> 190 99 191 """} 100 192 101 193 # Database flushing does not work on MySQL with the default storage engine … … 159 251 >>> management.call_command('loaddata', 'fixture5', verbosity=0) # doctest: +ELLIPSIS 160 252 Multiple fixtures named 'fixture5' in '...fixtures'. Aborting. 161 253 254 >>> management.call_command('flush', verbosity=0, interactive=False) 255 256 # Load back in fixture 1, we need the articles from it 257 >>> management.call_command('loaddata', 'fixture1', verbosity=0) 258 259 # Try to load fixture 6 using format discovery 260 >>> management.call_command('loaddata', 'fixture6', verbosity=0) 261 >>> Tag.objects.all() 262 [<Tag: <Article: Time to reform copyright> tagged "copyright">, <Tag: <Article: Time to reform copyright> tagged "law">] 263 264 # Dump the current contents of the database as a JSON fixture 265 >>> management.call_command('dumpdata', 'fixtures', format='json') 266 [{"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"}}] 267 268 # Dump the current contents of the database as an XML fixture 269 >>> management.call_command('dumpdata', 'fixtures', format='xml') 270 <?xml version="1.0" encoding="utf-8"?> 271 <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> 272 162 273 """ 163 274 164 275 from django.test import TestCase -
new file tests/regressiontests/fixtures_regress/fixtures/forward_ref_lookup.json
diff -r e0fb67da6521 tests/regressiontests/fixtures_regress/fixtures/forward_ref_lookup.json
- + 1 [ 2 { 3 "pk": "4", 4 "model": "fixtures_regress.person", 5 "fields": { 6 "name": "Neal Stephenson" 7 } 8 }, 9 { 10 "pk": "2", 11 "model": "fixtures_regress.store", 12 "fields": { 13 "name": "Amazon" 14 } 15 }, 16 { 17 "pk": "3", 18 "model": "fixtures_regress.store", 19 "fields": { 20 "name": "Borders" 21 } 22 }, 23 { 24 "pk": 1, 25 "model": "fixtures_regress.book", 26 "fields": { 27 "name": "Cryptonomicon", 28 "author": ["Neal Stephenson"], 29 "stores": [["Amazon"], ["Borders"]] 30 } 31 } 32 ] 33 No newline at end of file -
new file tests/regressiontests/fixtures_regress/fixtures/non_natural_1.json
diff -r e0fb67da6521 tests/regressiontests/fixtures_regress/fixtures/non_natural_1.json
- + 1 [ 2 { 3 "pk": 12, 4 "model": "fixtures_regress.person", 5 "fields": { 6 "name": "Greg Egan" 7 } 8 }, 9 { 10 "pk": 11, 11 "model": "fixtures_regress.store", 12 "fields": { 13 "name": "Angus and Robertson" 14 } 15 }, 16 { 17 "pk": 10, 18 "model": "fixtures_regress.book", 19 "fields": { 20 "name": "Permutation City", 21 "author": 12, 22 "stores": [11] 23 } 24 } 25 ] 26 No newline at end of file -
new file tests/regressiontests/fixtures_regress/fixtures/non_natural_2.xml
diff -r e0fb67da6521 tests/regressiontests/fixtures_regress/fixtures/non_natural_2.xml
- + 1 <?xml version="1.0" encoding="utf-8"?> 2 <django-objects version="1.0"> 3 <object pk="22" model="fixtures_regress.person"> 4 <field type="CharField" name="name">Orson Scott Card</field> 5 </object> 6 <object pk="21" model="fixtures_regress.store"> 7 <field type="CharField" name="name">Collins Bookstore</field> 8 </object> 9 <object pk="20" model="fixtures_regress.book"> 10 <field type="CharField" name="name">Ender's Game</field> 11 <field to="fixtures_regress.person" name="author" rel="ManyToOneRel">22</field> 12 <field to="fixtures_regress.store" name="stores" rel="ManyToManyRel"> 13 <object pk="21"/> 14 </field> 15 </object> 16 </django-objects> 17 No newline at end of file -
tests/regressiontests/fixtures_regress/models.py
diff -r e0fb67da6521 tests/regressiontests/fixtures_regress/models.py
a b 13 13 specimens = models.Manager() 14 14 15 15 def __unicode__(self): 16 return self. common_name16 return self.name 17 17 18 18 def animal_pre_save_check(signal, sender, instance, **kwargs): 19 19 "A signal that is used to check the type of data loaded from fixtures" … … 69 69 class Widget(models.Model): 70 70 name = models.CharField(max_length=255) 71 71 72 class Meta: 73 ordering = ('name',) 74 75 def __unicode__(self): 76 return self.name 77 72 78 class WidgetProxy(Widget): 73 79 class Meta: 74 80 proxy = True 75 81 82 # Check for forward references in FKs and M2Ms with natural keys 83 84 class TestManager(models.Manager): 85 def get_by_natural_key(self, key): 86 return self.get(name=key) 87 88 class Store(models.Model): 89 objects = TestManager() 90 name = models.CharField(max_length=255) 91 92 class Meta: 93 ordering = ('name',) 94 95 def __unicode__(self): 96 return self.name 97 98 def natural_key(self): 99 return (self.name,) 100 101 class Person(models.Model): 102 objects = TestManager() 103 name = models.CharField(max_length=255) 104 105 class Meta: 106 ordering = ('name',) 107 108 def __unicode__(self): 109 return self.name 110 111 # Person doesn't actually have a dependency on store, but we need to define 112 # one to test the behaviour of the dependency resolution algorithm. 113 def natural_key(self): 114 return (self.name,) 115 natural_key.dependencies = ['fixtures_regress.store'] 116 117 class Book(models.Model): 118 name = models.CharField(max_length=255) 119 author = models.ForeignKey(Person) 120 stores = models.ManyToManyField(Store) 121 122 class Meta: 123 ordering = ('name',) 124 125 def __unicode__(self): 126 return u'%s by %s (available at %s)' % ( 127 self.name, 128 self.author.name, 129 ', '.join(s.name for s in self.stores.all()) 130 ) 131 76 132 __test__ = {'API_TESTS':""" 77 133 >>> from django.core import management 78 134 … … 192 248 >>> management.call_command('dumpdata', 'fixtures_regress', format='json') 193 249 [{"pk": 1, "model": "fixtures_regress.widget", "fields": {"name": "grommet"}}] 194 250 251 ############################################### 252 # Check that natural key requirements are taken into account 253 # when serializing models 254 >>> management.call_command('loaddata', 'forward_ref_lookup.json', verbosity=0) 255 256 >>> management.call_command('dumpdata', 'fixtures_regress.book', 'fixtures_regress.person', 'fixtures_regress.store', verbosity=0) 257 [{"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"]}}] 258 259 # Now lets check the dependency sorting explicitly 260 261 # First Some models with pathological circular dependencies 262 >>> class Circle1(models.Model): 263 ... name = models.CharField(max_length=255) 264 ... def natural_key(self): 265 ... return self.name 266 ... natural_key.dependencies = ['fixtures_regress.circle2'] 267 268 >>> class Circle2(models.Model): 269 ... name = models.CharField(max_length=255) 270 ... def natural_key(self): 271 ... return self.name 272 ... natural_key.dependencies = ['fixtures_regress.circle1'] 273 274 >>> class Circle3(models.Model): 275 ... name = models.CharField(max_length=255) 276 ... def natural_key(self): 277 ... return self.name 278 ... natural_key.dependencies = ['fixtures_regress.circle3'] 279 280 >>> class Circle4(models.Model): 281 ... name = models.CharField(max_length=255) 282 ... def natural_key(self): 283 ... return self.name 284 ... natural_key.dependencies = ['fixtures_regress.circle5'] 285 286 >>> class Circle5(models.Model): 287 ... name = models.CharField(max_length=255) 288 ... def natural_key(self): 289 ... return self.name 290 ... natural_key.dependencies = ['fixtures_regress.circle6'] 291 292 >>> class Circle6(models.Model): 293 ... name = models.CharField(max_length=255) 294 ... def natural_key(self): 295 ... return self.name 296 ... natural_key.dependencies = ['fixtures_regress.circle4'] 297 298 >>> class ExternalDependency(models.Model): 299 ... name = models.CharField(max_length=255) 300 ... def natural_key(self): 301 ... return self.name 302 ... natural_key.dependencies = ['fixtures_regress.book'] 303 304 # It doesn't matter what order you mention the models 305 # Store *must* be serialized before then Person, and both 306 # must be serialized before Book. 307 >>> from django.core.management.commands.dumpdata import sort_dependencies 308 >>> sort_dependencies([('fixtures_regress', [Book, Person, Store])]) 309 [<class 'regressiontests.fixtures_regress.models.Store'>, <class 'regressiontests.fixtures_regress.models.Person'>, <class 'regressiontests.fixtures_regress.models.Book'>] 310 311 >>> sort_dependencies([('fixtures_regress', [Book, Store, Person])]) 312 [<class 'regressiontests.fixtures_regress.models.Store'>, <class 'regressiontests.fixtures_regress.models.Person'>, <class 'regressiontests.fixtures_regress.models.Book'>] 313 314 >>> sort_dependencies([('fixtures_regress', [Store, Book, Person])]) 315 [<class 'regressiontests.fixtures_regress.models.Store'>, <class 'regressiontests.fixtures_regress.models.Person'>, <class 'regressiontests.fixtures_regress.models.Book'>] 316 317 >>> sort_dependencies([('fixtures_regress', [Store, Person, Book])]) 318 [<class 'regressiontests.fixtures_regress.models.Store'>, <class 'regressiontests.fixtures_regress.models.Person'>, <class 'regressiontests.fixtures_regress.models.Book'>] 319 320 >>> sort_dependencies([('fixtures_regress', [Person, Book, Store])]) 321 [<class 'regressiontests.fixtures_regress.models.Store'>, <class 'regressiontests.fixtures_regress.models.Person'>, <class 'regressiontests.fixtures_regress.models.Book'>] 322 323 >>> sort_dependencies([('fixtures_regress', [Person, Store, Book])]) 324 [<class 'regressiontests.fixtures_regress.models.Store'>, <class 'regressiontests.fixtures_regress.models.Person'>, <class 'regressiontests.fixtures_regress.models.Book'>] 325 326 # A dangling dependency - assume the user knows what they are doing. 327 >>> sort_dependencies([('fixtures_regress', [Person, Circle1, Store, Book])]) 328 [<class 'regressiontests.fixtures_regress.models.Circle1'>, <class 'regressiontests.fixtures_regress.models.Store'>, <class 'regressiontests.fixtures_regress.models.Person'>, <class 'regressiontests.fixtures_regress.models.Book'>] 329 330 # A tight circular dependency 331 >>> sort_dependencies([('fixtures_regress', [Person, Circle2, Circle1, Store, Book])]) 332 Traceback (most recent call last): 333 ... 334 CommandError: Can't resolve dependencies for fixtures_regress.Circle1, fixtures_regress.Circle2 in serialized app list. 335 336 >>> sort_dependencies([('fixtures_regress', [Circle1, Book, Circle2])]) 337 Traceback (most recent call last): 338 ... 339 CommandError: Can't resolve dependencies for fixtures_regress.Circle1, fixtures_regress.Circle2 in serialized app list. 340 341 # A self referential dependency 342 >>> sort_dependencies([('fixtures_regress', [Book, Circle3])]) 343 Traceback (most recent call last): 344 ... 345 CommandError: Can't resolve dependencies for fixtures_regress.Circle3 in serialized app list. 346 347 # A long circular dependency 348 >>> sort_dependencies([('fixtures_regress', [Person, Circle2, Circle1, Circle3, Store, Book])]) 349 Traceback (most recent call last): 350 ... 351 CommandError: Can't resolve dependencies for fixtures_regress.Circle1, fixtures_regress.Circle2, fixtures_regress.Circle3 in serialized app list. 352 353 # A dependency on a normal, non-natural-key model 354 >>> sort_dependencies([('fixtures_regress', [Person, ExternalDependency, Book])]) 355 [<class 'regressiontests.fixtures_regress.models.Person'>, <class 'regressiontests.fixtures_regress.models.Book'>, <class 'regressiontests.fixtures_regress.models.ExternalDependency'>] 356 357 ############################################### 358 # Check that normal primary keys still work 359 # on a model with natural key capabilities 360 361 >>> management.call_command('loaddata', 'non_natural_1.json', verbosity=0) 362 >>> management.call_command('loaddata', 'non_natural_2.xml', verbosity=0) 363 364 >>> Book.objects.all() 365 [<Book: Cryptonomicon by Neal Stephenson (available at Amazon, Borders)>, <Book: Ender's Game by Orson Scott Card (available at Collins Bookstore)>, <Book: Permutation City by Greg Egan (available at Angus and Robertson)>] 366 195 367 """} 368