微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

Django:如何创建类的枚举以定义选择

如何解决Django:如何创建类的枚举以定义选择

如何对模型进行子类化。选择定义类的枚举?

以下代码引发TypeError:

from django.db.models import Choices

class DataTypes(type,Choices):
    CHAR = str,_('Short string')
    INTEGER = int,_('Integer')

错误消息:

dynamic_attributes = {k for c in enum_class.mro()
TypeError: descriptor 'mro' of 'type' object needs an argument

更新:

不使用mixin时,不会出现错误。但是,同样的,成员的值不能正确转换为所需的数据类型。

class DataTypes(Choices):
    CHAR = str,_('Integer')

测试:

str in (DataTypes.CHAR,DataTypes.INTEGER) # False

解决方法

我在评论中同意威廉·范·昂森的观点。我认为无法将HTTP Server用于类等数据类型。因此,我试图找到一种可以扩展其他类的方法。

也实现了定义选项的标签(就像Django Choices一样)。

models.Choices

现在,您可以创建Choices类,也可以将其子类化:

def _is_dunder(name):
    """
    Stolen liberally from 'aenum'.

    Returns True if a __dunder__ name,False otherwise.
    """
    return (len(name) > 4 and
            name[:2] == name[-2:] == '__' and
            name[2] != '_' and
            name[-3] != '_')


class ChoicesMeta(type):

    def __new__(mcs,cls,bases,attrs):
        # ignore any keys listed in _ignore_
        ignore = attrs.setdefault('_ignore_',[])
        ignore.append('_ignore_')

        # save constant names into list.
        names = [k for k in attrs if not(_is_dunder(k) or k in ignore)]

        # save constant labels into list.
        labels = []
        for k in names:
            value = attrs[k]
            if (
                isinstance(value,(list,tuple)) and
                len(value) > 1 and
                isinstance(value[-1],(Promise,str))
            ):
                value,label = value
            else:
                label = k.replace('_',' ').title()
            labels.append(label)
            attrs[k] = value

        new_cls = super().__new__(mcs,attrs)
        new_cls.local_names = names
        new_cls.local_labels = labels
        return new_cls

    @property
    def names(cls):
        names = []
        for c in reversed(cls.__mro__):
            names.extend(getattr(c,'local_names',[]))
        return list(dict.fromkeys(names))

    @property
    def choices(cls):
        empty = [(None,cls.__empty__)] if hasattr(cls,'__empty__') else []
        return empty + [(getattr(cls,name),cls.labels[i]) for i,name in enumerate(cls.names)]

    @property
    def labels(cls):
        labels = []
        for c in reversed(cls.__mro__):
            labels.extend(getattr(c,'local_labels',[]))
        return list(dict.fromkeys(labels))


class Choices(metaclass=ChoicesMeta):
    pass

测试:

class DataTypes(Choices):
    CHAR = str,_('Short string')
    INTEGER = int


class OtherTypes(DataTypes):
    BOOLEAN = bool,_('Boolean (Either True or False)')
    FLOAT = float,_('Floating point number')

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。