0

我正在尝试对 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))
4

1 回答 1

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会将请求以及参数发送到给定视图,因此,如果我们将其分解,以下参数将传递给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乐意使用上面提到的参数调用这个方法。

不幸的是,由于您的视图不接受widget2_hash_idkwarg,python 将引发错误。它确实如此。

我认为你迷路的重点是你错过了这样一个事实,即通过额外的 arg 是视图,而不是后端。然后视图的工作就是将其传递给后端。

解决方案

最容易的

您只需要修改您的__call__方法,使其接受额外的参数,然后将其传递给_ajax_upload方法。

然后,您需要将参数传递给后端。为此,您应该更改以下行:

backend.upload(upload, filename, is_raw)

backend.upload(upload, filename, is_raw, widget2_hash_id)

正确的那一个

现在,我必须说我对你在做什么感到有点困惑。您似乎将对象用作视图,但是,您为什么不使用django很棒的基于类的视图呢?

文档过去非常缺乏(老实说,我不知道是否仍然如此),所以这里有一个小指南来帮助您入门

花一些时间学习和使用它们。它们非常易于使用和扩展,从长远来看,它们将为您节省大量时间。

在结束语上

请务必使用django 形式,因为它们很摇滚。

于 2012-08-20T22:26:39.763 回答