从对象字典创建Django表单
我觉得这应该很简单,但经过几天的尝试,我完全搞不懂了。
我有一个字典,字典的键是一些对象,而值是这些对象对应的对象列表。接下来,我想用这些信息来构建一个表单:
for object in dictionary:
name_of_field = object.slug
name_of_field = forms.ModelMultipleChoiceField(widgets=forms.CheckboxSelectMultiple, queryset=dictionary[object])
当然,单纯把字段名写两遍是没办法动态生成不同名字的字段的。这样做其实只会创建一个叫“name_of_field”的字段,使用的是最后一个遍历到的对象。我希望能为字典中的每个键创建一个字段,字段名用键对象的标识符,并且选择的内容是该键对应的值。
有没有办法遍历这个字典,创建我想要的表单字段?我觉得答案可能在于重写 __init__
方法,但我还是搞不清楚怎么才能得到多个不同名字的字段。
2 个回答
0
我觉得我想为这个问题贡献点东西,尽管这个问题已经很老了,因为我光靠答案没法解决我的疑问。
对于一个特定的模型,形式如下:
class Product(models.Model):
data = models.JSONField()
store = models.ForeignKey(Store, on_delete = models.CASCADE)
number = models.PositiveIntegerField()
可以创建一个动态生成的表单(注意,这只是一个简化的例子,所有同一家店的产品在JSONField
中共享相同的键):
class ProductForm(forms.Form):
def __init__(self, first_product, *args, **kwargs):
super().__init__(*args, **kwargs)
self.fields["number"] = forms.IntegerField(required = True)
for key in first_product.data.keys():
self.fields[key] = forms.CharField(required = False)
class Meta:
model = Product
fields = ["number", "data"]
在视图中调用这个表单时,必须传入first_product
这个变量:
class SomeView(TemplateView):
template_name = "appName/sometemplatename.html"
def get_context_data(self, *args, **kwargs):
context = super().get_context_data(**kwargs)
store = Store.objects.get(user = self.request.user)
tmp = Product.objects.filter(store = store).first()
context["testform"] = ProductForm(first_product = tmp)
return context
这是一种非常通用的出发方式。
4
你没有说明你在哪里使用这段代码。你应该把它放在表单的 __init__
方法里,这样你就可以引用 self.fields
了:
class DynamicForm(forms.Form):
def __init__(self, *args, **kwargs):
dynamic_fields = kwargs.pop('dynamic_fields')
super(DynamicForm, self).__init__(*args, **kwargs)
for key, value in dynamic_fields:
self.fields[key.slug] = forms.ModelMultipleChoiceField(widget=forms.CheckboxSelectMultiple, queryset=value)