Python:如何使用存储在变量中的值来决定要启动哪个类实例?

Con*_*ion 1 python django metaprogramming django-models django-forms

我正在构建一个Django站点.我需要模拟许多不同的产品类别,如电视,笔记本电脑,女士服装,男鞋等.

由于不同的产品类别具有不同的产品属性,因此每个类别都有自己独立的模型:TV, Laptop, WomensApparel, MensShoes,

对于每个模型,我创建了一个ModelForm.因此我有TVForm, LaptopForm, WomensApparelForm, MensShoesForm,等等

用户可以通过多级下拉框选择产品类别来输入产品详细信息.用户选择产品类别后,我需要显示相应的产品表单.

显而易见的方法是使用一个巨大的if-elif结构:

# category is the product category selected by the user

if category == "TV":
    form = TVForm()
elif category == "Laptop":
    form = LaptopForm()
elif category == "WomensApparel":
    form = WomensApparelForm()
...
Run Code Online (Sandbox Code Playgroud)

不幸的是,如果不是更多类别,可能会有数百个.因此,上述方法容易出错且繁琐.

有没有什么方法可以使用变量的值category直接选择和初始化适当的ModelForm而不诉诸巨大的if-elif声明?

就像是:

# This doesn't work

model_form_name = category + "Form"
form = model_form_name()
Run Code Online (Sandbox Code Playgroud)

有没有办法做到这一点?

Zoo*_*oba 10

如果你的所有*Form课程都在一个模块中(让我们称之为forms),你可以这样做:

import forms

form = getattr(forms, category + "Form")()
Run Code Online (Sandbox Code Playgroud)

(显然,添加任何必要的验证,例如捕获AttributeError.安全性方面,如果您使用的是命名模块而不是全局命名空间,那么有人注入新*Form类就更难了.)


Man*_*dan 9

一种简单的方法是维护类别名称字典以形成类.例如

categories_and_classes = dict(TV = TVForm, Laptop = LaptopForm, ...)
Run Code Online (Sandbox Code Playgroud)

然后您可以使用该类别来查找表单类:

form = categories_and_classes.get(category, DefaultForm)
Run Code Online (Sandbox Code Playgroud)

或者你可以使用约定,正如@Zooba在他的回答中所说.如果您的表单统一命名,这将起作用<category name> + Form.

  • +1,这是唯一理智的方式,允许不同的表单名称或两个类别等具有相同的形式 (2认同)