我正在尝试对 ajax 上传器进行子类化以接受 django 模型的 hash_id(以便它可以在成功上传图像后创建模型)并且在传递额外的 kwarg(widget2_hash_id)时遇到问题。我将不胜感激有关如何正确添加 kwarg 的指导。
视图.py:
class S3UploadBackend_Widget2EditableImage(S3UploadBackend):
def upload(self, *args, **kwargs):
self.widget2_hash_id = kwargs.pop('widget2_hash_id')
k = Key(self._bucket)
chunk = uploaded.read()
k.set_contents_from_string(chunk)
# create uploaded file
fh = tempfile.TemporaryFile()
k.get_contents_to_file(fh)
fh.seek(0)
saveable_file = SimpleUploadedFile(k.name, fh.read())
# delete aws key and close tempfile
_media_bucket.delete_key(k)
fh.close()
self.widget2 = Widget2.objects.get(hash_id = self.widget2_hash_id)
self.widget2_editable_image = Widget2EditableImage(image = saveable_file, widget2 = self.widget2)
self.widget2_editable_image.save()
if k.key:
self.key = k.key
return True
else:
# Key creation failed.
return False
def upload_complete(self, request, filename):
# Manually add S3 key to ajaxuploader JSONresponse
res = {"aws_file_key": self.key, "url": self.widget2_editable_image.image.url}
视图.py:
widget2_editable_image_ajax_uploader = AjaxFileUploader(backend=S3UploadBackend_Widget2EditableImage)
网址.py:
(r'^widget2/widget2_image_upload/(?P<widget2_hash_id>[a-fA-F0-9]+)/$', 'widget2.views.widget2_editable_image_ajax_uploader'),
追溯:
Traceback (most recent call last):
File "/home/zain/XXX/lib/Django-1.3.1/django/core/handlers/base.py", line 111, in get_response
response = callback(request, *callback_args, **callback_kwargs)
TypeError: __call__() got an unexpected keyword argument 'widget2_hash_id'
[20/Aug/2012 20:50:44] "POST /widget2/widget2_image_upload/d9dc4fab3d5e0eb45995/?qqfile=s3Zas.jpg HTTP/1.1" 500 870358
编辑:我在课堂上试过这个并得到同样的错误:
def __init__(self, *args, **kwargs):
try:
self.widget2 = Widget2.objects.get(hash_id = kwargs.pop('widget2_hash_id'))
except KeyError:
self.widget2_hash_id = None
super(S3UploadBackend_Widget2EditableImage, self).__init__(*args, **kwargs)
EDIT2:这里是 AjaxFileUploader 类:
class AjaxFileUploader(object):
def __init__(self, backend=None, **kwargs):
if backend is None:
backend = LocalUploadBackend
self.get_backend = lambda: backend(**kwargs)
def __call__(self, request, **kwargs):
return self._ajax_upload(request)
def _ajax_upload(self, request):
if request.method == "POST":
if request.is_ajax():
# the file is stored raw in the request
upload = request
is_raw = True
# AJAX Upload will pass the filename in the querystring if it
# is the "advanced" ajax upload
try:
filename = request.GET['qqfile']
except KeyError:
return HttpResponseBadRequest("AJAX request not valid")
# not an ajax upload, so it was the "basic" iframe version with
# submission via form
else:
is_raw = False
if len(request.FILES) == 1:
# FILES is a dictionary in Django but Ajax Upload gives
# the uploaded file an ID based on a random number, so it
# cannot be guessed here in the code. Rather than editing
# Ajax Upload to pass the ID in the querystring, observe
# that each upload is a separate request, so FILES should
# only have one entry. Thus, we can just grab the first
# (and only) value in the dict.
upload = request.FILES.values()[0]
else:
raise Http404("Bad Upload")
filename = upload.name
backend = self.get_backend()
# custom filename handler
# Override filename to avoid collisons
filename = unicode(hashlib.sha1(str(datetime.datetime.now())).hexdigest()[0:6]) + filename
filename = (backend.update_filename(request, filename)
or filename)
# save the file
backend.setup(filename)
success = backend.upload(upload, filename, is_raw)
# callback
extra_context = backend.upload_complete(request, filename)
# let Ajax Upload know whether we saved it or not
ret_json = {'success': success, 'filename': filename}
if extra_context is not None:
ret_json.update(extra_context)
return HttpResponse(json.dumps(ret_json, cls=DjangoJSONEncoder))