如何在使用 Material Design Layout() 功能的 Django CreateView 上放置验证码
How to place captcha on Django CreateView that uses Material Design Layout() feature
我在使用 Django Material 的现有代码库中工作。有一个 CreateView
用 Django Material 布局定义:
class OurModelCreateView(LayoutMixin, CreateView):
model = OurModel
layout = Layout(
Row('field1', 'field2', 'field3'),
Row(...)
)
此视图收到大量垃圾邮件注册,因此需要验证码。我使用 Django Recaptcha,并且我过去设置了一些验证码。但是,我从来没有在不使用 ModelForm
的情况下进行设置。如果我创建一个 Django 模型表单并像往常一样在表单中定义验证码字段:
from captcha.fields import ReCaptchaField
from captcha.widgets import ReCaptchaV3
class OurModelForm(ModelForm):
captcha = ReCaptchaField(widget=ReCaptchaV3)
class Meta:
model = OurModel
exclude = ()
然后在 CreateView
上指定 form_class = OurModelForm
,ModelFormMixin.get_form_class()
引发以下错误:“不允许同时指定 'fields' 和 'form_class' ”。出现此错误是因为,虽然我没有明确指定 fields
,但 Django Material 的 LayoutMixin
定义了 fields
: https://github.com/viewflow/django-material/blob/294129f7b01a99832a91c48f129cefd02f2fe35f/material/base.py(页面底部)
我可以从 CreateView
中删除 Material Layout()
,但这意味着必须创建一个 html 表单来呈现 Django/Django Material 表单 - 不太理想,因为实际上有几个 CreateViews
需要应用验证码。
所以我认为完成我所追求的唯一方法是以某种方式将 captcha
字段动态插入到表单中。
我过去通过将字段定义放在 Django 表单定义的 __init__()
中动态地将字段插入到 Django 表单中,但我不知道在 [=14] 中覆盖什么=](或包含 CreateView
的各种 mixin)或 Django Material 的 LayoutMixin
,以便动态地将 captcha
字段插入表单。以下几次尝试覆盖 get_form
和 fields
以动态插入 captcha
字段不起作用:
On the CreateView:
def get_form(self, form_class=None):
form = super(OurModelCreate, self).get_form(form_class)
form.fields['captcha'] = ReCaptchaField(widget=ReCaptchaV3)
return form
def fields(self):
fields = super().fields(*args, **kwargs)
fields['captcha'] = ReCaptchaField(widget=ReCaptchaV3)
return [field.field_name for field in fields
# fields is actually a list, so trying the following too, but it doesn't include the ReCaptchaField(widget=ReCaptchaV3) anywhere at this point
def fields(self):
fields = super().fields(*args, **kwargs)
fields.append('captcha')
return fields
如有任何帮助,我们将不胜感激。
根据上面@Alasdair 的评论指出我的答案,我通过从 CreateView
中删除 Django Material 的 LayoutMixin
解决了这个问题,创建了一个 Django定义了验证码字段的表单,然后将 CreateView
添加到 Django 表单的 form_class
。另请参阅我上面的最后一条评论。这对我来说是违反直觉的,直到我在@Alasdair 的第二条评论后再次查看代码:CreateView
上的 layout = Layout(...)
不需要在 CreateView
上使用 LayoutMixin
] 上班。
我在使用 Django Material 的现有代码库中工作。有一个 CreateView
用 Django Material 布局定义:
class OurModelCreateView(LayoutMixin, CreateView):
model = OurModel
layout = Layout(
Row('field1', 'field2', 'field3'),
Row(...)
)
此视图收到大量垃圾邮件注册,因此需要验证码。我使用 Django Recaptcha,并且我过去设置了一些验证码。但是,我从来没有在不使用 ModelForm
的情况下进行设置。如果我创建一个 Django 模型表单并像往常一样在表单中定义验证码字段:
from captcha.fields import ReCaptchaField
from captcha.widgets import ReCaptchaV3
class OurModelForm(ModelForm):
captcha = ReCaptchaField(widget=ReCaptchaV3)
class Meta:
model = OurModel
exclude = ()
然后在 CreateView
上指定 form_class = OurModelForm
,ModelFormMixin.get_form_class()
引发以下错误:“不允许同时指定 'fields' 和 'form_class' ”。出现此错误是因为,虽然我没有明确指定 fields
,但 Django Material 的 LayoutMixin
定义了 fields
: https://github.com/viewflow/django-material/blob/294129f7b01a99832a91c48f129cefd02f2fe35f/material/base.py(页面底部)
我可以从 CreateView
中删除 Material Layout()
,但这意味着必须创建一个 html 表单来呈现 Django/Django Material 表单 - 不太理想,因为实际上有几个 CreateViews
需要应用验证码。
所以我认为完成我所追求的唯一方法是以某种方式将 captcha
字段动态插入到表单中。
我过去通过将字段定义放在 Django 表单定义的 __init__()
中动态地将字段插入到 Django 表单中,但我不知道在 [=14] 中覆盖什么=](或包含 CreateView
的各种 mixin)或 Django Material 的 LayoutMixin
,以便动态地将 captcha
字段插入表单。以下几次尝试覆盖 get_form
和 fields
以动态插入 captcha
字段不起作用:
On the CreateView:
def get_form(self, form_class=None):
form = super(OurModelCreate, self).get_form(form_class)
form.fields['captcha'] = ReCaptchaField(widget=ReCaptchaV3)
return form
def fields(self):
fields = super().fields(*args, **kwargs)
fields['captcha'] = ReCaptchaField(widget=ReCaptchaV3)
return [field.field_name for field in fields
# fields is actually a list, so trying the following too, but it doesn't include the ReCaptchaField(widget=ReCaptchaV3) anywhere at this point
def fields(self):
fields = super().fields(*args, **kwargs)
fields.append('captcha')
return fields
如有任何帮助,我们将不胜感激。
根据上面@Alasdair 的评论指出我的答案,我通过从 CreateView
中删除 Django Material 的 LayoutMixin
解决了这个问题,创建了一个 Django定义了验证码字段的表单,然后将 CreateView
添加到 Django 表单的 form_class
。另请参阅我上面的最后一条评论。这对我来说是违反直觉的,直到我在@Alasdair 的第二条评论后再次查看代码:CreateView
上的 layout = Layout(...)
不需要在 CreateView
上使用 LayoutMixin
] 上班。