[Fixed]-Unsigned integer field in django

9๐Ÿ‘

As far as I know, the only unsigned integer fields in Django are PositiveIntegerField and PositiveSmallIntegerField which are both too small for you. Youโ€™ll probably have to look at a custom field to get what you want. Documentation for that is here. One thing that is really helpful when writing custom fields is to look at the code for one of the official django model fields. They can all be found at django/db/models/fields/__init__.py

I would post some code but I donโ€™t have enough experience with custom fields to be confident that it would be what you need. Good luck!`

๐Ÿ‘คjohnmic07

4๐Ÿ‘

Gave it a go in creating a custom UnsignedIntegerField. Tested only manually for inserting unsigned 32-bit integers.

from django.core import validators
from django.db import models
from django.utils.functional import cached_property


class UnsignedIntegerField(models.IntegerField):

    MAX_INT = 4294967295

    @cached_property
    def validators(self):
        # These validators can't be added at field initialization time since
        # they're based on values retrieved from `connection`.
        validators_ = [*self.default_validators, *self._validators]
        min_value, max_value = 0, self.MAX_INT
        if (min_value is not None and not
            any(isinstance(validator, validators.MinValueValidator) and
                validator.limit_value >= min_value for validator in validators_)):
            validators_.append(validators.MinValueValidator(min_value))
        if (max_value is not None and not
            any(isinstance(validator, validators.MaxValueValidator) and
                validator.limit_value <= max_value for validator in validators_)):
            validators_.append(validators.MaxValueValidator(max_value))
        return validators_

    def db_type(self, connection):
        return "INTEGER UNSIGNED"

    def get_internal_type(self):
        return "UnsignedIntegerField"

    def formfield(self, **kwargs):
        return super().formfield(**{
            'min_value': 0,
            'max_value': self.MAX_INT,
            **kwargs,
        })
๐Ÿ‘คkodemartin

3๐Ÿ‘

As of Django 2.2, there is official documentation on how to create custom fields. The best part is, now they have an example of creating UnsignedAutoField right here. For my use case with Django 2.0, this snippet was sufficient.

from django.db.models.fields import AutoField

class UnsignedAutoField(AutoField):
    def db_type(self, connection):
        return 'integer UNSIGNED AUTO_INCREMENT'

    def rel_db_type(self, connection):
        return 'integer UNSIGNED'

Hope this helps.

๐Ÿ‘คArvind

Leave a comment