zoukankan      html  css  js  c++  java
  • 114.django复制模型对象和自定义字段

    1.复制模型对象

    产生原因:项目增加某部分表数据的复制功能,但是很难受由于项目是初始阶段,表中字段一直变化,通过对象复制操作
    每次增加一些字段我就需要改代码,特别烦人,所以产生了这个东西.
    
    代码如下很简单:
    from django.db.models import AutoField, DateTimeField
    from PublicMethod.CustomDjangoModelFiled import AutoIncreField   # 这个字段是我自定义的一个自增类型字段(google可以找到)
    def copy_object(obj):
        """
        拷贝模型对象对象,并排除exclude中的字段,返回一个新的对象
        :param obj 表示要copy的对象
        :param exclude 表示哪些字段排除之外
        :return 返回一个新的对象
        """
        # 关于其中排除字段的原因AutoField和AutoIncreField由于是自增字段所以该字段对应的值不应该复制过来,
    DateTimeField字段也是auto_now=True所以排除掉
        initial = dict([(f.name, getattr(obj, f.name))for f in obj._meta.fields
                        if not (isinstance(f, AutoField) or isinstance(f, DateTimeField) or isinstance(f, AutoIncreField))
                        and not f in obj._meta.parents.values()])
        return obj.__class__(**initial)
    

    2.自定义自增字段

    产生原因:我们的项目我来公司之前的表没有设置id字段,使用Char类型的字段当做主键的,但是后期项目需要我给所有的表添加自增的id
    字段,但是如果你在django里面使用AutoField那么primary_key=True是必须的,而现在我只需要一个自增的主键id,所以通过google和
    看AutoField的源码拼出来了一个新字段.
    
    建议:每个表设置主键id字段或者一个唯一的字段,此字段建议不要出现中文(项目中使用了的基本后期全部改掉了,所以不要尝试)使用自
    增字段或者使用uuid(推荐使用:因为是根据时间戳生成的所以基本不存在重复性问题),同时建议加上updated_time以及created_time
    字段方便后期查询过滤使用如下即可(推荐使用继承方式将下面三个字段写入父类中,通过其他模型继承,某写表不需要是可以不继承,同时
    建议将id字段和时间字段分开两个父类):
        id = models.AutoField(primary_key=True, verbose_name="ID")
        update_time = models.DateTimeField(auto_now=True, verbose_name="更新时间")
        create_time = models.DateTimeField(auto_now_add=True, verbose_name="创建时间")
    
    
    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):
        def __init__(self, *args, **kwargs):
            kwargs["blank"] = True
            super(AutoIncreField, self).__init__(*args, **kwargs)
            
        empty_strings_allowed = False
        default_error_messages = {
            'invalid': _('“%(value)s” value must be an integer.'),
        }
        description = _("Integer")
    
        def check(self, **kwargs):
            return [
                *super().check(**kwargs),
                *self._check_key(),
            ]
    
        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 validate(self, value, model_instance):
            pass
    
        def get_prep_value(self, value):
            value = super().get_prep_value(value)
            if value is None:
                return None
            try:
                return int(value)
            except (TypeError, ValueError) as e:
                raise e.__class__(
                    "Field '%s' expected a number but got %r." % (self.name, value),
                ) from e
    
        def deconstruct(self):
            name, path, args, kwargs = super().deconstruct()
            del kwargs['blank']
            kwargs['unique'] = True
            return name, path, args, kwargs
    
        def get_internal_type(self):
            # return "AutoIncreField"  # 请注意这里,不要随便起名字,这个就是我自己起的,但是迁移的时候这个字段迁移不到数据库中,
            # 你创建的字段类型和已经存在的哪个相似,就写那个比如我的和AutoField类似,就写这个,否则找不到错误在哪里除非你自己看源码
            return "AutoField"
    
        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 rel_db_type(self, connection):
            return IntegerField().db_type(connection=connection)
    
        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 contribute_to_class(self, cls, name, **kwargs):
            assert not cls._meta.auto_field, (
                "Model %s can't have more than one auto-generated field."
                % cls._meta.label
            )
            super().contribute_to_class(cls, name, **kwargs)
            cls._meta.auto_field = self
    
        def formfield(self, **kwargs):
            return None
    
  • 相关阅读:
    java基础学习总结——面向对象1
    java基础学习总结——基础语法2
    java基础学习总结——基础语法1
    java基础学习总结——开篇
    java基础学习总结——java环境变量配置
    Java基础加强总结(二)——泛型
    Java基础加强总结(一)——注解(Annotation)
    Web开发中设置快捷键来增强用户体验
    SQLServer2005中的CTE递归查询得到一棵树
    Jquery操作table
  • 原文地址:https://www.cnblogs.com/liuzhanghao/p/14028576.html
Copyright © 2011-2022 走看看