【发布时间】:2021-02-07 23:52:49
【问题描述】:
在我的 Django 表单中,我有一个需要根据当前用户的一些信息动态填充的选择字段。我能够正确设置该字段并在表单中呈现 - 但是,我在提交表单时遇到错误,因为它被我在表单的 __init__ 方法中的一些逻辑挂起,只有首先在生成表单的上下文中是有意义的。我是 Django 的超级新手,对这种情况的设计原则不太熟悉。
在我的应用程序的admin.py 中,我有一个用于为数据导出表单创建自定义视图的方法 - 它的相关部分设置如下......
# admin.py
from organizations.models import Organization
from .forms import ExportForm
class SomeModelAdmin(SimpleHistoryAdmin, SoftDeletionModelAdmin):
def export_view(self, request):
authorized_orgs_queryset = Organization.objects.viewable_for_user(request.user).all()
authorized_orgs = [{'id': org.id, 'name': org.name} for org in authorized_orgs_queryset]
context = dict(
self.admin_site.each_context(request),
form = ExportForm({'authorized_orgs': authorized_orgs}),
)
if request.method == 'POST':
form = ExportForm(request.POST)
if form.is_valid():
# do some stuff with the form.cleaned_data and return a .csv file as a response
return response
return TemplateResponse(request, 'export.html', context)
因此,当前用户可能被授权为多个组织导出数据,并且我想以表格的形式向用户展示一个填充了这些组织的选择元素。
ExportForm 具有许多始终相同的“固定”字段,并且只有一个动态选择元素,由我传递给它的 authorized_orgs arg 填充 - 它被定义为...
# forms.py
from django import forms
min_year = 1950
export_formats = [
'csv',
'xls',
'xlsx',
'ods',
'json',
]
class ExportForm(forms.Form):
current_year = datetime.datetime.now().year
export_format = forms.ChoiceField(required=True, label='Format', choices=export_format_choices)
apply_date_range = forms.BooleanField(required=False)
year_from = forms.IntegerField(required=False, disabled=True, min_value=min_year, max_value=current_year, initial=current_year)
year_through = forms.IntegerField(required=False, disabled=True, min_value=min_year, max_value=current_year, initial=current_year)
def __init__(self, *args, **kwargs):
super(ExportForm, self).__init__(*args, **kwargs)
authorized_orgs_choices = [(org['id'], org['name']) for org in args[0]['authorized_orgs']]
self.fields['authorized_org'] = forms.ChoiceField(required=False, label='Choose an authorized organization', choices=authorized_orgs_choices)
当我渲染表单时,一切都很好。但是,表单提交是出错的地方。提交表单会报错
File "/code/observations/forms.py", line 28, in __init__
authorized_orgs_choices = [(org['id'], org['name']) for org in args[0]['authorized_orgs']]
File "/usr/local/lib/python3.7/site-packages/django/utils/datastructures.py", line 78, in __getitem__
raise MultiValueDictKeyError(key)
django.utils.datastructures.MultiValueDictKeyError: 'authorized_orgs'
现在,我明白为什么会发生这种情况 - __init__ 正在从提交的表单中获取值作为其 args,这与我在设置表单时提供的不同。
我不知道在 Django 中通常应该如何处理这种事情......我该如何做到这一点,以便在定义要呈现的表单时正确创建这个动态字段,并且数据是提交后可以在form.cleaned_data 中找到吗?
非常感谢您的任何见解和帮助。
【问题讨论】: