django自定義非主鍵自增欄位型別(auto increment field)
阿新 • • 發佈:2019-02-03
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)