Ticket #399: bigint-patch-20091215.diff

File bigint-patch-20091215.diff, 12.6 KB (added by Tomáš Kopeček, 15 years ago)

fixed: correct saving null fields + test

  • django/db/models/fields/__init__.py

     
    743743        defaults.update(kwargs)
    744744        return super(IntegerField, self).formfield(**defaults)
    745745
     746class BigIntegerField(IntegerField):
     747    MAX_BIGINT = 9223372036854775807
     748    empty_strings_allowed = False
     749    def get_internal_type(self):
     750        return "BigIntegerField"
     751
     752    def get_db_prep_save(self, value):
     753        if value is not None:
     754            value = long(value)
     755            if value > BigIntegerField.MAX_BIGINT or value < -BigIntegerField.MAX_BIGINT - 1:
     756                raise ValueError("Value is to small/large to fit this field")
     757        return super(BigIntegerField, self).get_db_prep_save(value)
     758
     759    def formfield(self, **kwargs):
     760        defaults = {'min_value': -BigIntegerField.MAX_BIGINT - 1,
     761                    'max_value': BigIntegerField.MAX_BIGINT}
     762        defaults.update(kwargs)
     763        return super(BigIntegerField, self).formfield(**defaults)
     764
     765
    746766class IPAddressField(Field):
    747767    """IP address"""
    748768   
  • django/db/backends/postgresql/introspection.py

     
    44    # Maps type codes to Django Field types.
    55    data_types_reverse = {
    66        16: 'BooleanField',
     7        20: 'BigIntegerField',
    78        21: 'SmallIntegerField',
    89        23: 'IntegerField',
    910        25: 'TextField',
  • django/db/backends/postgresql/creation.py

     
    1818        'FilePathField':     'varchar(%(max_length)s)',
    1919        'FloatField':        'double precision',
    2020        'IntegerField':      'integer',
     21        'BigIntegerField':   'bigint',
    2122        'IPAddressField':    'inet',
    2223        'NullBooleanField':  'boolean',
    2324        'OneToOneField':     'integer',
  • django/db/backends/sqlite3/introspection.py

     
    1616        'smallinteger': 'SmallIntegerField',
    1717        'int': 'IntegerField',
    1818        'integer': 'IntegerField',
     19        'bigint': 'BigIntegerField',
    1920        'integer unsigned': 'PositiveIntegerField',
    2021        'decimal': 'DecimalField',
    2122        'real': 'FloatField',
  • django/db/backends/sqlite3/creation.py

     
    1919        'FilePathField':                'varchar(%(max_length)s)',
    2020        'FloatField':                   'real',
    2121        'IntegerField':                 'integer',
     22        'BigIntegerField':                 'bigint',
    2223        'IPAddressField':               'char(15)',
    2324        'NullBooleanField':             'bool',
    2425        'OneToOneField':                'integer',
  • django/db/backends/mysql/introspection.py

     
    1717        FIELD_TYPE.FLOAT: 'FloatField',
    1818        FIELD_TYPE.INT24: 'IntegerField',
    1919        FIELD_TYPE.LONG: 'IntegerField',
    20         FIELD_TYPE.LONGLONG: 'IntegerField',
     20        FIELD_TYPE.LONGLONG: 'BigIntegerField',
    2121        FIELD_TYPE.SHORT: 'IntegerField',
    2222        FIELD_TYPE.STRING: 'CharField',
    2323        FIELD_TYPE.TIMESTAMP: 'DateTimeField',
  • django/db/backends/mysql/creation.py

     
    1818        'FilePathField':     'varchar(%(max_length)s)',
    1919        'FloatField':        'double precision',
    2020        'IntegerField':      'integer',
     21        'BigIntegerField':   'bigint',
    2122        'IPAddressField':    'char(15)',
    2223        'NullBooleanField':  'bool',
    2324        'OneToOneField':     'integer',
     
    6364                field.rel.to._meta.db_table, field.rel.to._meta.pk.column)
    6465            ]
    6566        return table_output, deferred
    66        
    67  No newline at end of file
     67       
  • django/db/backends/oracle/introspection.py

     
    2929    def get_field_type(self, data_type, description):
    3030        # If it's a NUMBER with scale == 0, consider it an IntegerField
    3131        if data_type == cx_Oracle.NUMBER and description[5] == 0:
    32             return 'IntegerField'
     32            if description[4] > 11:
     33                return 'BigIntegerField'
     34            else:
     35                return 'IntegerField'
    3336        else:
    3437            return super(DatabaseIntrospection, self).get_field_type(
    3538                data_type, description)
  • django/db/backends/oracle/creation.py

     
    2727        'FilePathField':                'NVARCHAR2(%(max_length)s)',
    2828        'FloatField':                   'DOUBLE PRECISION',
    2929        'IntegerField':                 'NUMBER(11)',
     30        'BigIntegerField':              'NUMBER(19)',
    3031        'IPAddressField':               'VARCHAR2(15)',
    3132        'NullBooleanField':             'NUMBER(1) CHECK ((%(qn_column)s IN (0,1)) OR (%(qn_column)s IS NULL))',
    3233        'OneToOneField':                'NUMBER(11)',
  • django/contrib/admin/options.py

     
    4242        'form_class': forms.SplitDateTimeField,
    4343        'widget': widgets.AdminSplitDateTime
    4444    },
    45     models.DateField:    {'widget': widgets.AdminDateWidget},
    46     models.TimeField:    {'widget': widgets.AdminTimeWidget},
    47     models.TextField:    {'widget': widgets.AdminTextareaWidget},
    48     models.URLField:     {'widget': widgets.AdminURLFieldWidget},
    49     models.IntegerField: {'widget': widgets.AdminIntegerFieldWidget},
    50     models.CharField:    {'widget': widgets.AdminTextInputWidget},
    51     models.ImageField:   {'widget': widgets.AdminFileWidget},
    52     models.FileField:    {'widget': widgets.AdminFileWidget},
     45    models.DateField:       {'widget': widgets.AdminDateWidget},
     46    models.TimeField:       {'widget': widgets.AdminTimeWidget},
     47    models.TextField:       {'widget': widgets.AdminTextareaWidget},
     48    models.URLField:        {'widget': widgets.AdminURLFieldWidget},
     49    models.IntegerField:    {'widget': widgets.AdminIntegerFieldWidget},
     50    models.BigIntegerField: {'widget': widgets.AdminIntegerFieldWidget},
     51    models.CharField:       {'widget': widgets.AdminTextInputWidget},
     52    models.ImageField:      {'widget': widgets.AdminFileWidget},
     53    models.FileField:       {'widget': widgets.AdminFileWidget},
    5354}
    5455
    5556
  • tests/regressiontests/model_fields/tests.py

     
    66from django.db import models
    77from django.core.exceptions import ValidationError
    88
    9 from models import Foo, Bar, Whiz, BigD, BigS, Image
     9from models import Foo, Bar, Whiz, BigD, BigS, Image, BigInt
    1010
    1111try:
    1212    from decimal import Decimal
     
    144144        bs = BigS.objects.create(s = 'slug'*50)
    145145        bs = BigS.objects.get(pk=bs.pk)
    146146        self.assertEqual(bs.s, 'slug'*50)
     147
     148class BigIntegerFieldTests(django.test.TestCase):
     149    def test_existence(self):
     150        self.assertEqual(len(BigInt.objects.all()), 0)
     151
     152    def test_limits(self):
     153        self.assertRaises(ValueError, BigInt(value = 9223372036854775809111111111111111111).save)
     154        self.assertRaises(ValueError, BigInt(value = -9223372036854775809111111111111111111).save)
     155        self.assertRaises(ValueError, BigInt(value = 9223372036854775808).save)
     156        self.assertRaises(ValueError, BigInt(value = -9223372036854775809).save)
     157        self.assertEqual(BigInt(value = -9223372036854775808).save(), None)
     158        self.assertEqual(BigInt(value = 9223372036854775807).save(), None)
     159        self.assertEqual(BigInt(value = 0).save(), None)
     160
     161    def test_types(self):
     162        b = BigInt(value = 0)
     163        self.assertTrue(isinstance(b.value, (int, long)))
     164        b.save()
     165        self.assertTrue(isinstance(b.value, (int, long)))
     166        b = BigInt.objects.all()[0]
     167        self.assertTrue(isinstance(b.value, (int, long)))
     168
     169    def test_coercing(self):
     170        b = BigInt(value = 10)
     171        b.save()
     172        self.assertEqual(b.value, 10)
     173        self.assertEqual(unicode(b), unicode(10))
     174
     175    def test_null(self):
     176        # this test needs to be run in one transaction, so null tests need to
     177        # be split
     178        try:
     179            # it raises different exceptions depending on backend
     180            BigInt(value = None).save()
     181            self.assertTrue(False, 'null saved in not null field')
     182        except:
     183            pass
     184
     185    def test_null2(self):
     186        BigInt(value = 1, null_value = 4).save()
     187        BigInt(value = 1, null_value = None).save()
  • tests/regressiontests/model_fields/models.py

     
    5151class BigS(models.Model):
    5252    s = models.SlugField(max_length=255)
    5353
     54class BigInt(models.Model):
     55    value = models.BigIntegerField()
     56    null_value = models.BigIntegerField(null = True, blank = True)
    5457
     58    def __unicode__(self):
     59        return unicode(self.value)
     60
    5561###############################################################################
    5662# ImageField
    5763
  • tests/regressiontests/introspection/tests.py

     
    7777        cursor = connection.cursor()
    7878        desc = connection.introspection.get_table_description(cursor, Reporter._meta.db_table)
    7979        self.assertEqual([datatype(r[1], r) for r in desc],
    80                           ['IntegerField', 'CharField', 'CharField', 'CharField'])
     80                          ['IntegerField', 'CharField', 'CharField', 'CharField', 'BigIntegerField'])
    8181
    8282    # Regression test for #9991 - 'real' types in postgres
    8383    if settings.DATABASE_ENGINE.startswith('postgresql'):
  • tests/regressiontests/introspection/models.py

     
    44    first_name = models.CharField(max_length=30)
    55    last_name = models.CharField(max_length=30)
    66    email = models.EmailField()
     7    facebook_user_id = models.BigIntegerField()
    78
    89    def __unicode__(self):
    910        return u"%s %s" % (self.first_name, self.last_name)
     
    1718        return self.headline
    1819
    1920    class Meta:
    20         ordering = ('headline',)
    21  No newline at end of file
     21        ordering = ('headline',)
  • docs/ref/models/fields.txt

     
    641641An integer. The admin represents this as an ``<input type="text">`` (a
    642642single-line input).
    643643
     644``bigintegerfield``
     645~~~~~~~~~~~~~~~~
     646
     647.. class:: BigIntegerField([**options])
     648
     649A big integer. The admin represents this as an ``<input type="text">``
     650(a single-line input).
     651
     652a 64 bit type like an ``integerfield``, except that it fits numbers from
     653-9223372036854775808 to 9223372036854775807
     654 
     655
    644656``IPAddressField``
    645657------------------
    646658
Back to Top