4

It seems that the default primary key is int. Is there anyway to use the big integer for the autofield as the primary key?

karlcow
  • 6,977
  • 4
  • 38
  • 72
zs2020
  • 53,766
  • 29
  • 154
  • 219
  • 3
    I really can't believe Django even doesn't support BigInteger primary key inherently , how can it compete with other frameworks?? I think I should just use UUID even it is not quite suitable for my situation. – zs2020 Feb 21 '11 at 21:56
  • possible duplicate of [Django BigInteger auto-increment field as primary key?](http://stackoverflow.com/questions/2672975/django-biginteger-auto-increment-field-as-primary-key) – Mp0int Jan 17 '14 at 09:54

8 Answers8

4

I would suggest you use a newer Django. Official Django documentation doesn't go farther back than 1.3 now. And 1.3 is insecure and unsupported. I realize the question was asked over 3 years ago, but since there is still no accepted answer I will give it a shot.

In Django 1.6.5 you can just do this in your model:

class MyModel(models.Model):
    id = models.BigIntegerField(unique=True, primary_key=True)

The primary_key=True will override the default id on the model. In use this field auto increments with each new model object. It just works!

e.thompsy
  • 1,297
  • 1
  • 15
  • 19
2

Since Django 1.10 you can use BigAutoField as described on documentation works exactly as AutoField but it is guaranteed to fit numbers from 1 to 9223372036854775807.

So you can use it like:

class SomeModel(models.Model):
    id = models.BigAutoField()
    ...
Henoc Díaz
  • 43
  • 1
  • 8
2

There are a couple of ways I can see to implement this. Either way, you have to define your pk field.

First of all, just create your own id field and override the save method.

modelname(models.Model):
    # model definition

def save(self):
    self.pkfield = nextIntFucntion()
    super(modelname, self).save()

The nextIntFunction() is easy enough with a query of objects ordered by id, then get the id+1

I also found this link BigIntegerField and BigAutoField which seems to solve the problem, but I have not tested it myself

Rod
  • 52,748
  • 3
  • 38
  • 55
neolaser
  • 6,722
  • 18
  • 57
  • 90
  • South will migrate properly. It wont work if you are manually entering data to the database (or external to django) – neolaser Feb 08 '11 at 06:02
  • The nextIntFunction() is easy enough with a query of objects ordered by id, then get the id+1...how can you guarantee uniqueness if more than one reader increment it by one at the same time? – zs2020 Feb 11 '11 at 05:16
  • hmm, good question. Since the nextInt will conly be calculated on the save, the chances are pretty slim...but still here. An extension of the idea, you could keep a 'BigIntReference' Table... – neolaser Feb 11 '11 at 05:24
  • ...or maybe Django enforces a lock when it saves...not sure. More research will be needed to clarify – neolaser Feb 11 '11 at 05:25
  • Django does NOT enforce a lock when it saves (at least not in 1.6). This is a race condition waiting to fail. Not to mention that if you have enough of this model to require a bigint key, you're likely saving them pretty quickly, which only increases the likelihood of hitting that condition. On the other hand, since it's a primary key, the integrity will be enforced by the database, so you can just put your super call in a loop. – DylanYoung Jul 29 '16 at 19:13
2

I met the same question too. I have add some code like

User._meta.has_auto_field = True
User._meta.auto_field = id

And I define the id field to BigIntegerField(primary_key=True) After I use user.Save(), user.id will have its id, don't need I query again. I think it works, but it is not a beautiful solution, so I still finding a good way.

ZhouQi
  • 531
  • 1
  • 6
  • 16
1

http://docs.djangoproject.com/en/dev/topics/db/models/

class BigIntegerField([**options])

available option is :

primary_key If True, this field is the primary key for the model.

And after all you do a south migration: ALTER TABLE mytable MODIFY COLUMN myid BIGINT(20) NOT NULL AUTO_INCREMENT;

1

You can hack Django and change the default auto-keys to the right values. Check out:

http://code.djangoproject.com/browser/django/trunk/django/db/backends/mysql/creation.py

from django.conf import settings
from django.db.backends.creation import BaseDatabaseCreation

class DatabaseCreation(BaseDatabaseCreation):
    # This dictionary maps Field objects to their associated MySQL column
    # types, as strings. Column-type strings can contain format strings; they'll
    # be interpolated against the values of Field.__dict__ before being output.
    # If a column type is set to None, it won't be included in the output.
    data_types = {
        'AutoField':         'integer AUTO_INCREMENT',
        'BooleanField':      'bool',
        'CharField':         'varchar(%(max_length)s)',

You can modify this using a patch in your own code:

DatabaseCreation.data_types['AutoField'] = 'bigint AUTO_INCREMENT'

You will also have to patch the AutoField class:

http://code.djangoproject.com/browser/django/trunk/django/db/models/fields/__init__.py

(untested code, good luck)

Dimitry
  • 6,545
  • 2
  • 20
  • 21
  • Hacking a framework is never a good idea. It's always better to extend it. – shangxiao Nov 06 '14 at 14:27
  • The same could be done by just creating an AutoBigIntField, subclass Model to use it for it's default pk and register it with the appropriate data type in the backend. – DylanYoung Jul 29 '16 at 19:18
0

These snippets work. Use the BigAutoField class as your primary key on your model and it works seemlessly without any hacking.

notbad.jpeg
  • 3,308
  • 1
  • 32
  • 37
0

You are right, sorry. The neccessary snippet is here:

http://djangosnippets.org/snippets/1244/

Allows to create bigint (mysql), bigserial (psql), or NUMBER(19) (oracle) fields which have auto-increment set by using the AutoField of django, therefore ensuring that the ID gets updated in the instance when calling its 'save()' method.

If you would only subclass IntegerField to BigIntegerField and use that as your primary key, your model instance you create would not get the id attribute set when calling 'save()', buy instead you would have to query and load the instance from the DB again to get the ID.