Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Fixed #399: Added big integer field. Thanks to Tomáš Kopeček for pers…

…istently maintaining a patch for this.

git-svn-id: http://code.djangoproject.com/svn/django/trunk@11887 bcc190cf-cafb-0310-a4f2-bffc1f526a37
  • Loading branch information...
commit 5bd63663a9754ef783aa21402f534fe6ed45ef57 1 parent fd4cc65
@kmtracey kmtracey authored
View
1  AUTHORS
@@ -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>
View
17 django/contrib/admin/options.py
@@ -42,14 +42,15 @@ class IncorrectLookupParameters(Exception):
'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},
}
View
1  django/db/backends/mysql/creation.py
@@ -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',
View
2  django/db/backends/mysql/introspection.py
@@ -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',
View
1  django/db/backends/oracle/creation.py
@@ -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)',
View
5 django/db/backends/oracle/introspection.py
@@ -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)
View
1  django/db/backends/postgresql/creation.py
@@ -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',
View
1  django/db/backends/postgresql/introspection.py
@@ -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',
View
1  django/db/backends/sqlite3/creation.py
@@ -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',
View
1  django/db/backends/sqlite3/introspection.py
@@ -16,6 +16,7 @@ class FlexibleFieldLookupDict:
'smallinteger': 'SmallIntegerField',
'int': 'IntegerField',
'integer': 'IntegerField',
+ 'bigint': 'BigIntegerField',
'integer unsigned': 'PositiveIntegerField',
'decimal': 'DecimalField',
'real': 'FloatField',
View
13 django/db/models/fields/__init__.py
@@ -732,6 +732,19 @@ def formfield(self, **kwargs):
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")
View
12 docs/ref/models/fields.txt
@@ -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``
----------------
View
8 docs/topics/forms/modelforms.txt
@@ -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:
View
34 tests/modeltests/model_forms/models.py
@@ -13,12 +13,6 @@
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 @@ def __unicode__(self):
# 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:
View
1  tests/regressiontests/introspection/models.py
@@ -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)
View
2  tests/regressiontests/introspection/tests.py
@@ -77,7 +77,7 @@ def test_get_table_description_types(self):
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'):
View
3  tests/regressiontests/model_fields/models.py
@@ -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
View
31 tests/regressiontests/model_fields/tests.py
@@ -6,7 +6,7 @@
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 @@ def test_slugfield_max_length(self):
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)
+
View
3  tests/regressiontests/serializers_regress/models.py
@@ -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)
View
5 tests/regressiontests/serializers_regress/tests.py
@@ -321,6 +321,11 @@ def inherited_compare(testcase, pk, klass, data):
(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
Please sign in to comment.
Something went wrong with that request. Please try again.