djangoモデルのhash_idを受け入れるようにajaxアップローダーをサブクラス化しようとしています(画像のアップロードが成功したときにモデルを作成できるようにするため)、追加のkwarg(widget2_hash_id)を渡すのに問題があります。kwargを適切に追加する方法についてのガイダンスをいただければ幸いです。
views.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}
views.py:
widget2_editable_image_ajax_uploader = AjaxFileUploader(backend=S3UploadBackend_Widget2EditableImage)
urls.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))