Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP

Bigint AutoField (fixes #56, #13774) #62

Closed
wants to merge 1 commit into from

2 participants

Pavel Zinovkin Anssi Kääriäinen
Pavel Zinovkin

Alternative approach to fix ticket 56.
Based on discussion #49
This approach doesn't change AutoField behavior. Only those who need extended int range may use it.
It keeps values ranges consistent between databases. Also it works nice with related fields.

Anssi Kääriäinen
Owner

To me it seems this needs some tests, mainly one for checking that the foreign key to a bigautofield is created properly as bigint. As per the policy of "commit or close when reviewing" I am closing this pull request.

Anssi Kääriäinen akaariai closed this July 16, 2012
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Showing 1 unique commit by 1 author.

May 13, 2012
Pavel Zinovkin Bigint AutoField e5bfaca
This page is out of date. Refresh to see the latest.
3  django/db/backends/__init__.py
@@ -847,7 +847,8 @@ def convert_values(self, value, field):
847 847
         internal_type = field.get_internal_type()
848 848
         if internal_type == 'DecimalField':
849 849
             return value
850  
-        elif internal_type and internal_type.endswith('IntegerField') or internal_type == 'AutoField':
  850
+        elif (internal_type and internal_type.endswith('IntegerField')
  851
+                or internal_type.endswith('AutoField')):
851 852
             return int(value)
852 853
         elif internal_type in ('DateField', 'DateTimeField', 'TimeField'):
853 854
             return value
1  django/db/backends/mysql/creation.py
@@ -6,6 +6,7 @@ class DatabaseCreation(BaseDatabaseCreation):
6 6
     # be interpolated against the values of Field.__dict__ before being output.
7 7
     # If a column type is set to None, it won't be included in the output.
8 8
     data_types = {
  9
+        'BigAutoField':      'bigint AUTO_INCREMENT',
9 10
         'AutoField':         'integer AUTO_INCREMENT',
10 11
         'BooleanField':      'bool',
11 12
         'CharField':         'varchar(%(max_length)s)',
1  django/db/backends/oracle/creation.py
@@ -15,6 +15,7 @@ class DatabaseCreation(BaseDatabaseCreation):
15 15
     # output (the "qn_" prefix is stripped before the lookup is performed.
16 16
 
17 17
     data_types = {
  18
+        'BigAutoField':                 'NUMBER(19)',
18 19
         'AutoField':                    'NUMBER(11)',
19 20
         'BooleanField':                 'NUMBER(1) CHECK (%(qn_column)s IN (0,1))',
20 21
         'CharField':                    'NVARCHAR2(%(max_length)s)',
1  django/db/backends/postgresql_psycopg2/creation.py
@@ -10,6 +10,7 @@ class DatabaseCreation(BaseDatabaseCreation):
10 10
     # be interpolated against the values of Field.__dict__ before being output.
11 11
     # If a column type is set to None, it won't be included in the output.
12 12
     data_types = {
  13
+        'BigAutoField':      'bigserial',
13 14
         'AutoField':         'serial',
14 15
         'BooleanField':      'boolean',
15 16
         'CharField':         'varchar(%(max_length)s)',
3  django/db/backends/sqlite3/base.py
@@ -191,7 +191,8 @@ def convert_values(self, value, field):
191 191
         internal_type = field.get_internal_type()
192 192
         if internal_type == 'DecimalField':
193 193
             return util.typecast_decimal(field.format_number(value))
194  
-        elif internal_type and internal_type.endswith('IntegerField') or internal_type == 'AutoField':
  194
+        elif (internal_type and internal_type.endswith('IntegerField')
  195
+                or internal_type.endswith('AutoField')):
195 196
             return int(value)
196 197
         elif internal_type == 'DateField':
197 198
             return parse_date(value)
1  django/db/backends/sqlite3/creation.py
@@ -7,6 +7,7 @@ class DatabaseCreation(BaseDatabaseCreation):
7 7
     # thing" given more verbose field definitions, so leave them as is so that
8 8
     # schema inspection is more useful.
9 9
     data_types = {
  10
+        'BigAutoField':                 'integer',
10 11
         'AutoField':                    'integer',
11 12
         'BooleanField':                 'bool',
12 13
         'CharField':                    'varchar(%(max_length)s)',
42  django/db/models/fields/__init__.py
@@ -205,6 +205,13 @@ def clean(self, value, model_instance):
205 205
         self.run_validators(value)
206 206
         return value
207 207
 
  208
+    def _internal_to_db_type(self, internal_type, connection):
  209
+        data = DictWrapper(self.__dict__, connection.ops.quote_name, "qn_")
  210
+        try:
  211
+            return connection.creation.data_types[internal_type] % data
  212
+        except KeyError:
  213
+            return None
  214
+
208 215
     def db_type(self, connection):
209 216
         """
210 217
         Returns the database column data type for this field, for the provided
@@ -225,12 +232,14 @@ def db_type(self, connection):
225 232
         # mapped to one of the built-in Django field types. In this case, you
226 233
         # can implement db_type() instead of get_internal_type() to specify
227 234
         # exactly which wacky database column type you want to use.
228  
-        data = DictWrapper(self.__dict__, connection.ops.quote_name, "qn_")
229  
-        try:
230  
-            return (connection.creation.data_types[self.get_internal_type()]
231  
-                    % data)
232  
-        except KeyError:
233  
-            return None
  235
+        return self._internal_to_db_type(self.get_internal_type(), connection)
  236
+
  237
+    def rel_db_type(self, connection):
  238
+        """
  239
+        Returns the database column data type for related field referencing
  240
+        to this.
  241
+        """
  242
+        return self.db_type(connection)
234 243
 
235 244
     @property
236 245
     def unique(self):
@@ -514,14 +523,19 @@ class AutoField(Field):
514 523
         'invalid': _(u"'%s' value must be an integer."),
515 524
     }
516 525
 
517  
-    def __init__(self, *args, **kwargs):
  526
+    def __init__(self, verbose_name=None, name=None, big=False, **kwargs):
518 527
         assert kwargs.get('primary_key', False) is True, \
519 528
                "%ss must have primary_key=True." % self.__class__.__name__
520 529
         kwargs['blank'] = True
521  
-        Field.__init__(self, *args, **kwargs)
  530
+        self.big = big
  531
+        Field.__init__(self, verbose_name, name, **kwargs)
522 532
 
523 533
     def get_internal_type(self):
524  
-        return "AutoField"
  534
+        return 'AutoField' if not self.big else 'BigAutoField'
  535
+
  536
+    def rel_db_type(self, connection):
  537
+        db_type = 'IntegerField' if not self.big else 'BigIntegerField'
  538
+        return self._internal_to_db_type(db_type, connection)
525 539
 
526 540
     def to_python(self, value):
527 541
         if value is None:
@@ -1139,6 +1153,11 @@ class PositiveIntegerField(IntegerField):
1139 1153
     def get_internal_type(self):
1140 1154
         return "PositiveIntegerField"
1141 1155
 
  1156
+    def rel_db_type(self, connection):
  1157
+        if connection.features.related_fields_match_type:
  1158
+            return self.db_type(connection)
  1159
+        return self._internal_to_db_type('IntegerField', connection)
  1160
+
1142 1161
     def formfield(self, **kwargs):
1143 1162
         defaults = {'min_value': 0}
1144 1163
         defaults.update(kwargs)
@@ -1150,6 +1169,11 @@ class PositiveSmallIntegerField(IntegerField):
1150 1169
     def get_internal_type(self):
1151 1170
         return "PositiveSmallIntegerField"
1152 1171
 
  1172
+    def rel_db_type(self, connection):
  1173
+        if connection.features.related_fields_match_type:
  1174
+            return self.db_type(connection)
  1175
+        return self._internal_to_db_type('IntegerField', connection)
  1176
+
1153 1177
     def formfield(self, **kwargs):
1154 1178
         defaults = {'min_value': 0}
1155 1179
         defaults.update(kwargs)
13  django/db/models/fields/related.py
@@ -1018,19 +1018,8 @@ def formfield(self, **kwargs):
11  docs/ref/models/fields.txt
@@ -320,13 +320,22 @@ Field types
320 320
 ``AutoField``
321 321
 -------------
322 322
 
323  
-.. class:: AutoField(**options)
  323
+.. class:: AutoField([big=False, **options])
324 324
 
325 325
 An :class:`IntegerField` that automatically increments
326 326
 according to available IDs. You usually won't need to use this directly; a
327 327
 primary key field will automatically be added to your model if you don't specify
328 328
 otherwise. See :ref:`automatic-primary-key-fields`.
329 329
 
  330
+.. attribute:: AutoField.big
  331
+
  332
+    .. versionadded:: 1.5
  333
+
  334
+    Optional.  Either ``False`` or ``True``.  Default is ``False``. Allow you
  335
+    to use bigint for storing field values. This extends values range up to
  336
+    max 64 bit integer (from 1 to 9223372036854775807).
  337
+
  338
+
330 339
 ``BigIntegerField``
331 340
 -------------------
332 341
 
Commit_comment_tip

Tip: You can add notes to lines in a file. Hover to the left of a line to make a note

Something went wrong with that request. Please try again.