我目前正在使用Django构建一个Web应用程序,我已经实现了可能被称为“签名字段”的东西。本质上,它使用http://keith-wood.name/signature.html处的jQuery UI插件来实现签名捕获字段,在提交表单时,通过AJAX POST将其作为基本64位编码字符串发送到服务器,然后转换为映像。服务器
现在,我已经将它的客户端方面重构为一个名为SignatureInput的可重用小部件,并且我还在单个视图中实现了它的服务器端方面。但是,我真的想把它变成通用的字段,以便我可以将它与现有的通用视图一起使用,这就是我在努力的地方 - 它可能只是一个木头换树的时刻,但我可以在Django文档中找不到包含这种情况的任何内容。
SignatureField本身扩展了ImageField,在管理界面中我想坚持使用现有的图像上传对话框,所以我不想在模型级别覆盖它。相反,当它仅在前端提交时,我希望它从request.POST中提取,处理并添加到request.FILES。
我在widgets.py中为它定义了以下小部件:
class SignatureInput(ClearableFileInput):
def render(self, name, value, attrs=None):
try:
id = self.attrs['id']
except KeyError:
id = None
if id:
id_html = ' id="%s"' % (id)
else:
id_html = ''
# Value is set - show existing image and field to change it
if value:
html = """
<div class="signatureContainer">
<br /><img class="existingSignature" alt="Signature" title="Signature" src="/media/%s"></img>
<div data-role="collapsible">
<h4>New signature</h4>
<br /><div class="signature"%s></div><br /><br />
<a data-role="button" class="signatureClear">Clear signature</a>
</div>
""" % (value, id_html)
else:
html = """
<div class="signatureContainer">
<br /><div class="signature"%s></div><br /><br />
<a data-role="button" class="signatureClear">Clear signature</a>
</div>
""" % (id_html)
return html
SignatureInput字段用于需要签名字段的所有前端表单,并使用jQuery AJAX作为base 64编码字符串提交。
以下是我在现有视图中实现处理图像的服务器端代码的方法:
# Create your views here.
import cStringIO as StringIO
from xhtml2pdf import pisa
from django.http import HttpResponse, HttpResponseRedirect
from django.template.loader import get_template
from django.template.context import Context
from django.shortcuts import render, render_to_response
from my_app.models import *
from my_app.forms import JobForm
from django.core.files.uploadedfile import InMemoryUploadedFile
from django.conf import settings
import base64
import uuid
import sys
def decodeImage(image):
# Remove encoding data
image = image.replace('data:image/png;base64,', '')
# Decode image
image = base64.b64decode(image)
# Return it
return image
def addJob(request):
# If request is a GET request, just render it
if request.method == 'GET':
return render_to_response('my_app/job_form.html', {'form': JobForm})
elif request.method == 'POST':
# If request is a POST request, process it
# Get the signatures
if request.POST.get(u'signature'):
signature = StringIO.StringIO(decodeImage(request.POST[u'signature']))
# Construct the File objects
signatureOutput = InMemoryUploadedFile(signature,
field_name='signature',
name=settings.MEDIA_ROOT + str(int(uuid.uuid1()))[:10] + '.png',
content_type="image/png",
size=sys.getsizeof(signature),
charset=None)
request.FILES[u'signature'] = signatureOutput
# Validate the data
jobform = JobForm(request.POST, request.FILES)
if jobform.is_valid():
# Save the form as a new instance of Job
jobform.save()
# Show the success page
return HttpResponseRedirect('/forms/jobs/add/success/')
else:
# Return an error
return render(request, 'my_app/job_form.html', {
'form': jobform,
})
我如何在提交过程的早期执行addJob视图函数中当前完成的处理,以便我可以使用带有通用视图的签名字段?基本上我需要能够将字符串处理成图像,并在它到达视图之前将其从request.POST移动到request.FILES。中间件似乎是错误的地方。
答案 0 :(得分:1)
您可以尝试使用value_from_datadict
方法在自定义窗口小部件中执行此操作。从这个函数的Django文档字符串:
给定数据字典和此窗口小部件的名称,返回值 这个小部件。如果没有提供,则返回None。
此方法应该返回基于POST数据字典和窗口小部件名称的值。因此,在您的情况下,您可以从POST读取base64字符串并将其转换为图像文件数据。此数据需要与ImageField的预期相对应。
这个问题使用了我提到的功能:
Django subclassing multiwidget - reconstructing date on post using custom multiwidget
此处还检查此功能的Django代码:
https://github.com/django/django/blob/master/django/forms/widgets.py