mirror of
https://github.com/django/django.git
synced 2025-07-04 09:49:12 +00:00
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
This commit is contained in:
parent
881c07cf2e
commit
815837c8af
@ -34,15 +34,15 @@ 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 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 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)
|
||||
|
@ -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)
|
||||
|
@ -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__,
|
||||
|
@ -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
|
||||
|
@ -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':
|
||||
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)
|
||||
|
@ -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):
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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'))
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
===============
|
||||
|
@ -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`_.
|
||||
|
||||
@ -114,8 +117,8 @@ 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
|
||||
@ -123,40 +126,37 @@ as ``ssl``, ``use_unicode``, ``init_command``, and ``sql_mode``; consult the
|
||||
.. _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::
|
||||
* After the tables are created, execute an ``ALTER TABLE`` statement to
|
||||
convert a table to a new storage engine (such as InnoDB)::
|
||||
|
||||
ALTER TABLE <tablename> ENGINE=INNODB;
|
||||
|
||||
With a lot of tables, this can be tedious.
|
||||
This can be tedious if you have a lot of tables.
|
||||
|
||||
Another option is to use the ``init_command`` option for MySQLdb prior to
|
||||
creating your tables::
|
||||
* 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
|
||||
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
@ -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``
|
||||
----------------
|
||||
|
@ -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 '
|
||||
|
||||
|
@ -6,6 +6,7 @@ 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.
|
||||
|
@ -25,6 +25,14 @@ def data_create(pk, klass, 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)
|
||||
setattr(instance, 'data_id', data)
|
||||
@ -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)
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user