2009-03-12 10 views
3

ファイルの名前をモデルの保存メソッドでアップロードした後に名前を変更しようとしています。私はファイルの主キーとファイルタイトルのスラッグの組み合わせにファイルの名前を変更しています。Django:アップロードされたファイルがロックされました。名前を変更できません

ファイルを最初にアップロードしたとき、新しいファイルをアップロードしたとき、ファイルやファイルのタイトルが変更されていないときに動作します。

ただし、ファイルのタイトルが変更され、システムは、私は次のエラーを取得する新しいパスに、古いファイルの名前を変更しようとしたとき:

WindowsError at /admin/main/file/1/ 
(32, 'The process cannot access the file because it is being used by another process') 

私は実際に取得する方法がわかりませんこの周り。私はちょうど新しいパスにファイルを対処しようとしました。これは動作しますが、私は古いバージョンを削除することはできません。モデルの短縮

class File(models.Model): 
    nzb = models.FileField(upload_to='files/') 
    name = models.CharField(max_length=256) 
    name_slug = models.CharField(max_length=256, blank=True, null=True, editable=False) 

    def save(self): 
     # Create the name slug. 
     self.name_slug = re.sub('[^a-zA-Z0-9]', '-', self.name).strip('-').lower() 
     self.name_slug = re.sub('[-]+', '-', self.name_slug) 

     # Need the primary key for naming the file. 
     super(File, self).save() 

     # Create the system paths we need. 
     orignal_nzb = u'%(1)s%(2)s' % {'1': settings.MEDIA_ROOT, '2': self.nzb} 
     renamed_nzb = u'%(1)sfiles/%(2)s_%(3)s.nzb' % {'1': settings.MEDIA_ROOT, '2': self.pk, '3': self.name_slug} 

     # Rename the file. 
     if orignal_nzb not in renamed_nzb: 
      if os.path.isfile(renamed_nzb): 
       os.remove(renamed_nzb) 

      # Fails when name is updated. 
      os.rename(orignal_nzb, renamed_nzb) 

     self.nzb = 'files/%(1)s_%(2)s.nzb' % {'1': self.pk, '2': self.name_slug} 

     super(File, self).save() 

を私は質問がアップロードされたファイルを再アップロードされていない場合、私はアップロードされたファイルの名前を変更することができますどのように誰もが知っている、であると仮定?これはロックされた/使用中のように見える唯一の時間です。


更新:

タイラーのアプローチは、新しいファイルが主キーが利用できないアップロードされ、下の彼のテクニックがエラーを投げているとき以外は、働いています。

if not instance.pk: 
    instance.save() 

エラー:

maximum recursion depth exceeded while calling a Python object 

は、主キーをつかむためにどのような方法がありますか?

+0

私は実際にFileFieldに移動/名前の変更機能がない理由を疑っていました。 – Powerlord

答えて

5

あなたはupload_toフィールドを詳しく見てください。これはおそらく、保存中に名前を変更することを迷うよりも簡単です。一度アップロード

http://docs.djangoproject.com/en/dev/ref/models/fields/#filefield

This may also be a callable, such as a function, which will be called to obtain the upload path, including the filename. This callable must be able to accept two arguments, and return a Unix-style path (with forward slashes) to be passed along to the storage system. The two arguments that will be passed are:

+0

しかし、その呼び出し可能ファイルは、実際にファイルがアップロードされたときにのみ使用されますか?もしそうなら、それを指定するだけでは、モデルインスタンスが保存されたときに既存のファイルの名前を変更するだけでは不十分です。 –

+0

私はGuðmundurが正しいと信じています。 upload_toフィールドが使用され、ファイルのタイトルが更新された場合、ファイルは新しいタイトルで名前が変更されることはありません。 –

+0

私の主張は、その事実がうまくサポートされていない場合の名前の変更です。このプロセスの初期段階で名前を変更することは十分サポートされています。おそらく、Djangoが何をしているのかに合わせて解決策を考え直すことは役に立ちます。 –

0

、あなたが持っているすべての権利、メモリ内の画像オブジェクトのですか?

このオブジェクトを自分が選択したフォルダに保存し、手動でデータベースエントリを編集することができます。

あなたはDjango ORM全体をバイパスしていますが、それ以上のDjangoの方法が見つからない限り、私がやることではありません。

+0

私はあなたがこれによって何を意味するか正確には分かりません。 –

+0

私はちょうどそれをより明確にするために答え全体を修正しました。それが役に立てば幸い。 – voyager

3

私の他の答えが廃止され、代わりにこれを使用する:1.0、upload_to can be callableのよう

class File(models.Model): 
    nzb = models.FileField(upload_to=get_filename) 
    ... 
    def get_filename(instance, filename): 
     if not instance.pk: 
      instance.save() 
     # Create the name slug. 
     name_slug = re.sub('[^a-zA-Z0-9]', '-', instance.name).strip('-').lower() 
     name_slug = re.sub('[-]+', '-', name_slug) 

     filename = u'filess/%(2)s_%(3)s.nzb' % {'2': instance.pk, '3': name_slug} 

     return filename 

を、(MEDIA_ROOTに対して)パスを含むファイル名を返すことが予想される場合。

+0

これはかなりうまくいきますが、instance.save()はこのエラーをスローします: "__instancecheck__で最大再帰深度を超えました"。それは何について知っていますか? –

+0

ファイル名(この場合はname_slug)が変更され、ファイルが再アップロードされない場合、ファイル名は変更されません。大したことではないが、それは私が狙っているものだ。これはまだ私が前にそれをやっていた方法をよりきれいにすることができます。あなたはそのエラーを修正する方法を知っていますか? –

+0

また、 "get_filename"がFileクラスの外側でdefindであった場合にのみ、それを動作させることができました。 –

関連する問題