Fixed #9431 -- Added extra validation for VARCHAR-based fields on MySQL.

max_length > 255 and unique=True is not permitted. Based on a patch from
adamnelson.


git-svn-id: http://code.djangoproject.com/svn/django/trunk@9650 bcc190cf-cafb-0310-a4f2-bffc1f526a37
This commit is contained in:
Malcolm Tredinnick 2008-12-16 06:43:18 +00:00
parent fddc0c589e
commit b58a260c56
3 changed files with 52 additions and 12 deletions

View File

@ -2,12 +2,27 @@ from django.db.backends import BaseDatabaseValidation
class DatabaseValidation(BaseDatabaseValidation): class DatabaseValidation(BaseDatabaseValidation):
def validate_field(self, errors, opts, f): def validate_field(self, errors, opts, f):
"Prior to MySQL 5.0.3, character fields could not exceed 255 characters" """
There are some field length restrictions for MySQL:
- Prior to version 5.0.3, character fields could not exceed 255
characters in length.
- No character (varchar) fields can have a length exceeding 255
characters if they have a unique index on them.
"""
from django.db import models from django.db import models
from django.db import connection from django.db import connection
db_version = connection.get_server_version() db_version = connection.get_server_version()
if db_version < (5, 0, 3) and isinstance(f, (models.CharField, models.CommaSeparatedIntegerField, models.SlugField)) and f.max_length > 255: varchar_fields = (models.CharField, models.CommaSeparatedIntegerField,
errors.add(opts, models.SlugField)
'"%s": %s cannot have a "max_length" greater than 255 when you are using a version of MySQL prior to 5.0.3 (you are using %s).' % if isinstance(f, varchar_fields) and f.max_length > 255:
(f.name, f.__class__.__name__, '.'.join([str(n) for n in db_version[:3]]))) if db_version < (5, 0, 3):
msg = '"%(name)s": %(cls)s cannot have a "max_length" greater than 255 when you are using a version of MySQL prior to 5.0.3 (you are using %(version)s).'
if f.unique == True:
msg = '"%(name)s": %(cls)s cannot have a "max_length" greater than 255 when using "unique=True".'
else:
msg = None
if msg:
errors.add(opts, msg % {'name': f.name, 'cls': f.__class__.__name__, 'version': '.'.join([str(n) for n in db_version[:3]])})

View File

@ -234,8 +234,11 @@ storage engine, you have a couple of options.
.. _AlterModelOnSyncDB: http://code.djangoproject.com/wiki/AlterModelOnSyncDB .. _AlterModelOnSyncDB: http://code.djangoproject.com/wiki/AlterModelOnSyncDB
Boolean fields in Django Notes on specific fields
------------------------- ------------------------
Boolean fields
~~~~~~~~~~~~~~
Since MySQL doesn't have a direct ``BOOLEAN`` column type, Django uses a Since MySQL doesn't have a direct ``BOOLEAN`` column type, Django uses a
``TINYINT`` column with values of ``1`` and ``0`` to store values for the ``TINYINT`` column with values of ``1`` and ``0`` to store values for the
@ -244,6 +247,19 @@ of that field for more details, but usually this won't be something that will
matter unless you're printing out the field values and are expecting to see matter unless you're printing out the field values and are expecting to see
``True`` and ``False.``. ``True`` and ``False.``.
Character fields
~~~~~~~~~~~~~~~~
Any fields that are stored with ``VARCHAR`` column types have their
``max_length`` restricted to 255 characters if you are using ``unique=True``
for the field. This affects :class:`~django.db.models.CharField`,
:class:`~django.db.models.SlugField` and
:class:`~django.db.models.CommaSeparatedIntegerField`.
Furthermore, if you are using a version of MySQL prior to 5.0.3, all of those
column types have a maximum length restriction of 255 characters, regardless
of whether ``unique=True`` is specified or not.
.. _sqlite-notes: .. _sqlite-notes:
SQLite notes SQLite notes

View File

@ -327,6 +327,13 @@ The admin represents this as an ``<input type="text">`` (a single-line input).
The maximum length (in characters) of the field. The max_length is enforced The maximum length (in characters) of the field. The max_length is enforced
at the database level and in Django's validation. at the database level and in Django's validation.
.. note::
If you are writing an application that must be portable to multiple
database backends, you should be aware that there are restrictions on
``max_length`` for some backends. Refer to the :ref:`database backend
notes <ref-databases>` for details.
.. admonition:: MySQL users .. admonition:: MySQL users
If you are using this field with MySQLdb 1.2.2 and the ``utf8_bin`` If you are using this field with MySQLdb 1.2.2 and the ``utf8_bin``
@ -341,7 +348,8 @@ The admin represents this as an ``<input type="text">`` (a single-line input).
.. class:: CommaSeparatedIntegerField(max_length=None, [**options]) .. class:: CommaSeparatedIntegerField(max_length=None, [**options])
A field of integers separated by commas. As in :class:`CharField`, the A field of integers separated by commas. As in :class:`CharField`, the
:attr:`~CharField.max_length` argument is required. :attr:`~CharField.max_length` argument is required and the note about database
portability mentioned there should be heeded.
``DateField`` ``DateField``
------------- -------------
@ -654,9 +662,10 @@ Like a :class:`PositiveIntegerField`, but only allows values under a certain
containing only letters, numbers, underscores or hyphens. They're generally used containing only letters, numbers, underscores or hyphens. They're generally used
in URLs. in URLs.
Like a CharField, you can specify :attr:`~CharField.max_length`. If Like a CharField, you can specify :attr:`~CharField.max_length` (read the note
:attr:`~CharField.max_length` is not specified, Django will use a default length about database portability and :attr:`~CharField.max_length` in that section,
of 50. too). If :attr:`~CharField.max_length` is not specified, Django will use a
default length of 50.
Implies setting :attr:`Field.db_index` to ``True``. Implies setting :attr:`Field.db_index` to ``True``.