我在下面创建了FormView,它将根据用户所处过程的哪个步骤动态返回表单类。我在tournament_form_dict = {
'1':TournamentCreationForm,
'2':TournamentDateForm,
'3':TournamentTimeForm,
'4':TournamentLocationForm,
'5':TournamentRestrictionForm,
'6':TournamentSectionForm,
'7':TournamentSectionRestrictionForm,
'8':TournamentSectionRoundForm,}
class CreateTournament(FormView):
template_name = 'events/create_tournament_step.html'
def __init__(self, *args, **kwargs):
form_class = self.get_form()
success_url = self.get_success_url()
super(CreateTournament, self).__init__(*args, **kwargs)
def get_form(self, **kwargs):
if 'step' not in kwargs:
step = '1'
else:
step = kwargs['step']
return tournament_form_dict[step]
def get_success_url(self, **kwargs):
if 'step' not in kwargs:
step = 1
else:
step = int(kwargs['step'])
step += 1
if 'record_id' not in kwargs:
record_id = 0
else:
record_id = int(kwargs['record_id'])
return 'events/tournaments/create/%d/%d/' % (record_id, step)
方法上遇到了麻烦。它会在get请求中返回正确的表单类,但post请求无法正常工作。
django\views\generic\edit.py
发布请求在get_form
行的def post(self, request, *args, **kwargs):
"""
Handle POST requests: instantiate a form instance with the passed
POST variables and then check if it's valid.
"""
form = self.get_form()
if form.is_valid(): …
return self.form_valid(form)
else:
return self.form_invalid(form)
处失败,我意识到这是因为我已在FormView中将其覆盖:
get_form
但是,当我将自定义gen_form
方法的名称更改为def __init__(self, *args, **kwargs):
form_class = self.gen_form()
success_url = self.get_success_url()
super(CreateTournament, self).__init__(*args, **kwargs)
def gen_form(self, **kwargs):
if 'step' not in kwargs:
step = '1'
else:
step = kwargs['step']
return tournament_form_dict[step]
时,就像这样:
None
我的表单类未在get请求中得到处理,其结果为get_form
。我想知道为什么当我覆盖{{1}}方法时它可以工作,但是我自己的命名方法不起作用吗?有人知道缺陷可能是什么吗?
答案 0 :(得分:1)
Django的FormMixin
[Django-doc]定义了get_form
function [Django-doc]。因此,您在这里基本上将FormView
的子类化,并“修补”了get_form
方法。
您尝试使用gen_form
无效,因为您仅定义了 local 变量,因此没有太大的区别,只有super(..)
调用会有一些副作用。其他命令将使CPU繁忙一段时间,但是最后,将仅分配对对Form
变量的form_class
调用的引用,但是由于它是本地变量,因此将其丢弃
也就是说,您的函数包含一些错误。例如,**kwargs
通常最多包含一个 个参数:form_class
。因此,step
不会做太多事情。您可以通过self.args
和self.kwargs
访问URL参数,并通过self.request.GET
访问querystring参数。此外,您可能仍然想修补get_form_class
function,因为您返回的是对类的引用,而据我所知,不是对初始化表格的引用。
通过字符串处理构造URL也不是一个好主意,因为如果您(稍微)更改URL模式,那么很可能您会忘记替换success_url
,因此您将参考一条不再存在的路径。使用reverse
function是更安全的方法,因为您传递了视图名称和参数,然后此函数将“计算”正确的URL。这基本上是Django模板中{% url ... %}
模板标记背后的机制。
因此,更好的方法是:
from django.urls import reverse
class CreateTournament(FormView):
template_name = 'events/create_tournament_step.html'
def get_form_class(self):
return tournament_form_dict[self.kwargs.get('step', '1')]
def get_success_url(self):
new_step = int(self.kwargs.get('step', 1)) + 1
# use a reverse
return reverse('name_of_view', kwargs={'step': new_step})