1
0
mirror of https://github.com/django/django.git synced 2025-03-28 02:00:45 +00:00

Fixed : Added big integer field. Thanks to Tomáš Kopeček for persistently maintaining a patch for this.

git-svn-id: http://code.djangoproject.com/svn/django/trunk@11887 bcc190cf-cafb-0310-a4f2-bffc1f526a37
This commit is contained in:
Karen Tracey 2009-12-17 15:10:38 +00:00
parent fd4cc65baf
commit 5bd63663a9
20 changed files with 125 additions and 18 deletions
AUTHORS
django
docs
ref/models
topics/forms
tests
modeltests/model_forms
regressiontests
introspection
model_fields
serializers_regress

@ -246,6 +246,7 @@ answer newbie questions, and generally made Django that much better:
Cameron Knight (ckknight)
Nena Kojadin <nena@kiberpipa.org>
Igor Kolar <ike@email.si>
Tomáš Kopeček <permonik@m6.cz>
Gasper Koren
Martin Kosír <martin@martinkosir.net>
Arthur Koziel <http://arthurkoziel.com>

@ -42,14 +42,15 @@ FORMFIELD_FOR_DBFIELD_DEFAULTS = {
'form_class': forms.SplitDateTimeField,
'widget': widgets.AdminSplitDateTime
},
models.DateField: {'widget': widgets.AdminDateWidget},
models.TimeField: {'widget': widgets.AdminTimeWidget},
models.TextField: {'widget': widgets.AdminTextareaWidget},
models.URLField: {'widget': widgets.AdminURLFieldWidget},
models.IntegerField: {'widget': widgets.AdminIntegerFieldWidget},
models.CharField: {'widget': widgets.AdminTextInputWidget},
models.ImageField: {'widget': widgets.AdminFileWidget},
models.FileField: {'widget': widgets.AdminFileWidget},
models.DateField: {'widget': widgets.AdminDateWidget},
models.TimeField: {'widget': widgets.AdminTimeWidget},
models.TextField: {'widget': widgets.AdminTextareaWidget},
models.URLField: {'widget': widgets.AdminURLFieldWidget},
models.IntegerField: {'widget': widgets.AdminIntegerFieldWidget},
models.BigIntegerField: {'widget': widgets.AdminIntegerFieldWidget},
models.CharField: {'widget': widgets.AdminTextInputWidget},
models.ImageField: {'widget': widgets.AdminFileWidget},
models.FileField: {'widget': widgets.AdminFileWidget},
}

@ -18,6 +18,7 @@ class DatabaseCreation(BaseDatabaseCreation):
'FilePathField': 'varchar(%(max_length)s)',
'FloatField': 'double precision',
'IntegerField': 'integer',
'BigIntegerField': 'bigint',
'IPAddressField': 'char(15)',
'NullBooleanField': 'bool',
'OneToOneField': 'integer',

@ -17,7 +17,7 @@ class DatabaseIntrospection(BaseDatabaseIntrospection):
FIELD_TYPE.FLOAT: 'FloatField',
FIELD_TYPE.INT24: 'IntegerField',
FIELD_TYPE.LONG: 'IntegerField',
FIELD_TYPE.LONGLONG: 'IntegerField',
FIELD_TYPE.LONGLONG: 'BigIntegerField',
FIELD_TYPE.SHORT: 'IntegerField',
FIELD_TYPE.STRING: 'CharField',
FIELD_TYPE.TIMESTAMP: 'DateTimeField',

@ -27,6 +27,7 @@ class DatabaseCreation(BaseDatabaseCreation):
'FilePathField': 'NVARCHAR2(%(max_length)s)',
'FloatField': 'DOUBLE PRECISION',
'IntegerField': 'NUMBER(11)',
'BigIntegerField': 'NUMBER(19)',
'IPAddressField': 'VARCHAR2(15)',
'NullBooleanField': 'NUMBER(1) CHECK ((%(qn_column)s IN (0,1)) OR (%(qn_column)s IS NULL))',
'OneToOneField': 'NUMBER(11)',

@ -29,7 +29,10 @@ class DatabaseIntrospection(BaseDatabaseIntrospection):
def get_field_type(self, data_type, description):
# If it's a NUMBER with scale == 0, consider it an IntegerField
if data_type == cx_Oracle.NUMBER and description[5] == 0:
return 'IntegerField'
if description[4] > 11:
return 'BigIntegerField'
else:
return 'IntegerField'
else:
return super(DatabaseIntrospection, self).get_field_type(
data_type, description)

