在我的一个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个模型实例的自定义代码,它将保持这种程度。任何想法或模式如何以清晰,可读的方式实现?
感谢您的帮助。
答案 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)