0

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))
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_uploaderview)に渡されます。

request
*args: []
*kwargs: {'widget2_hash_id':'somehashid',}

さて、語彙ではdispatchどういう意味ですか?djangoさて、基本的には、関数を呼び出すことを意味します。

たまたまwidget2.views.widget2_editable_image_ajax_uploader呼び出しメソッドがあるので、django上記の引数を使用してこのメ​​ソッドを喜んで呼び出します。

widget2_hash_id残念ながら、ビューはkwargを受け入れないため、Pythonはエラーを発生させます。それは何をしますか。

迷子になったのは、バックエンドではなく、余分な引数が渡されるのはビューであるという事実を見逃したことだと思います。次に、ビューをバックエンドに渡すのがビューの仕事です。

ソリューション

簡単なもの

追加の引数を受け入れるようにメソッドを変更して__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 に答える