@ -18,6 +18,7 @@ class DatabaseCreation(BaseDatabaseCreation):
'FilePathField': 'varchar(%(max_length)s)',
'FloatField': 'double precision',
'IntegerField': 'integer',
'BigIntegerField': 'bigint',
'IPAddressField': 'inet',
'NullBooleanField': 'boolean',
'OneToOneField': 'integer',

@ -4,6 +4,7 @@ class DatabaseIntrospection(BaseDatabaseIntrospection):
# Maps type codes to Django Field types.
data_types_reverse = {
16: 'BooleanField',
20: 'BigIntegerField',
21: 'SmallIntegerField',
23: 'IntegerField',
25: 'TextField',

@ -19,6 +19,7 @@ class DatabaseCreation(BaseDatabaseCreation):
'FilePathField': 'varchar(%(max_length)s)',
'FloatField': 'real',
'IntegerField': 'integer',
'BigIntegerField': 'bigint',
'IPAddressField': 'char(15)',
'NullBooleanField': 'bool',
'OneToOneField': 'integer',

@ -16,6 +16,7 @@ class FlexibleFieldLookupDict:
'smallinteger': 'SmallIntegerField',
'int': 'IntegerField',
'integer': 'IntegerField',
'bigint': 'BigIntegerField',
'integer unsigned': 'PositiveIntegerField',
'decimal': 'DecimalField',
'real': 'FloatField',

@ -732,6 +732,19 @@ class IntegerField(Field):
defaults.update(kwargs)
return super(IntegerField, self).formfield(**defaults)
class BigIntegerField(IntegerField):
empty_strings_allowed = False
description = ugettext_lazy("Big (8 byte) integer")
MAX_BIGINT = 9223372036854775807
def get_internal_type(self):
return "BigIntegerField"
def formfield(self, **kwargs):
defaults = {'min_value': -BigIntegerField.MAX_BIGINT - 1,
'max_value': BigIntegerField.MAX_BIGINT}
defaults.update(kwargs)
return super(BigIntegerField, self).formfield(**defaults)
class IPAddressField(Field):
empty_strings_allowed = False
description = ugettext_lazy("IP address")

@ -299,6 +299,18 @@ according to available IDs. You usually won't need to use this directly; a
primary key field will automatically be added to your model if you don't specify
otherwise. See :ref:`automatic-primary-key-fields`.
``BigIntegerField``
-------------------
.. versionadded:: 1.2
.. class:: BigIntegerField([**options])
A 64 bit integer, much like an :class:`IntegerField` except that it is
guaranteed to fit numbers from -9223372036854775808 to 9223372036854775807. The
admin represents this as an ``<input type="text">`` (a single-line input).
``BooleanField``
----------------

@ -46,6 +46,10 @@ the full list of conversions:
=============================== ========================================
``AutoField`` Not represented in the form
``BigIntegerField`` ``IntegerField`` with ``min_value`` set
to -9223372036854775808 and ``max_value``
set to 9223372036854775807.
``BooleanField`` ``BooleanField``
``CharField`` ``CharField`` with ``max_length`` set to
@ -108,6 +112,10 @@ the full list of conversions:
The ``FloatField`` form field and ``DecimalField`` model and form fields
are new in Django 1.0.
.. versionadded:: 1.2
The ``BigIntegerField`` is new in Django 1.2.
As you might expect, the ``ForeignKey`` and ``ManyToManyField`` model field
types are special cases:

@ -13,12 +13,6 @@ import tempfile
from django.db import models
from django.core.files.storage import FileSystemStorage
# Python 2.3 doesn't have sorted()
try:
sorted
except NameError:
from django.utils.itercompat import sorted
temp_storage_dir = tempfile.mkdtemp()
temp_storage = FileSystemStorage(temp_storage_dir)
@ -201,6 +195,12 @@ class Post(models.Model):
def __unicode__(self):
return self.name
class BigInt(models.Model):
biggie = models.BigIntegerField()
def __unicode__(self):
return unicode(self.biggie)
__test__ = {'API_TESTS': """
>>> from django import forms
>>> from django.forms.models import ModelForm, model_to_dict
@ -1145,6 +1145,28 @@ True
# Delete the current file since this is not done by Django.
>>> instance.file.delete()
>>> instance.delete()
# BigIntegerField ################################################################
>>> class BigIntForm(forms.ModelForm):
... class Meta:
... model = BigInt
...
>>> bif = BigIntForm({'biggie': '-9223372036854775808'})
>>> bif.is_valid()
True
>>> bif = BigIntForm({'biggie': '-9223372036854775809'})
>>> bif.is_valid()
False
>>> bif.errors
{'biggie': [u'Ensure this value is greater than or equal to -9223372036854775808.']}
>>> bif = BigIntForm({'biggie': '9223372036854775807'})
>>> bif.is_valid()
True
>>> bif = BigIntForm({'biggie': '9223372036854775808'})
>>> bif.is_valid()
False
>>> bif.errors
{'biggie': [u'Ensure this value is less than or equal to 9223372036854775807.']}
"""}
if test_images:

@ -4,6 +4,7 @@ class Reporter(models.Model):
first_name = models.CharField(max_length=30)
last_name = models.CharField(max_length=30)
email = models.EmailField()
facebook_user_id = models.BigIntegerField()
def __unicode__(self):
return u"%s %s" % (self.first_name, self.last_name)

@ -77,7 +77,7 @@ class IntrospectionTests(TestCase):
cursor = connection.cursor()
desc = connection.introspection.get_table_description(cursor, Reporter._meta.db_table)
self.assertEqual([datatype(r[1], r) for r in desc],
['IntegerField', 'CharField', 'CharField', 'CharField'])
['IntegerField', 'CharField', 'CharField', 'CharField', 'BigIntegerField'])
# Regression test for #9991 - 'real' types in postgres
if settings.DATABASE_ENGINE.startswith('postgresql'):

