带有动态窗体的Django FormView

带有动态窗体的Django FormView,django,python-3.x,django-class-based-views,Django,Python 3.x,Django Class Based Views,我在下面创建了FormView,它将根据用户所处的流程步骤动态返回一个form类。我在使用get\u form方法时遇到问题。它在get请求中返回正确的表单类,但post请求不起作用 tournament_form_dict = { '1':TournamentCreationForm, '2':TournamentDateForm, '3':TournamentTimeForm, '4':TournamentLocationForm, '5':Tourn

我在下面创建了FormView,它将根据用户所处的流程步骤动态返回一个form类。我在使用
get\u form
方法时遇到问题。它在get请求中返回正确的表单类,但post请求不起作用

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)
post请求在
get\u form
行的
django\views\generic\edit.py
失败,我意识到这是因为我在FormView中覆盖了它:

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)
但是,当我将自定义
get\u form
方法的名称更改为
gen\u 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]
我的表单类在get请求中未得到处理,计算结果为
None
。我在挠头,为什么当我重写
get\u form
方法时,它能工作,而我自己命名的方法却不能?有人知道该漏洞可能是什么吗?

Django的定义是。因此,这里基本上对
FormView
进行了子类化,并对
get\u form
方法进行了“修补”

您尝试使用
gen_form
无效,因为您只定义了局部变量,因此没有多大区别,只有
super(…)
调用会产生一些副作用。其他命令将使CPU忙碌一段时间,但在最后,将只为
Form
调用
Form\u类
变量分配一个引用,但由于它是本地变量,您将丢弃它

也就是说,您的函数包含一些错误。例如,
**kwargs
通常最多包含一个参数:
form\u class
。因此
步骤
s不会有太大作用。您可以通过
self.args
self.kwargs
访问URL参数,并通过
self.request.GET
访问查询字符串参数。此外,您可能无论如何都想修补,因为您返回了对类的引用,而不是对初始化表单的引用

通过字符串处理构建URL可能也不是一个好主意,因为如果您(稍微)更改URL模式,那么您可能会忘记替换
success\u URL
,因此您将引用一个不再存在的路径。使用是一种更安全的方法,因为您传递视图的名称和参数,然后此函数将“计算”正确的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})
从django.url反向导入
类CreateTournament(FormView):
template_name='events/create_contraction_step.html'
def get_form_类(自我):
返回比赛形式[self.kwargs.get('step','1')]
def get_success_url(自我):
new_step=int(self.kwargs.get('step',1))+1
#用反面

return reverse('name_of_view',kwargs={'step':new_step})
是的,
get_表单
是在
FormView
中定义的函数,因此使用该函数。事实上,除了
super(…)
调用之外,您的
\uuuu init\uuu
函数没有做任何事情,因为您只使用局部变量。因此我需要:
self.form\u类
它?是的,而且我建议使用
reverse
来“计算”URL而不是自己进行列表格式化:好的,谢谢……python/django的某些方面对我来说似乎并不直观……但也许我只是对它了解不够……我会试试看。thanksI发现阅读一些文档很有帮助。对于许多工具来说,文档质量并不高。但我不得不说,写(大多数)Django文档的人做得很好。一段时间后,你会更熟悉Django的“感觉”,因此,一段时间后,你可以“预测”事物是如何设计的。