tl;dr:我正在寻找一种将模型的表单与给定模型相关联的简单方法,以便仅知道模型我可以呈现适当的创建/编辑表单。我已经开发了一个解决方案,将相应ModelForm
的名称作为字符串属性存储在 Model 类上,但是对于 django 来说是新手,我很好奇这是否是首选解决方案。
我正在开发 django 任务/项目管理站点,该站点将为许多产品组存储任务。导航到mysite/<ProductGroup>/create_task.html
应该将用户引导到用于在该产品组中创建任务/项目的表单。默认情况下,这将允许Task
使用简单的ModelForm
. 但是,对于特定的产品组,我希望可以选择对Task
模型进行子类化(示例SalesTask
)并显示ModeForm
该子类的特定内容(例如SalesTaskForm
)。
我目前的解决方案是将任务对象类型作为内容类型存储在ProductGroup
模型中,例如:
class ProductGroup(models.Model):
task_type = models.ForeignKey(ContentType)
...
<define other fields here>
然后定义一个带有特殊字符串属性的基本任务模型,给出ModelForm
渲染时使用的对应属性,例如:
<models.py>
class Task(models.Model):
product_group = models.ForeignKey(ProductGroup)
...
<define task fields common to all Task subclasses>
...
# Associate model with a form (regular python class attribute,
# not a django field)
form = 'TaskForm'
<forms.py>
class TaskForm(ModelForm):
class Meta:
model = Task
*Note that it would be slightly more convenient if I could set Task.form equal
to the actual TaskForm(ModelForm) class rather than a string, but I couldn't
get around the circular imports when trying this route (models.py `Task`
would need to import `Taskorm` from forms.py, which itself needs to import
`Task`).*
Task
此设置允许我通过简单地继承和TaskForm
覆盖Task.form
模型子类定义(例如SalesTask.form = 'SalesTaskForm'
)上的属性,然后为 的销售实例设置 task_type 外键,轻松扩展给定产品组的任务模型ProductGroup
。
然后,生成的create_task
视图函数可以智能地为给定的产品组呈现适当的表单:
<views.py>
...
import mysite.forms as taskforms
...
def create_task(request, name):
try:
product_group = ProductGroup.object.get(product_group_iexact=name)
except ProductGroup.DoesNotExist:
raise Http404
if request.method == 'POST':
task_model = product_group.item_type.model_class()
try:
form = taskforms.__getattribute__(task_model.form)
except AttributeError:
raise Http404
if form.is_valid():
# Process form
...
这似乎可行,我对解决方案并不不满,但将表单与给定模型相关联似乎是一种常见的需求——对 django 来说相对较新——我想知道是否有内置或更雄辩的方法来处理这个?
提前致谢。