Python 如何通过字符串动态地恢复Django表单?
我正在尝试为Django编写一个应用程序。我希望我的用户能够收集某些类型的数据,例如样本、视频等。。。该应用程序称为收集器,每种类型的项目都有一个类和一个表单 示例类:Python 如何通过字符串动态地恢复Django表单?,python,django,forms,Python,Django,Forms,我正在尝试为Django编写一个应用程序。我希望我的用户能够收集某些类型的数据,例如样本、视频等。。。该应用程序称为收集器,每种类型的项目都有一个类和一个表单 示例类: class CreateTextView(CreateItemView): form_class = TextForm model = Text def get_context_data(self, **kwargs): context = super(CreateTextVie
class CreateTextView(CreateItemView):
form_class = TextForm
model = Text
def get_context_data(self, **kwargs):
context = super(CreateTextView, self).get_context_data(**kwargs)
context['item_type'] = 'text'
return context
示例表格:
class TextForm(forms.ModelForm):
class Meta:
model = Text
fields = COMMON_FIELDS + ('text',)
如您所见,实际视图继承自CreateItemView。我希望为CreateItemView定义尽可能多的功能,这样我就不必为所有的item类单独定义。这在很大程度上起到了作用,但当我试图用数据处理表单时,它变得有点棘手
def post(self, request, *args, **kwargs):
form = TextForm(request.POST) # line 2
form = getattr(TextForm, '__init__')(data=request.POST) # line 3
if form.is_valid():
# Add owner information.
item = form.save(commit=False)
item.owner = request.user
item.save()
return HttpResponseRedirect(reverse('collector:index'))
return render(request, self.template_name, {'form': form})
在第2行中,您可以看到如果只有一种表单类型,我将如何处理表单。第三行就是我要做的。我希望能够使用上下文['item_type']动态选择正确的表单,并用给定的数据实例化它
现在问题出在uu init uuu-方法上,我从未在任何地方定义过它。当我只将POST.request传递给_init__时,它抱怨没有自我。当我传递额外的self时,它会抱怨CreateTextView没有元属性等等。我就是找不到合适的参数组合来满足uuu init_uuuu-方法。我也找不到它的定义,因为我没有定义它。然后,我遵循django框架中父类的定义,这使我找到了两个看起来像工厂的复杂函数。这对我没什么帮助
现在我知道如何使用文本表单初始化。有没有一种方法可以使用getattr动态获取此方法?那会省去我的麻烦。如果没有,我如何为_init__提供正确的自我实例
正如下面提到的,我稍微改变了我的课程。我不再使用上下文来存储item_类型,而是使用class变量在视图中轻松访问item_类型。My post方法在母类CreateItemView中定义,现在如下所示:
def post(self, request, *args, **kwargs):
try:
form_cls = ITEM_TYPE_MAP[self.item_type]
except KeyError:
# invalid item_type. raise a meaningful error here
raise Exception('Invalid item type.')
form = form_cls(request.POST)
if form.is_valid():
# Add owner information.
item = form.save(commit=False)
item.owner = request.user
item.save()
return HttpResponseRedirect(reverse('collector:index'))
return render(request, self.template_name, {'form': form})
一个干净且非常简单的解决方案是使用字典将项类型值映射到实际的表单类:
ITEM_TYPE_MAP = {
"foo": TextForm,
"bar": SomeOtherForm,
}
您可以将该字典放在某个全局位置,并在控制器中使用它,如下所示:
item_type = context['item_type']
try:
form_cls = ITEM_TYPE_MAP[item_type]
except KeyError:
# invalid item_type. raise a meaningful error here
raise
form = form_cls(request.POST)
通常不能直接调用uuu init uuuu,因为实例化对象的方法不止这些。Python还将在对象的类上调用_new _uu,因此确保的唯一方法是通过实际的构造函数,该构造函数正在调用类型
这就是上面发生的事情,首先将类型提取到form_cls中,然后调用类型,即构造函数。感谢您给出了这个漂亮的答案。这正是我要找的。我不知道你刚才添加到变量的语法变体。我最初学习的语言比较保守,主要是Java。不过,我不再使用上下文。我刚刚在我的类中创建了一个名为item_type的成员变量,以便从类中轻松访问该类型。