python - 根据 Django 模型中的字段值选择方法

标签 python django python-3.x polymorphism

总的来说,我有一个 Django 模型,我希望实例根据其字段之一的值具有不同的行为:

ANIMAL_TYPES = ('cow', 'african swallow', 'dog')
ANIMAL_TYPE_CHOICES = tuple(enumerate(ANIMALS, start=1))

class Animal(models.Model):
    animal_type = models.PositiveIntegerField(choices=ANIMAL_TYPE_CHOICES)
    # ... other model fields

    def speak_cow(self):
        return 'moo'

    def speak_african_swallow(self):
        return 'squawk'

    def speak_dog(self):
        return 'woof'

    choose_speak = {i: getattr(Animal,'speak_{}'.format(
             name.replace(' ', '_'))) for (i, name) in ANIMAL_TYPE_CHOICES}

    def speak(self):
        return Animal.speak[self.animal_type](self)

目标是能够在 Animal 实例上调用 speak() 并让类选择正确的 speak 方法。 (需要明确的是:speak 方法不仅仅返回一个字符串。)

这不起作用:当我在 choose_speak 的字典理解中使用它时,Animal 尚未定义。目前,我的解决方法是使用

choose_speak = [None, speak_cow, speak_african_swallow, speak_dog]

但是有没有办法自动生成我想要的内容,这样我就不必手动添加任何我定义的新方法(例如 speak_sheep)?

最佳答案

您还可以定义一个包含所有动物声音的列表......即

 ANIMAL_SOUNDS = ['moo', 'squawk'..]

这样您就不必定义新方法。 在说话中使用它,例如:

def speak(self):
    return ANIMAL_SOUNDS[self.animal_type]

编辑:

只是为了它,我玩了一下,并用纯Python想出了这段代码,它可能接近你想要的:

ANIMAL_TYPES = ('cow', 'african swallow', 'dog')
ANIMAL_TYPE_CHOICES = tuple(enumerate(ANIMAL_TYPES, start=1))

class Animal(object):

    def __init__(self, *args, **kwargs):
        self.choose_speak = {i: getattr(self, 'speak_{}'.format(
            name.replace(' ', '_'))) for (i, name) in ANIMAL_TYPE_CHOICES}

    animal_type = 1

    def speak_cow(self):
        return 'moo'

    def speak_african_swallow(self):
        return 'squawk'

    def speak_dog(self):
        return 'woof'

    def speak(self):
        return self.choose_speak[self.animal_type]()

animal = Animal()
animal.speak()

注意:覆盖模型的 __init__ 不是 Django 最佳实践,如图所示 here :

关于python - 根据 Django 模型中的字段值选择方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32284209/

相关文章:

python - django:必填字段在 HTML 中没有 "required"属性

python - Panda 重采样功能不适用于 'MS' 频率

python - 获取具有最大置信度的边界框 pandas opencv python

python - 如何为 PyPI 组织 Python 模块以支持 2.x 和 3.x

python - 将目录更改为 Python 脚本的目录

python - 如何在 Python 中构造具有多个特征的元素

python - Python 3.2 上的 PDF 生成

python - 交换原始文件的颜色 channel (BGGR -> RGGB)

django - 在 django admin 上编辑实际对象之前保存相关对象

Django 1.11 - 基于其他表排除的查询