diff options
author | Boulder Sprinters <boulder-sprinters@djangoproject.com> | 2007-03-20 16:21:17 +0000 |
---|---|---|
committer | Boulder Sprinters <boulder-sprinters@djangoproject.com> | 2007-03-20 16:21:17 +0000 |
commit | 815837c8af6cb917dabbb3638b2ccf182263866d (patch) | |
tree | 5ed1c4d8448c2977f8773404effe4360c1f9ae9d | |
parent | 881c07cf2e212e04b2a8be47f444c6da56b5f382 (diff) | |
download | django-815837c8af6cb917dabbb3638b2ccf182263866d.tar.gz |
boulder-oracle-sprint: Merged to [4754]. 8 tests still fail, although
serializers_regress fails on Postgres as well so it may need a more general fix.
git-svn-id: http://code.djangoproject.com/svn/django/branches/boulder-oracle-sprint@4755 bcc190cf-cafb-0310-a4f2-bffc1f526a37
-rw-r--r-- | django/core/serializers/base.py | 20 | ||||
-rw-r--r-- | django/core/serializers/pyyaml.py | 4 | ||||
-rw-r--r-- | django/core/serializers/xml_serializer.py | 9 | ||||
-rw-r--r-- | django/db/backends/mysql/base.py | 10 | ||||
-rw-r--r-- | django/db/models/fields/__init__.py | 12 | ||||
-rw-r--r-- | django/db/models/fields/generic.py | 1 | ||||
-rw-r--r-- | django/db/models/options.py | 1 | ||||
-rw-r--r-- | django/db/models/query.py | 2 | ||||
-rw-r--r-- | django/template/defaulttags.py | 8 | ||||
-rw-r--r-- | django/utils/datastructures.py | 2 | ||||
-rw-r--r-- | django/utils/text.py | 2 | ||||
-rw-r--r-- | docs/contributing.txt | 14 | ||||
-rw-r--r-- | docs/databases.txt | 122 | ||||
-rw-r--r-- | docs/distributions.txt | 2 | ||||
-rw-r--r-- | docs/django-admin.txt | 2 | ||||
-rw-r--r-- | docs/i18n.txt | 14 | ||||
-rw-r--r-- | docs/model-api.txt | 5 | ||||
-rw-r--r-- | tests/regressiontests/defaultfilters/tests.py | 6 | ||||
-rw-r--r-- | tests/regressiontests/serializers_regress/models.py | 19 | ||||
-rw-r--r-- | tests/regressiontests/serializers_regress/tests.py | 20 |
20 files changed, 170 insertions, 105 deletions
diff --git a/django/core/serializers/base.py b/django/core/serializers/base.py index 7dde2a4faf..8e610ad240 100644 --- a/django/core/serializers/base.py +++ b/django/core/serializers/base.py @@ -34,17 +34,17 @@ class Serializer(object): for obj in queryset: self.start_object(obj) for field in obj._meta.fields: - if field is obj._meta.pk: - continue - elif field.rel is None: - if self.selected_fields is None or field.attname in self.selected_fields: - self.handle_field(obj, field) - else: - if self.selected_fields is None or field.attname[:-3] in self.selected_fields: - self.handle_fk_field(obj, field) + if field.serialize: + if field.rel is None: + if self.selected_fields is None or field.attname in self.selected_fields: + self.handle_field(obj, field) + else: + if self.selected_fields is None or field.attname[:-3] in self.selected_fields: + self.handle_fk_field(obj, field) for field in obj._meta.many_to_many: - if self.selected_fields is None or field.attname in self.selected_fields: - self.handle_m2m_field(obj, field) + if field.serialize: + if self.selected_fields is None or field.attname in self.selected_fields: + self.handle_m2m_field(obj, field) self.end_object(obj) self.end_serialization() return self.getvalue() diff --git a/django/core/serializers/pyyaml.py b/django/core/serializers/pyyaml.py index f45a511e79..fa3dec984e 100644 --- a/django/core/serializers/pyyaml.py +++ b/django/core/serializers/pyyaml.py @@ -15,7 +15,7 @@ import yaml class Serializer(PythonSerializer): """ - Convert a queryset to JSON. + Convert a queryset to YAML. """ def end_serialization(self): yaml.dump(self.objects, self.stream, **self.options) @@ -25,7 +25,7 @@ class Serializer(PythonSerializer): def Deserializer(stream_or_string, **options): """ - Deserialize a stream or string of JSON data. + Deserialize a stream or string of YAML data. """ if isinstance(stream_or_string, basestring): stream = StringIO(stream_or_string) diff --git a/django/core/serializers/xml_serializer.py b/django/core/serializers/xml_serializer.py index 9e37f03cc2..3a0fdb5395 100644 --- a/django/core/serializers/xml_serializer.py +++ b/django/core/serializers/xml_serializer.py @@ -13,6 +13,10 @@ class Serializer(base.Serializer): Serializes a QuerySet to XML. """ + def indent(self, level): + if self.options.get('indent', None) is not None: + self.xml.ignorableWhitespace('\n' + ' ' * self.options.get('indent', None) * level) + def start_serialization(self): """ Start serialization -- open the XML document and the root element. @@ -25,6 +29,7 @@ class Serializer(base.Serializer): """ End serialization -- end the document. """ + self.indent(0) self.xml.endElement("django-objects") self.xml.endDocument() @@ -35,6 +40,7 @@ class Serializer(base.Serializer): if not hasattr(obj, "_meta"): raise base.SerializationError("Non-model object (%s) encountered during serialization" % type(obj)) + self.indent(1) self.xml.startElement("object", { "pk" : str(obj._get_pk_val()), "model" : str(obj._meta), @@ -44,6 +50,7 @@ class Serializer(base.Serializer): """ Called after handling all fields for an object. """ + self.indent(1) self.xml.endElement("object") def handle_field(self, obj, field): @@ -51,6 +58,7 @@ class Serializer(base.Serializer): Called to handle each field on an object (except for ForeignKeys and ManyToManyFields) """ + self.indent(2) self.xml.startElement("field", { "name" : field.name, "type" : field.get_internal_type() @@ -94,6 +102,7 @@ class Serializer(base.Serializer): """ Helper to output the <field> element for relational fields """ + self.indent(2) self.xml.startElement("field", { "name" : field.name, "rel" : field.rel.__class__.__name__, diff --git a/django/db/backends/mysql/base.py b/django/db/backends/mysql/base.py index c635e58cba..5767eaed51 100644 --- a/django/db/backends/mysql/base.py +++ b/django/db/backends/mysql/base.py @@ -10,8 +10,14 @@ try: except ImportError, e: from django.core.exceptions import ImproperlyConfigured raise ImproperlyConfigured, "Error loading MySQLdb module: %s" % e -if Database.version_info < (1,2,1,'final',2): - raise ImportError, "MySQLdb-1.2.1p2 or newer is required; you have %s" % MySQLdb.__version__ + +# We want version (1, 2, 1, 'final', 2) or later. We can't just use +# lexicographic ordering in this check because then (1, 2, 1, 'gamma') +# inadvertently passes the version test. +version = Database.version_info +if (version < (1,2,1) or (version[:3] == (1, 2, 1) and + (len(version) < 5 or version[3] != 'final' or version[4] < 2))): + raise ImportError, "MySQLdb-1.2.1p2 or newer is required; you have %s" % Database.__version__ from MySQLdb.converters import conversions from MySQLdb.constants import FIELD_TYPE diff --git a/django/db/models/fields/__init__.py b/django/db/models/fields/__init__.py index b1436dcecd..cb167004bc 100644 --- a/django/db/models/fields/__init__.py +++ b/django/db/models/fields/__init__.py @@ -67,7 +67,7 @@ class Field(object): def __init__(self, verbose_name=None, name=None, primary_key=False, maxlength=None, unique=False, blank=False, null=False, db_index=False, - core=False, rel=None, default=NOT_PROVIDED, editable=True, + core=False, rel=None, default=NOT_PROVIDED, editable=True, serialize=True, prepopulate_from=None, unique_for_date=None, unique_for_month=None, unique_for_year=None, validator_list=None, choices=None, radio_admin=None, help_text='', db_column=None): @@ -78,6 +78,7 @@ class Field(object): self.blank, self.null = blank, null self.core, self.rel, self.default = core, rel, default self.editable = editable + self.serialize = serialize self.validator_list = validator_list or [] self.prepopulate_from = prepopulate_from self.unique_for_date, self.unique_for_month = unique_for_date, unique_for_month @@ -851,9 +852,12 @@ class TimeField(Field): value = value.replace(microsecond=0) value = str(value) elif settings.DATABASE_ENGINE == 'oracle': - value = value.replace(microsecond=0) - # cx_Oracle expects a datetime.datetime to persist into TIMESTAMP field. - value = datetime.datetime(1900, 1, 1, value.hour, value.minute, value.second) + if hasattr(value, 'microsecond'): + value = value.replace(microsecond=0) + # cx_Oracle expects a datetime.datetime to persist into TIMESTAMP field. + value = datetime.datetime(1900, 1, 1, value.hour, value.minute, value.second) + else: + value = datetime.datetime(*(time.strptime(value, '%H:%M:%S')[:6])) else: value = str(value) return Field.get_db_prep_save(self, value) diff --git a/django/db/models/fields/generic.py b/django/db/models/fields/generic.py index 1ad8346e42..480ee689c9 100644 --- a/django/db/models/fields/generic.py +++ b/django/db/models/fields/generic.py @@ -94,6 +94,7 @@ class GenericRelation(RelatedField, Field): kwargs['blank'] = True kwargs['editable'] = False + kwargs['serialize'] = False Field.__init__(self, **kwargs) def get_manipulator_field_objs(self): diff --git a/django/db/models/options.py b/django/db/models/options.py index 32a9a274ce..e2c896a668 100644 --- a/django/db/models/options.py +++ b/django/db/models/options.py @@ -88,6 +88,7 @@ class Options(object): self.fields.insert(bisect(self.fields, field), field) if not self.pk and field.primary_key: self.pk = field + field.serialize = False def __repr__(self): return '<Options for %s>' % self.object_name diff --git a/django/db/models/query.py b/django/db/models/query.py index b92cf4e04e..b9dd620afc 100644 --- a/django/db/models/query.py +++ b/django/db/models/query.py @@ -808,7 +808,7 @@ def fill_table_cache(opts, select, tables, where, old_prefix, cache_tables_seen, def parse_lookup(kwarg_items, opts): # Helper function that handles converting API kwargs # (e.g. "name__exact": "tom") to SQL. - # Returns a tuple of (tables, joins, where, params). + # Returns a tuple of (joins, where, params). # 'joins' is a sorted dictionary describing the tables that must be joined # to complete the query. The dictionary is sorted because creation order diff --git a/django/template/defaulttags.py b/django/template/defaulttags.py index ed870047b1..b18fa1dce7 100644 --- a/django/template/defaulttags.py +++ b/django/template/defaulttags.py @@ -582,7 +582,7 @@ ifequal = register.tag(ifequal) #@register.tag def ifnotequal(parser, token): - """Output the contents of the block if the two arguments are not equal. See ifequal""" + """Output the contents of the block if the two arguments are not equal. See ifequal.""" return do_ifequal(parser, token, True) ifnotequal = register.tag(ifnotequal) @@ -901,7 +901,7 @@ def url(parser, token): """ Returns an absolute URL matching given view with its parameters. - This is a way to define links that aren't tied to a particular url configuration:: + This is a way to define links that aren't tied to a particular URL configuration:: {% url path.to.some_view arg1,arg2,name1=value1 %} @@ -912,11 +912,11 @@ def url(parser, token): URL. All arguments for the URL should be present. For example if you have a view ``app_name.client`` taking client's id and - the corresponding line in a urlconf looks like this:: + the corresponding line in a URLconf looks like this:: ('^client/(\d+)/$', 'app_name.client') - and this app's urlconf is included into the project's urlconf under some + and this app's URLconf is included into the project's URLconf under some path:: ('^clients/', include('project_name.app_name.urls')) diff --git a/django/utils/datastructures.py b/django/utils/datastructures.py index e924e4edbc..7b7fa2b0f0 100644 --- a/django/utils/datastructures.py +++ b/django/utils/datastructures.py @@ -94,7 +94,7 @@ class SortedDict(dict): def copy(self): "Returns a copy of this object." - # This way of initialising the copy means it works for subclasses, too. + # This way of initializing the copy means it works for subclasses, too. obj = self.__class__(self) obj.keyOrder = self.keyOrder return obj diff --git a/django/utils/text.py b/django/utils/text.py index 1c1c456e2d..faf8705fa9 100644 --- a/django/utils/text.py +++ b/django/utils/text.py @@ -17,7 +17,7 @@ def wrap(text, width): pos = len(word) - word.rfind('\n') - 1 for word in it: if "\n" in word: - lines = word.splitlines() + lines = word.split('\n') else: lines = (word,) pos += len(lines[0]) + 1 diff --git a/docs/contributing.txt b/docs/contributing.txt index 8364405775..1d2b635b76 100644 --- a/docs/contributing.txt +++ b/docs/contributing.txt @@ -303,11 +303,11 @@ Please follow these coding standards when writing code for inclusion in Django: def my_view(req, foo): # ... - * Our policy is to keep the names of developers and contributors - in the ``AUTHORS`` file distributed with Django, so please don't include - your name in the actual code. Feel free to include a change to the - ``AUTHORS`` file in your patch if you make more than a single trivial - change. + * Please don't put your name in the code you contribute. Our policy is to + keep contributors' names in the ``AUTHORS`` file distributed with Django + -- not scattered throughout the codebase itself. Feel free to include a + change to the ``AUTHORS`` file in your patch if you make more than a + single trivial change. Committing code =============== @@ -527,12 +527,12 @@ sure all other lines are commented:: # http://code.djangoproject.com/svn/django/trunk/ # /path/to/trunk - + # <branch> is a svn checkout of: # http://code.djangoproject.com/svn/django/branches/<branch>/ # #/path/to/<branch> - + # On windows a path may look like this: # C:/path/to/<branch> diff --git a/docs/databases.txt b/docs/databases.txt index ff6abd7271..3545b58d47 100644 --- a/docs/databases.txt +++ b/docs/databases.txt @@ -1,56 +1,59 @@ =============================== -Notes About Supported Databases +Notes about supported databases =============================== -Django attempts to support as many features as possible on all databases. -However, since not all database servers are identical, there is obviously -going to be some variations. This file describes some of the -features that might relevant to Django usage. It is not intended as a -replacement for server-specific documentation or reference manuals. +Django attempts to support as many features as possible on all database +backends. However, not all database backends are alike, and we've had to make +design decisions on which features to support and which assumptions we can make +safely. -MySQL Notes +This file describes some of the features that might be relevant to Django +usage. Of course, it is not intended as a replacement for server-specific +documentation or reference manuals. + +MySQL notes =========== Django expects the database to support transactions, referential integrity, -and Unicode support (UTF-8 encoding). Fortunately MySQL_ has all these +and Unicode support (UTF-8 encoding). Fortunately, MySQL_ has all these features as available as far back as 3.23. While it may be possible to use -3.23 or 4.0, you will probably have less trouble if you use 4.1 or 5.0. +3.23 or 4.0, you'll probably have less trouble if you use 4.1 or 5.0. -MySQL-4.1 +MySQL 4.1 --------- -MySQL-4.1_ has greatly improved support for character sets. It is possible to +`MySQL 4.1`_ has greatly improved support for character sets. It is possible to set different default character sets on the database, table, and column. Previous versions have only a server-wide character set setting. It's also the first version where the character set can be changed on the fly. 4.1 also has -support for views, but these are not currently used by Django. +support for views, but Django currently doesn't use views. -MySQL-5.0 +MySQL 5.0 --------- -MySQL-5.0_ adds the ``information_schema`` database, which contains detailed -data on all database schema. This is used for Django's ``inspectdb`` feature, -when it is available. 5.0 also has support for stored procedures, but these -are not currently used by Django. +`MySQL 5.0`_ adds the ``information_schema`` database, which contains detailed +data on all database schema. Django's ``inspectdb`` feature uses this +``information_schema`` if it's available. 5.0 also has support for stored +procedures, but Django currently doesn't use stored procedures. .. _MySQL: http://www.mysql.com/ -.. _MySQL-4.1: http://dev.mysql.com/doc/refman/4.1/en/index.html -.. _MySQL-5.0: http://dev.mysql.com/doc/refman/5.0/en/index.html +.. _MySQL 4.1: http://dev.mysql.com/doc/refman/4.1/en/index.html +.. _MySQL 5.0: http://dev.mysql.com/doc/refman/5.0/en/index.html -Storage Engines +Storage engines --------------- MySQL has several `storage engines`_ (previously called table types). You can change the default storage engine in the server configuration. -The default one is MyISAM_. The main drawback of MyISAM is that it does not -currently have support for transactions or foreign keys. On the plus side, it -is currently the only engine that supports full-text indexing and searching. +The default engine is MyISAM_. The main drawback of MyISAM is that it doesn't +currently support transactions or foreign keys. On the plus side, it's +currently the only engine that supports full-text indexing and searching. The InnoDB_ engine is fully transactional and supports foreign key references. The BDB_ engine, like InnoDB, is also fully transactional and supports foreign -key references. However, it's use seems to be somewhat deprecated. +key references. However, its use seems to be deprecated. `Other storage engines`_, including SolidDB_ and Falcon_, are on the horizon. For now, InnoDB is probably your best choice. @@ -66,25 +69,25 @@ For now, InnoDB is probably your best choice. MySQLdb ------- -`MySQLdb`_ is the Python interface to MySQL. 1.2.1 is the first version which -has support for MySQL-4.1 and newer. If you are trying to use an older version -of MySQL, then 1.2.0 *may* work for you. +`MySQLdb`_ is the Python interface to MySQL. 1.2.1 is the first version that +has support for MySQL 4.1 and newer. If you are trying to use an older version +of MySQL, then 1.2.0 *might* work for you. .. _MySQLdb: http://sourceforge.net/projects/mysql-python Creating your database -~~~~~~~~~~~~~~~~~~~~~~ +---------------------- You can `create your database`_ using the command-line tools and this SQL:: CREATE DATABASE <dbname> CHARACTER SET utf8; - -This ensures all tables and columns will use utf8 by default. - + +This ensures all tables and columns will use UTF-8 by default. + .. _create your database: http://dev.mysql.com/doc/refman/5.0/en/create-database.html Connecting to the database -~~~~~~~~~~~~~~~~~~~~~~~~~~ +-------------------------- Refer to the `settings documentation`_. @@ -106,7 +109,7 @@ Here's a sample configuration which uses a MySQL option file:: DATABASE_OPTIONS = { 'read_default_file': '/path/to/my.cnf', } - + # my.cnf [client] database = DATABASE_NAME @@ -114,49 +117,46 @@ Here's a sample configuration which uses a MySQL option file:: passwd = DATABASE_PASSWORD default-character-set = utf8 -There are several other MySQLdb connection options which may be useful, such -as ``ssl``, ``use_unicode``, ``init_command``, and ``sql_mode``; consult the +Several other MySQLdb connection options may be useful, such as ``ssl``, +``use_unicode``, ``init_command``, and ``sql_mode``. Consult the `MySQLdb documentation`_ for more details. - + .. _settings documentation: http://www.djangoproject.com/documentation/settings/#database-engine .. _MySQL option file: http://dev.mysql.com/doc/refman/5.0/en/option-files.html .. _MySQLdb documentation: http://mysql-python.sourceforge.net/ Creating your tables -~~~~~~~~~~~~~~~~~~~~ +-------------------- -When Django generates the schema, it doesn't specify a storage engine, so they -will be created with whatever default `storage engine`__ your database server -is configured for. The easiest solution is to set your database server's default -storage engine to the desired engine. +When Django generates the schema, it doesn't specify a storage engine, so +tables will be created with whatever default storage engine your database +server is configured for. The easiest solution is to set your database server's +default storage engine to the desired engine. -__ `storage engines`_ - -If you are using a hosting service and can't change your server's default +If you're using a hosting service and can't change your server's default storage engine, you have a couple of options. -After the tables is created, all that is needed to convert it to a new storage -engine (such as InnoDB) is:: - - ALTER TABLE <tablename> ENGINE=INNODB; + * After the tables are created, execute an ``ALTER TABLE`` statement to + convert a table to a new storage engine (such as InnoDB):: -With a lot of tables, this can be tedious. + ALTER TABLE <tablename> ENGINE=INNODB; -Another option is to use the ``init_command`` option for MySQLdb prior to -creating your tables:: + This can be tedious if you have a lot of tables. - DATABASE_OPTIONS = { - ... - "init_command": "SET storage_engine=INNODB", - ... - } + * Another option is to use the ``init_command`` option for MySQLdb prior to + creating your tables:: + + DATABASE_OPTIONS = { + # ... + "init_command": "SET storage_engine=INNODB", + # ... + } -This sets the default storage engine upon connecting to the database. After -your tables are set up and running in production, you should remove this -option. + This sets the default storage engine upon connecting to the database. + After your tables have been created, you should remove this option. -Another method for changing the storage engine is described in -AlterModelOnSyncDB_. + * Another method for changing the storage engine is described in + AlterModelOnSyncDB_. .. _AlterModelOnSyncDB: http://code.djangoproject.com/wiki/AlterModelOnSyncDB diff --git a/docs/distributions.txt b/docs/distributions.txt index a77d3a1959..63206c535e 100644 --- a/docs/distributions.txt +++ b/docs/distributions.txt @@ -57,7 +57,7 @@ Gentoo ------ A Django build is available for `Gentoo Linux`_, and is based on Django 0.95.1. -The `current Gentoo build`_ can be installed by typing ``emerge Django``. +The `current Gentoo build`_ can be installed by typing ``emerge django``. .. _Gentoo Linux: http://www.gentoo.org/ .. _current Gentoo build: http://packages.gentoo.org/packages/?category=dev-python;name=django diff --git a/docs/django-admin.txt b/docs/django-admin.txt index 371c44e010..ef1d73cdbd 100644 --- a/docs/django-admin.txt +++ b/docs/django-admin.txt @@ -216,7 +216,7 @@ installation will be aborted, and any data installed in the call to ``loaddata`` will be removed from the database. The fixtures that are named can include directory components. These -directories will be inluded in the search path. For example:: +directories will be included in the search path. For example:: django-admin.py loaddata foo/bar/mydata.json diff --git a/docs/i18n.txt b/docs/i18n.txt index d430a56160..4a05e53ddf 100644 --- a/docs/i18n.txt +++ b/docs/i18n.txt @@ -284,13 +284,13 @@ obtain) the language translations themselves. Here's how that works. .. admonition:: Locale restrictions - Django does not support localising your application into a locale for - which Django itself has not been translated -- it will ignore your - translation files. If you were to try this and Django supported it, you - would inevitably see a mixture of translated strings (from your - application) and English strings (from Django itself). If you are wanting - to support a locale for your application that is not already part of - Django, you will need to make at least a minimal translation of the Django + Django does not support localizing your application into a locale for + which Django itself has not been translated. In this case, it will ignore + your translation files. If you were to try this and Django supported it, + you would inevitably see a mixture of translated strings (from your + application) and English strings (from Django itself). If you want to + support a locale for your application that is not already part of + Django, you'll need to make at least a minimal translation of the Django core. Message files diff --git a/docs/model-api.txt b/docs/model-api.txt index e66e96de68..26686b02fe 100644 --- a/docs/model-api.txt +++ b/docs/model-api.txt @@ -1216,8 +1216,9 @@ screen via ``<script src="">`` tags. This can be used to tweak a given type of admin page in JavaScript or to provide "quick links" to fill in default values for certain fields. -If relative URLs are used, Django admin will automatically prepend these links -with ``settings.ADMIN_MEDIA_PREFIX``. +If you use relative URLs -- URLs that don't start with ``http://`` or ``/`` -- +then the admin site will automatically prefix these links with +``settings.ADMIN_MEDIA_PREFIX``. ``list_display`` ---------------- diff --git a/tests/regressiontests/defaultfilters/tests.py b/tests/regressiontests/defaultfilters/tests.py index c850806052..db3f7fab2a 100644 --- a/tests/regressiontests/defaultfilters/tests.py +++ b/tests/regressiontests/defaultfilters/tests.py @@ -133,6 +133,12 @@ u'\xcb' >>> wordwrap('this is a long paragraph of text that really needs to be wrapped I\'m afraid', 14) "this is a long\nparagraph of\ntext that\nreally needs\nto be wrapped\nI'm afraid" +>>> wordwrap('this is a short paragraph of text.\n But this line should be indented',14) +'this is a\nshort\nparagraph of\ntext.\n But this\nline should be\nindented' + +>>> wordwrap('this is a short paragraph of text.\n But this line should be indented',15) +'this is a short\nparagraph of\ntext.\n But this line\nshould be\nindented' + >>> ljust('test', 10) 'test ' diff --git a/tests/regressiontests/serializers_regress/models.py b/tests/regressiontests/serializers_regress/models.py index b558050022..d3415ac1b9 100644 --- a/tests/regressiontests/serializers_regress/models.py +++ b/tests/regressiontests/serializers_regress/models.py @@ -6,7 +6,8 @@ This class sets up a model for each model field type """ from django.db import models - +from django.contrib.contenttypes.models import ContentType + # The following classes are for testing basic data # marshalling, including NULL values. @@ -73,6 +74,22 @@ class USStateData(models.Model): class XMLData(models.Model): data = models.XMLField(null=True) +class Tag(models.Model): + """A tag on an item.""" + data = models.SlugField() + content_type = models.ForeignKey(ContentType) + object_id = models.PositiveIntegerField() + + content_object = models.GenericForeignKey() + + class Meta: + ordering = ["data"] + +class GenericData(models.Model): + data = models.CharField(maxlength=30) + + tags = models.GenericRelation(Tag) + # The following test classes are all for validation # of related objects; in particular, forward, backward, # and self references. diff --git a/tests/regressiontests/serializers_regress/tests.py b/tests/regressiontests/serializers_regress/tests.py index 008ccecc2c..97b3fbacbe 100644 --- a/tests/regressiontests/serializers_regress/tests.py +++ b/tests/regressiontests/serializers_regress/tests.py @@ -24,6 +24,14 @@ def data_create(pk, klass, data): instance.data = data instance.save() return instance + +def generic_create(pk, klass, data): + instance = klass(id=pk) + instance.data = data[0] + instance.save() + for tag in data[1:]: + instance.tags.create(data=tag) + return instance def fk_create(pk, klass, data): instance = klass(id=pk) @@ -56,6 +64,11 @@ def data_compare(testcase, pk, klass, data): testcase.assertEqual(data, instance.data, "Objects with PK=%d not equal; expected '%s' (%s), got '%s' (%s)" % (pk,data, type(data), instance.data, type(instance.data))) +def generic_compare(testcase, pk, klass, data): + instance = klass.objects.get(id=pk) + testcase.assertEqual(data[0], instance.data) + testcase.assertEqual(data[1:], [t.data for t in instance.tags.all()]) + def fk_compare(testcase, pk, klass, data): instance = klass.objects.get(id=pk) testcase.assertEqual(data, instance.data_id) @@ -76,6 +89,7 @@ def pk_compare(testcase, pk, klass, data): # actually a pair of functions; one to create # and one to compare objects of that type data_obj = (data_create, data_compare) +generic_obj = (generic_create, generic_compare) fk_obj = (fk_create, fk_compare) m2m_obj = (m2m_create, m2m_compare) o2o_obj = (o2o_create, o2o_compare) @@ -140,6 +154,9 @@ The end."""), (data_obj, 190, XMLData, "<foo></foo>"), (data_obj, 191, XMLData, None), + (generic_obj, 200, GenericData, ['Generic Object 1', 'tag1', 'tag2']), + (generic_obj, 201, GenericData, ['Generic Object 2', 'tag2', 'tag3']), + (data_obj, 300, Anchor, "Anchor 1"), (data_obj, 301, Anchor, "Anchor 2"), @@ -222,6 +239,9 @@ def serializerTest(format, self): transaction.commit() transaction.leave_transaction_management() + # Add the generic tagged objects to the object list + objects.extend(Tag.objects.all()) + # Serialize the test database serialized_data = serializers.serialize(format, objects, indent=2) |