[python] Django의 FileField를 기존 파일로 설정

디스크에 기존 파일 (예 : /folder/file.txt)과 Django에 FileField 모델 필드가 있습니다.

내가 할 때

instance.field = File(file('/folder/file.txt'))
instance.save()

파일을 file_1.txt(다음 번 _2에 등) 으로 다시 저장합니다 .

나는 그 이유를 이해하지만이 동작을 원하지 않습니다. 필드가 연결되기를 원하는 파일이 실제로 나를 기다리고 있다는 것을 알고 있으며 Django가이를 가리 키기를 원합니다.

어떻게?



답변

이 작업을 영구적으로 수행하려면 고유 한 FileStorage 클래스를 만들어야합니다.

import os
from django.conf import settings
from django.core.files.storage import FileSystemStorage

class MyFileStorage(FileSystemStorage):

    # This method is actually defined in Storage
    def get_available_name(self, name):
        if self.exists(name):
            os.remove(os.path.join(settings.MEDIA_ROOT, name))
        return name # simply returns the name passed

이제 모델에서 수정 된 MyFileStorage를 사용합니다.

from mystuff.customs import MyFileStorage

mfs = MyFileStorage()

class SomeModel(model.Model):
   my_file = model.FileField(storage=mfs)


답변

instance.field.name파일 경로로 설정 하십시오.

class Document(models.Model):
    file = FileField(upload_to=get_document_path)
    description = CharField(max_length=100)


doc = Document()
doc.file.name = 'path/to/file'  # must be relative to MEDIA_ROOT
doc.file
<FieldFile: path/to/file>


답변

이것을 시도하십시오 ( doc ) :

instance.field.name = <PATH RELATIVE TO MEDIA_ROOT>
instance.save()


답변

자신의 스토리지 클래스를 작성하는 것이 옳습니다. 그러나 get_available_name재정의하는 올바른 방법이 아닙니다.

get_available_nameDjango가 동일한 이름의 파일을보고 사용 가능한 새 파일 이름을 얻으려고 할 때 호출됩니다. 이름을 바꾸는 것은 방법이 아닙니다. 그 원인은_save . 의 주석은 _save꽤 좋으며 os.O_EXCL동일한 파일 이름이 이미 존재하면 OSError를 발생시키는 플래그로 작성하기 위해 파일을 쉽게 열 수 있습니다 . Django는이 오류를 포착 한 다음 호출 get_available_name하여 새 이름을 얻습니다.

그래서 올바른 방법은 _saveflag없이 os.open () 을 재정의 하고 호출하는 것 os.O_EXCL입니다. 수정은 아주 간단하지만 방법이 조금 길어서 여기에 붙여 넣지 않습니다. 도움이 더 필요하면 알려주세요. 🙂


답변

나는 똑같은 문제가 있었다! 그런 다음 내 모델이 그 원인을 알았습니다. 예를 들어 다음과 같은 모델을 사용했습니다.

class Tile(models.Model):
  image = models.ImageField()

그런 다음 디스크의 동일한 파일을 참조하는 하나의 타일을 더 많이 갖고 싶었습니다! 그것을 해결하기 위해 찾은 방법은 내 모델 구조를 다음과 같이 변경하는 것입니다.

class Tile(models.Model):
  image = models.ForeignKey(TileImage)

class TileImage(models.Model):
  image = models.ImageField()

같은 파일을 DB에 더 많이 저장하려면 다른 테이블을 만들어야하기 때문입니다.

모델을 변경할 수 있기를 바라면서도 그렇게 문제를 해결할 수 있다고 생각합니다!

편집하다

또한 다음과 같은 다른 저장소를 사용할 수 있다고 생각합니다. SymlinkOrCopyStorage

http://code.welldev.org/django-storages/src/11bef0c2a410/storages/backends/symlinkorcopy.py


답변

자체 스토리지를 정의하고 FileSystemStorage에서 상속하고 OS_OPEN_FLAGS클래스 속성 및 get_available_name()메서드를 재정의해야 합니다 .

Django 버전 : 3.1

프로젝트 /core/files/storages/backends/local.py

import os

from django.core.files.storage import FileSystemStorage


class OverwriteStorage(FileSystemStorage):
    """
    FileSystemStorage subclass that allows overwrite the already existing
    files.

    Be careful using this class, as user-uploaded files will overwrite
    already existing files.
    """

    # The combination that don't makes os.open() raise OSError if the
    # file already exists before it's opened.
    OS_OPEN_FLAGS = os.O_WRONLY | os.O_TRUNC | os.O_CREAT | getattr(os, 'O_BINARY', 0)

    def get_available_name(self, name, max_length=None):
        """
        This method will be called before starting the save process.
        """
        return name

모델에서 사용자 지정 OverwriteStorage를 사용합니다.

myapp / models.py

from django.db import models

from core.files.storages.backends.local import OverwriteStorage


class MyModel(models.Model):
   my_file = models.FileField(storage=OverwriteStorage())


답변