手动将文件添加到 Django 的媒体文件夹并以编程方式填充数据库



我试图第一次尝试生产django项目。我的django pre-django实现包含大量数据(数千个图像,数据库中的数千个条目)。我写了一个自定义manage.py populate_db命令,该命令解析了旧数据库的转储,并根据我的模型创建新的Django数据库。但是,我坚持添加所有文件。

我的最初部署计划是在本地创建一次数据库,SFTP-UPLOAD所有图像到服务器上的媒体文件夹,对数据库进行相同的操作,仅此而已。为此,我需要数据库在媒体文件夹中引用图像文件。据我了解,Django仅通过文件名来完成。到目前为止,我已经能够做到这一点:

def _add_image_files(self, user: str):
    i = 0 
    for f in local_files:
        i += 1
        photo = Photo(album=1, number=i, back=False, added_by=user)
        from django.core.files import File
        photo.image.save(f.name, File(open(f.path, 'rb')))

将照片定义为

class Photo(models.Model):
    album = models.IntegerField(null=True)
    number = models.IntegerField(null=True)
    image = models.ImageField(null=True, upload_to='photo_image_files')

但是,Django显然通过读取并将其写入媒体文件夹来重复每个文件。我不需要此重复,我只想将每个文件的引用添加到数据库中。

我该如何实现?另外,如果这是出于某种原因的方法,请让我知道更好的方法。谢谢。

我实际上在这里找到了答案:https://stackoverflow.com/a/12917845/674976"窍门"是可以简单地用图像文件名填充imageField。结合Bulk_create,我现在得到合理的执行时间。

 photo_list = []
 for i in range(1000):
     photo = Photo(album=1, number=i, back=False)
     photo.image = 'photo_image_files/:filename_i.jpg'
     photo_list.append(photo)
 Photo.objects.bulk_create(photo_list)

我找不到此技巧的任何参考(将文件名直接分配给ImageField),因此,如果您可以通过编辑或评论中添加一个技巧,这将是一个很好的改进。

django版本:3.2.4

好吧,您可以定义您的存储空间,这不会重复文件,情况已经存在。警告:此解决方案会导致问题,当两个进程尝试以相同名称保存文件时。但它适合编程填充数据库。

models.py
...
from django.core.files.storage import FileSystemStorage
...
class NonDuplicateStorage(FileSystemStorage):
    OS_OPEN_FLAGS = os.O_WRONLY | os.O_CREAT | getattr(
        os, 'O_BINARY', 0)
    def exists(self, name):
        return False
non_duplicate_storage = NonDuplicateStorage()
class Photo(models.Model):
    ...
    image = models.ImageField(null=True, upload_to='photo_image_files', storage = non_duplicate_storage)

这里发生了什么:让我们打开存储类

lib site-packages django core files storege.py

class FileSystemStorage(Storage):
    """
    Standard filesystem storage
    """
    # The combination of O_CREAT and O_EXCL makes os.open() raise OSError if
    # the file already exists before it's opened.
    OS_OPEN_FLAGS = os.O_WRONLY | os.O_CREAT | os.O_EXCL | getattr(
        os, 'O_BINARY', 0)
def _save(self, name, content):
...
        # There's a potential race condition between get_available_name and
        # saving the file; it's possible that two threads might return the
        # same name, at which point all sorts of fun happens. So we need to
        # try to create the file, but if it already exists we have to go back
        # to get_available_name() and try again.
...
        while True:
...
                    fd = os.open(full_path, self.OS_OPEN_FLAGS, 0o666)
...
            except FileExistsError:
                # A new name is needed if the file exists.
                name = self.get_available_name(name)
...

和self.get_available_name调用self.exists(),案例文件已经存在 - 它将被重命名

相关内容

最新更新