1. 程式人生 > >django自定義非主鍵自增欄位型別(auto increment field)

django自定義非主鍵自增欄位型別(auto increment field)

1.django自定義欄位型別,實現非主鍵欄位的自增

# -*- encoding: utf-8 -*-

from django.db.models.fields import Field, IntegerField
from django.core import checks, exceptions
from django.utils.translation import ugettext_lazy as _


class AutoIncreField(Field):
    description = _("Integer")

    empty_strings_allowed = False
default_error_messages = { 'invalid': _("'%(value)s' value must be an integer."), } def __init__(self, *args, **kwargs): kwargs['blank'] = True super(AutoIncreField, self).__init__(*args, **kwargs) def check(self, **kwargs): errors = super(AutoIncreField, self).check(**kwargs) # 每張表只能設定一個欄位為自增長欄位,這個欄位可以是主鍵,也可以不是主鍵,如果不是主鍵,則必須設定為一種“鍵(key)”
# (primary key)也是鍵(key)的一種,key還包括外來鍵(foreign key)、唯一鍵(unique key) errors.extend(self._check_key()) return errors def _check_key(self): if not self.unique: return [ checks.Error( 'AutoIncreFields must set key(unique=True).'
, obj=self, id='fields.E100', ), ] else: return [] def deconstruct(self): name, path, args, kwargs = super(AutoIncreField, self).deconstruct() del kwargs['blank'] kwargs['unique'] = True return name, path, args, kwargs def get_internal_type(self): return "AutoIncreField" def to_python(self, value): if value is None: return value try: return int(value) except (TypeError, ValueError): raise exceptions.ValidationError( self.error_messages['invalid'], code='invalid', params={'value': value}, ) def db_type(self, connection): return 'bigint AUTO_INCREMENT' def rel_db_type(self, connection): return IntegerField().db_type(connection=connection) def validate(self, value, model_instance): pass def get_db_prep_value(self, value, connection, prepared=False): if not prepared: value = self.get_prep_value(value) value = connection.ops.validate_autopk_value(value) return value def get_prep_value(self, value): value = super(AutoIncreField, self).get_prep_value(value) if value is None: return None return int(value) def contribute_to_class(self, cls, name, **kwargs): assert not cls._meta.auto_field, "A model can't have more than one AutoIncreField." super(AutoIncreField, self).contribute_to_class(cls, name, **kwargs) cls._meta.auto_field = self def formfield(self, **kwargs): return None

2.使用

class Test(models.Model):

    id = models.UUIDField(primary_key=True, default=uuid4)
    numbering = AutoIncreField(_(u'numbering'), unique=True)
    name = models.CharField(_(u'name'), max_length=32, blank=True, null=True)

3.bug

當save()後並不能重新整理instance,及save後numbering會為空值,需要重寫get一次.
如果您修復了這個問題請留言回覆下,謝謝

4.bug修復

以一種非常不優雅的方法進行了簡單修復,重寫了模型的save方法,在save後從新get

class AutoIncreFieldFixMinxin(object):
    def save(self, *args, **kwargs):
        super(AutoIncreFieldFixMinxin, self).save(*args, **kwargs)
        auto_field = self._meta.auto_field.name
        new_obj = self.__class__.objects.get(pk=self.pk)
        setattr(self, auto_field, int(getattr(new_obj, auto_field)))


class Test(AutoIncreFieldFixMinxin, models.Model):
    id = models.UUIDField(primary_key=True, default=uuid4)
    sequence = AutoIncreField(_(u'sequence'), unique=True)
    name = models.CharField(_(u'name'), max_length=100)