【发布时间】:2018-06-04 06:48:28
【问题描述】:
我想让文件上传成为表单页面上可能的 Wagtail 表单字段类型。我如何配置模型以使这成为可能?请注意,我对允许用户上传 PDF 等文档文件而不是图像更感兴趣。
【问题讨论】:
我想让文件上传成为表单页面上可能的 Wagtail 表单字段类型。我如何配置模型以使这成为可能?请注意,我对允许用户上传 PDF 等文档文件而不是图像更感兴趣。
【问题讨论】:
这是来自 LB Johnson 的great article 就此事。下面的代码直接取自文章(但复制此处以防文章消失),但是您可能希望按照文章逐步解释所有内容。
目前非常复杂,您需要:
AbstractFormField 以定义新的字段类型。FormBuilder以处理新的字段类型。form_builder 设置为您的自定义 FormBuilder 类。serve 方法以将文件数据传递给表单(仅当您使用 Wagtail 1.12 及更低版本时,它会自动从 Wagtail 1.13 执行)process_form_submission 以处理文件这里是完整的代码:
from wagtail.wagtailforms.models import AbstractFormField, FORM_FIELD_CHOICES
from wagtail.wagtailforms.forms import FormBuilder
from wagtail.wagtailimages.fields import WagtailImageField
def filename_to_title(filename):
from os.path import splitext
if filename:
result = splitext(filename)[0]
result = result.replace('-', ' ').replace('_', ' ')
return result.title()
class FormField(AbstractFormField):
FORM_FIELD_CHOICES = list(FORM_FIELD_CHOICES) + [('image', 'Upload Image')]
field_type = models.CharField(
verbose_name=_('field type'),
max_length=16,
choices=FORM_FIELD_CHOICES)
page = ParentalKey('FormPage', related_name='form_fields')
class ExtendedFormBuilder(FormBuilder):
def create_image_upload_field(self, field, options):
return WagtailImageField(**options)
FIELD_TYPES = FormBuilder.FIELD_TYPES
FIELD_TYPES.update({
'image': create_image_upload_field,
})
class FormPage(AbstractEmailForm):
form_builder = ExtendedFormBuilder
def serve(self, request, *args, **kwargs):
if request.method == 'POST':
# form = self.get_form(request.POST, page=self, user=request.user) # Original line
form = self.get_form(request.POST, request.FILES, page=self, user=request.user)
if form.is_valid():
self.process_form_submission(form)
return render(
request,
self.get_landing_page_template(request),
self.get_context(request)
)
else:
form = self.get_form(page=self, user=request.user)
context = self.get_context(request)
context['form'] = form
return render(
request,
self.get_template(request),
context
)
def process_form_submission(self, form):
cleaned_data = form.cleaned_data
for name, field in form.fields.iteritems():
if isinstance(field, WagtailImageField):
image_file_data = cleaned_data[name]
if image_file_data:
ImageModel = get_image_model()
image = ImageModel(
file=cleaned_data[name],
title=filename_to_title(cleaned_data[name].name),
collection=self.upload_image_to_collection,
# assumes there is always a user - will fail otherwise
uploaded_by_user=form.user,
)
image.save()
cleaned_data.update({name: image.id})
else:
# remove the value from the data
del cleaned_data[name]
form_data = json.dumps(cleaned_data, cls=DjangoJSONEncoder)
submission_object = dict(
page=self,
form_data=form_data,
user=form.user,
)
intro = RichTextField(blank=True)
thank_you_text = RichTextField(blank=True)
FormPage.content_panels = [
FieldPanel('title', classname="full title"),
FieldPanel('intro', classname="full"),
InlinePanel('form_fields', label="Form fields"),
FieldPanel('thank_you_text', classname="full"),
MultiFieldPanel([
FieldRowPanel([
FieldPanel('from_address', classname="col6"),
FieldPanel('to_address', classname="col6"),
]),
FieldPanel('subject'),
], "Email"),
]
这是处理文档而不是图像的(未经测试的)代码:
from django.forms import FileField
from wagtail.wagtaildocs.models import get_document_model
# Other imports
class FormField(AbstractFormField):
FORM_FIELD_CHOICES = list(FORM_FIELD_CHOICES) + [('document', 'Upload Document')]
# `field_type` and `page` remain unchanged
class ExtendedFormBuilder(FormBuilder):
def create_document_upload_field(self, field, options):
return FileField(**options)
FIELD_TYPES = FormBuilder.FIELD_TYPES
FIELD_TYPES.update({
'document': create_document_upload_field,
})
class FormPage(AbstractEmailForm):
# `form_builder` attribute and `serve` remain unchanged.
def process_form_submission(self, form):
cleaned_data = form.cleaned_data
for name, field in form.fields.iteritems():
if isinstance(field, FileField):
document_file_data = cleaned_data[name]
if document_file_data:
DocumentModel = get_document_model()
document = DocumentModel(
file=cleaned_data[name],
title=filename_to_title(cleaned_data[name].name),
# assumes there is always a user - will fail otherwise
uploaded_by_user=form.user,
)
document.save()
cleaned_data.update({name: document.id})
else:
# remove the value from the data
del cleaned_data[name]
# The rest of the function is unchanged
【讨论】:
现在 Wagtail 开发人员在 FormBuilder 中进行了一些更改,所以在下面给出的代码现在不起作用
class ExtendedFormBuilder(FormBuilder):
def create_document_upload_field(self, field, options):
return FileField(**options)
FIELD_TYPES = FormBuilder.FIELD_TYPES
FIELD_TYPES.update({
'document': create_document_upload_field,
})
他们做的不是这个
class ExtendedFormBuilder(FormBuilder):
def create_document_upload_field(self, field, options):
return FileField(**options)
FIELD_TYPES = FormBuilder.formfields
Wagtail Core 开发人员将 FormBuilder.FIELD_TYPES 属性更改为 FormBuilder.formfields
所以我希望这有助于开发者让你知道最近发生了哪些变化。
【讨论】: