django自定义非主键自增字段类型(auto increment field)

来源:互联网 发布:php oa 开源 编辑:程序博客网 时间:2024/06/10 23:19

1.django自定义字段类型,实现非主键字段的自增

# -*- encoding: utf-8 -*-from django.db.models.fields import Field, IntegerFieldfrom django.core import checks, exceptionsfrom 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)
原创粉丝点击