我正在尝试将ajax上传器子类化以接受django模型的hash_id(以便它可以在成功上载图像时创建模型)并且无法传递额外的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))
答案 0 :(得分:3)
在urls.py
中,你有这个:
(r'^widget2/widget2_image_upload/(?P<widget2_hash_id>[a-fA-F0-9]+)/$', 'widget2.views.widget2_editable_image_ajax_uploader'),
当url
匹配时,django
会将请求以及args分派给给定视图,因此,如果我们将其分解,则以下参数将传递给{{ 1}}(widget2.views.widget2_editable_image_ajax_uploader
):
view
现在,request
*args: []
*kwargs: {'widget2_hash_id':'somehashid',}
在dispatch
词汇中意味着什么?嗯,基本上,它意味着呼叫功能。
恰好django
有一个调用方法,因此widget2.views.widget2_editable_image_ajax_uploader
会很乐意使用上面提到的参数调用此方法。
不幸的是,由于你的视图不接受django
kwarg,python会引发错误。它是做什么的。
我认为你丢失的重点在于你错过了这样一个事实:它是通过额外的arg而不是后端的视图。然后,视图的工作就是将其传递给后端。
您只需要修改widget2_hash_id
方法,使其接受额外的arg,然后将其传递给__call__
方法。
然后,您需要将参数传递给后端。为此,您应该更改以下行:
_ajax_upload
到
backend.upload(upload, filename, is_raw)
现在,我必须说我对你在做什么感到有点困惑。您似乎将对象用作视图,但是,为什么不使用backend.upload(upload, filename, is_raw, widget2_hash_id)
的真棒class-based views?
以前的文档非常缺乏(老实说我不知道是否仍然如此),所以这里是a small guide to get you started。
花一些时间学习和使用它们。它们非常易于使用和扩展,从长远来看,它们将为您节省大量时间。
请使用django forms,因为他们摇滚。