Django模型实例特定代码

时间:2010-10-20 08:16:53

标签: python django django-models

在我的一个Django模型中,我必须为每个模型实例添加特定代码。现在,我想知道实现这一目标的好方法。我目前的尝试导致了一个很难读的if语句。

考虑以下模型:

class Foo(models.Model):
    name = models.CharField(max_length=255)

    def do_instance_specific_stuff(self, arg):
        if self.id == 1:
            do_X(arg)
        elif self.id == 2:
            do_Y(arg)
        else:
            do_Z()

现在,有大约20个模型实例的自定义代码,它将保持这种程度。任何想法或模式如何以清晰,可读的方式实现?

感谢您的帮助。

2 个答案:

答案 0 :(得分:3)

我会在您的模型中添加另一个字段vendor。然后将每个供应商方法添加到模型中,并使用getattr:

调用它们
class Foo(models.Model):
    name = models.CharField(max_length=255)
    vendor = models.CharField(max_length=50)

    def vendor_fedex(self, arg):
        blah blah

    def vendor_ups(self, arg):
        blah blah

    def vendor_usps(self, arg):
        blah blah

    def do_instance_specific_stuff(self, arg):
        fn = getattr(self, "vendor_"+self.vendor, None)
        if not fn:
            raise Exception("Uh-oh, bad vendor")
        fn(arg)

取决于id的特定值,似乎非常脆弱。在您的数据模型中,每个供应商字符串只会出现一次,但它具有可读性和可塑性。如果getattr找不到供应商代码,您可以决定要执行的操作。

答案 1 :(得分:1)

常见的模式是使用dict

stuff_per_id = {1 : do_X, 2 : do_Y, ...}
def do_instance_specific_stuff(arg):
    try:
        stuff_per_id[self.id](arg)
    except KeyError:
        do_Z()

虽然你真的不应该这样做。在模型中添加一个额外字段会更好,这表示应该在arg上为此实例运行代码。然后dict模式可能仍然有用。

修改:如果您的任何特定于实例的功能可能会引发KeyError,则上述执行do_Z。如果您不想这样做,请将未使用的参数添加到do_Z并使用以下内容:

def do_instance_specific_stuff(arg):
    try:
        f = stuff_per_id[self.id]
    except KeyError:
        f = do_Z
    f(arg)