Ticket #7052: lookup-dictionaries-for-fixtures.patch

File lookup-dictionaries-for-fixtures.patch, 34.8 KB (added by juan@…, 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):  
    6868        verbose_name = _('permission')
    6969        verbose_name_plural = _('permissions')
    7070        unique_together = (('content_type', 'codename'),)
     71        dump_relation = unique_together[0]
    7172        ordering = ('content_type__app_label', 'codename')
    7273
    7374    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):  
    7373        db_table = 'django_content_type'
    7474        ordering = ('name',)
    7575        unique_together = (('app_label', 'model'),)
     76        dump_relation = unique_together[0]
    7677
    7778    def __unicode__(self):
    7879        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)
    7989
    8090    def model_class(self):
    8191        "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  
    99from django.db import models
    1010from django.utils.encoding import smart_unicode
    1111from django.utils.safestring import mark_safe
     12
     13class RelationDepthExceeded(RuntimeError):
     14    pass
    1215
    1316class Serializer(base.Serializer):
    1417    """
    class Serializer(base.Serializer):  
    4245        value = smart_unicode(getattr(obj, field.name), strings_only=True)
    4346        self._current[field.name] = value
    4447
     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
    4567    def handle_fk_field(self, obj, field):
    4668        related = getattr(obj, field.name)
    4769        if related is not None:
    4870            if field.rel.field_name == related._meta.pk.name:
    4971                # Related to remote object via primary key
    50                 related = related._get_pk_val()
     72                related = self.handle_related(related)
    5173            else:
    5274                # 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
    5577
    5678    def handle_m2m_field(self, obj, field):
    5779        if field.creates_table:
    58             self._current[field.name] = [smart_unicode(related._get_pk_val(), strings_only=True)
     80            self._current[field.name] = [self.handle_related(related)
    5981                               for related in getattr(obj, field.name).iterator()]
    6082
    6183    def getvalue(self):
    def Deserializer(object_list, **options)  
    87109
    88110            # Handle M2M relations
    89111            if field.rel and isinstance(field.rel, models.ManyToManyRel):
    90                 m2m_convert = field.rel.to._meta.pk.to_python
    91                 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]
    92114
    93115            # Handle FK fields
    94116            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:
    96122                    data[field.attname] = field.rel.to._meta.get_field(field.rel.field_name).to_python(field_value)
    97                 else:
    98                     data[field.attname] = None
    99123
    100124            # Handle all other fields
    101125            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):  
    7676
    7777        self.xml.endElement("field")
    7878
     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
    7992    def handle_fk_field(self, obj, field):
    8093        """
    8194        Called to handle a ForeignKey (we need to treat them slightly
    class Serializer(base.Serializer):  
    8699        if related is not None:
    87100            if field.rel.field_name == related._meta.pk.name:
    88101                # Related to remote object via primary key
    89                 related = related._get_pk_val()
     102                self._handle_related(related.dump_related(), depth=3)
    90103            else:
    91104                # 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)))
    94106        else:
    95107            self.xml.addQuickElement("None")
    96108        self.xml.endElement("field")
    class Serializer(base.Serializer):  
    104116        if field.creates_table:
    105117            self._start_relational_field(field)
    106118            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)
    108128            self.xml.endElement("field")
    109129
    110130    def _start_relational_field(self, field):
    class Deserializer(base.Deserializer):  
    185205        # Return a DeserializedObject so that the m2m data has a place to live.
    186206        return base.DeserializedObject(Model(**data), m2m_data)
    187207
     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
    188246    def _handle_fk_field_node(self, node, field):
    189247        """
    190248        Handle a <field> node for a ForeignKey
    191249        """
    192250        # Check if there is a child node named 'None', returning None if so.
    193         if node.getElementsByTagName('None'):
     251        if node.getElementsByTagName("None"):
    194252            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)
    198254
    199255    def _handle_m2m_field_node(self, node, field):
    200256        """
    201257        Handle a <field> node for a ManyToManyField.
    202258        """
    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
    206262
    207263    def _get_model_from_node(self, node, attr):
    208264        """
  • django/db/models/base.py

    diff --git a/django/db/models/base.py b/django/db/models/base.py
    a b class Model(object):  
    295295        return setattr(self, self._meta.pk.attname, value)
    296296
    297297    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)
    298345
    299346    def save(self, force_insert=False, force_update=False):
    300347        """
  • 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  
    1919get_verbose_name = lambda class_name: re.sub('(((?<=[a-z])[A-Z])|([A-Z](?![A-Z]|$)))', ' \\1', class_name).lower().strip()
    2020
    2121DEFAULT_NAMES = ('verbose_name', 'db_table', 'ordering',
    22                  'unique_together', 'permissions', 'get_latest_by',
     22                 'unique_together', 'dump_relation', 'permissions', 'get_latest_by',
    2323                 'order_with_respect_to', 'app_label', 'db_tablespace',
    2424                 'abstract')
    2525
    class Options(object):  
    3232        self.db_table = ''
    3333        self.ordering = []
    3434        self.unique_together =  []
     35        self.dump_relation = []
    3536        self.permissions =  []
    3637        self.object_name, self.app_label = None, app_label
    3738        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  
    360360More details on named URL patterns are in the :ref:`URL dispatch documentation
    361361<topics-http-urls>`.
    362362
     363.. _lookup-dictionary:
     364
     365Serializing and deserializing auto-created objects
     366==================================================
     367
     368.. versionadded:: development
     369
     370In certain circumstances, a model needs to create objects based on
     371other models in an application. For instance, whenever a
     372:class:`~django.db.models.Model` is defined, Django will eventually
     373create corresponding :class:`~django.contrib.auth.models.Permission`
     374objects.
     375
     376Models with a :ref:`forward relationship<related-objects>` to
     377automatically created objects, such as ``Permission``, need help when
     378serializing and deserializing these references. This happens whenever
     379you create or load a fixture. Since ``Permission`` objects can be
     380created in any order, they cannot be reliably referenced by their
     381primary keys during serialization. Instead, they are referenced by a
     382lookup dictionary.
     383
     384``dump_relation``
     385-----------------
     386
     387When writing a class that will be referenced by a lookup dictionary,
     388you should specify :attr:`Options.dump_relation`.  For more
     389information, see the :ref:`model option reference<ref-models-options>`.
     390
     391Methods for handling custom relations
     392-------------------------------------
     393
     394If :attr:`dump_related` is too inflexible for a particular model, you
     395can override the following methods to serialize and deserialize custom
     396lookup dictionaries.
     397
     398.. method:: Model.dump_related()
     399
     400Defines a ``dump_related()`` method to tell Django how to build a lookup
     401dictionary for this model. For example::
     402
     403    def dump_related(self):
     404        return {'year': self.year, 'month': self.month, 'day': self.day}
     405
     406Django uses this when serializing objects, which typically happens when
     407:djadmin:`dumpdata<dumpdata>` is run.
     408
     409.. method:: Model.load_related(value)
     410
     411Defines a ``load_related()`` method to tell Django how to find the
     412primary key for this model, when deserializing. It returns the primary
     413key 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
     421Django 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
     425were created automatically, such as
     426:class:`~django.contrib.auth.models.Permission` or
     427:class:`~django.contrib.contenttypes.models.ContentType` objects. This
     428typically happens when :djadmin:`loaddata<loaddata>` is run.
     429
    363430Extra instance methods
    364431======================
    365432
  • 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  
    5959
    6060The name of the database tablespace to use for the model. If the backend doesn't
    6161support tablespaces, this option is ignored.
     62
     63``dump_relation``
     64-----------------
     65
     66.. attribute:: Options.dump_relation
     67
     68.. versionadded:: development
     69
     70Set of field names that, taken together, that define a :ref:`lookup
     71dictionary<lookup-dictionary>` for serialization::
     72
     73    dump_relation = ("driver", "restaurant")
     74
     75It's used by :meth:`Model.dump_related()` to build a lookup dictionary
     76when serializing a reference to this model.
     77
     78Since these fields are used to fetch a single object, they should also
     79appear in :attr:`~Options.unique_together`.
    6280
    6381``get_latest_by``
    6482-----------------
  • 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()``:  
    749749    for item in my_queryset:
    750750        item.save()
    751751
     752.. _related-objects:
     753
    752754Related objects
    753755===============
    754756
  • 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 &quot;Prince&quot;</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  
    88``FIXTURE_DIRS`` setting.
    99"""
    1010
     11from django.contrib.auth.models import Permission
     12from django.contrib.contenttypes import generic
     13from django.contrib.contenttypes.models import ContentType
    1114from django.db import models
    1215from django.conf import settings
    1316
    class Article(models.Model):  
    2023
    2124    class Meta:
    2225        ordering = ('-pub_date', 'headline')
     26
     27class 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
     37class 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
     48class 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()))
    2355
    2456__test__ = {'API_TESTS': """
    2557>>> from django.core import management
    __test__ = {'API_TESTS': """  
    4880>>> Article.objects.all()
    4981[<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>]
    5082
     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
    51103# Load a fixture that doesn't exist
    52104>>> management.call_command('loaddata', 'unknown.json', verbosity=0)
    53105
    54106# object list is unaffected
    55107>>> Article.objects.all()
    56108[<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>
    57118"""}
    58119
    59120# Database flushing does not work on MySQL with the default storage engine
    Multiple fixtures named 'fixture2' in '.  
    79140>>> Article.objects.all()
    80141[<Article: Time to reform copyright>, <Article: Poker has no place on ESPN>, <Article: Python program becomes self aware>]
    81142
     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
    82148# Dump the current contents of the database as a JSON fixture
    83149>>> 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>
    85156"""
    86157
    87158from django.test import TestCase
Back to Top