@ -51,6 +51,9 @@ class BigD(models.Model):
class BigS(models.Model):
s = models.SlugField(max_length=255)
class BigInt(models.Model):
value = models.BigIntegerField()
null_value = models.BigIntegerField(null = True, blank = True)
###############################################################################
# ImageField

@ -6,7 +6,7 @@ from django import forms
from django.db import models
from django.core.exceptions import ValidationError
from models import Foo, Bar, Whiz, BigD, BigS, Image
from models import Foo, Bar, Whiz, BigD, BigS, Image, BigInt
try:
from decimal import Decimal
@ -144,3 +144,32 @@ class SlugFieldTests(django.test.TestCase):
bs = BigS.objects.create(s = 'slug'*50)
bs = BigS.objects.get(pk=bs.pk)
self.assertEqual(bs.s, 'slug'*50)
class BigIntegerFieldTests(django.test.TestCase):
def test_limits(self):
# Ensure that values that are right at the limits can be saved
# and then retrieved without corruption.
maxval = 9223372036854775807
minval = -maxval - 1
BigInt.objects.create(value=maxval)
qs = BigInt.objects.filter(value__gte=maxval)
self.assertEqual(qs.count(), 1)
self.assertEqual(qs[0].value, maxval)
BigInt.objects.create(value=minval)
qs = BigInt.objects.filter(value__lte=minval)
self.assertEqual(qs.count(), 1)
self.assertEqual(qs[0].value, minval)
def test_types(self):
b = BigInt(value = 0)
self.assertTrue(isinstance(b.value, (int, long)))
b.save()
self.assertTrue(isinstance(b.value, (int, long)))
b = BigInt.objects.all()[0]
self.assertTrue(isinstance(b.value, (int, long)))
def test_coercing(self):
BigInt.objects.create(value ='10')
b = BigInt.objects.get(value = '10')
self.assertEqual(b.value, 10)

@ -43,6 +43,9 @@ class FloatData(models.Model):
class IntegerData(models.Model):
data = models.IntegerField(null=True)
class BigIntegerData(models.Model):
data = models.BigIntegerField(null=True)
# class ImageData(models.Model):
# data = models.ImageField(null=True)

@ -321,6 +321,11 @@ The end."""),
(inherited_obj, 900, InheritAbstractModel, {'child_data':37,'parent_data':42}),
(inherited_obj, 910, ExplicitInheritBaseModel, {'child_data':37,'parent_data':42}),
(inherited_obj, 920, InheritBaseModel, {'child_data':37,'parent_data':42}),
(data_obj, 1000, BigIntegerData, 9223372036854775807),
(data_obj, 1001, BigIntegerData, -9223372036854775808),
(data_obj, 1002, BigIntegerData, 0),
(data_obj, 1003, BigIntegerData, None),
]
# Because Oracle treats the empty string as NULL, Oracle is expected to fail