Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Django BigInteger auto-increment field as primary key?

I'm currently building a project which involves a lot of collective intelligence. Every user visiting the web site gets created a unique profile and their data is later used to calculate best matches for themselves and other users.

By default, Django creates an INT(11) id field to handle models primary keys. I'm concerned with this being overflown very quickly (i.e. ~2.4b devices visiting the page without prior cookie set up). How can I change it to be represented as BIGINT in MySQL and long() inside Django itself?

I've found I could do the following (http://docs.djangoproject.com/en/dev/ref/models/fields/#bigintegerfield):

class MyProfile(models.Model):     id = BigIntegerField(primary_key=True) 

But is there a way to make it autoincrement, like usual id fields? Additionally, can I make it unsigned so that I get more space to fill in?

Thanks!

like image 984
letoosh Avatar asked Apr 20 '10 06:04

letoosh


People also ask

Does Django automatically create primary key?

If you don't specify primary_key=True for any fields in your model, Django will automatically add an IntegerField to hold the primary key, so you don't need to set primary_key=True on any of your fields unless you want to override the default primary-key behavior. For more, see Automatic primary key fields.

Can we update primary key in Django?

The primary key field is read-only. If you change the value of the primary key on an existing object and then save it, a new object will be created alongside the old one.

Does Django support multiple column primary keys?

Do Django models support multiple-column primary keys? ¶ No. Only single-column primary keys are supported.

Does Django auto generate ID?

Thus, an id AutoField that auto increments on every instance of that model is created by default when you run makemigrations on the project.


2 Answers

Django now has a BigAutoField built in if you are using Django 1.10:

https://docs.djangoproject.com/en/1.10/ref/models/fields/#bigautofield

like image 92
Garry Polley Avatar answered Sep 20 '22 11:09

Garry Polley


Inspired by lfagundes but with a small but important correction:

class BigAutoField(fields.AutoField):     def db_type(self, connection):  # pylint: disable=W0621         if 'mysql' in connection.__class__.__module__:             return 'bigint AUTO_INCREMENT'         return super(BigAutoField, self).db_type(connection)  add_introspection_rules([], [r"^a\.b\.c\.BigAutoField"]) 

Notice instead of extending BigIntegerField, I am extending AutoField. This is an important distinction. With AutoField, Django will retrieve the AUTO INCREMENTed id from the database, whereas BigInteger will not.

One concern when changing from BigIntegerField to AutoField was the casting of the data to an int in AutoField.

Notice from Django's AutoField:

def to_python(self, value):     if value is None:         return value     try:         return int(value)     except (TypeError, ValueError):         msg = self.error_messages['invalid'] % str(value)         raise exceptions.ValidationError(msg) 

and

def get_prep_value(self, value):     if value is None:         return None     return int(value) 

It turns out this is OK, as verified in a python shell:

>>> l2 = 99999999999999999999999999999 >>> type(l2) <type 'long'> >>> int(l2) 99999999999999999999999999999L >>> type(l2) <type 'long'> >>> type(int(l2)) <type 'long'> 

In other words, casting to an int will not truncate the number, nor will it change the underlying type.

like image 36
Larry Avatar answered Sep 20 '22 11:09

Larry