6

Mongoengine 将 FileField 和 ImageField 存储到 GridFS。复制原始文件/图像字段功能的最简单方法是什么?

编辑:

所以这是我目前的课程。我能够加载文件并将它们保存到磁盘,Mongo 在数据库中保存文件的路径。

我迷上了“to_python”,因为我相信它需要创建 proxy_class 的对象,但我不知道如何,如果我得到的只是文件的路径(作为传入的值)。

import os
import datetime

from mongoengine.python_support import str_types
from django.db.models.fields.files import FieldFile
from django.core.files.base import File
from django.core.files.storage import default_storage
from mongoengine.base import BaseField
from mongoengine.connection import get_db, DEFAULT_CONNECTION_NAME
from django.utils.encoding import force_text
#from django.utils.encoding import force_str


class DJFileField(BaseField):

    proxy_class = FieldFile

    def __init__(self,
                 db_alias=DEFAULT_CONNECTION_NAME, 
                 name=None,
                 upload_to='',
                 storage=None,
                 **kwargs):

        self.db_alias = db_alias
        self.storage = storage or default_storage
        self.upload_to = upload_to

        if callable(upload_to):
            self.generate_filename = upload_to

        super(DJFileField, self).__init__(**kwargs)


    def __get__(self, instance, owner):
        # Lots of information on whats going on here can be found
        # on Django's FieldFile implementation, go over to GitHub to
        # read it.
        file = instance._data.get(self.name)

        if isinstance(file, str_types) or file is None:
            attr = self.proxy_class(instance, self, file)
            instance._data[self.name] = attr

        elif isinstance(file, File) and not isinstance(file, FieldFile):
            file_copy = self.proxy_class(instance, self, file.name)
            file_copy.file = file
            file_copy._committed = False
            instance._data[self.name] = file_copy

        elif isinstance(file, FieldFile) and not hasattr(file, 'field'):
            file.instance = instance
            file.field = self
            file.storage = self.storage

        # That was fun, wasn't it?
        return instance._data[self.name]


    def __set__(self, instance, value):
        instance._data[self.name] = value

    # The 3 methods below get used by the FieldFile proxy_object
    def get_directory_name(self):
        return os.path.normpath(force_text(datetime.datetime.now().strftime(self.upload_to)))

    def get_filename(self, filename):
        return os.path.normpath(self.storage.get_valid_name(os.path.basename(filename)))

    def generate_filename(self, instance, filename):
        return os.path.join(self.get_directory_name(), self.get_filename(filename))


    def to_mongo(self, value):
    # Store the path in MongoDB
    # I also used this bit to actually save the file to disk.
    # The value I'm getting here is a FileFiled and it all looks
    # pretty good at this stage even though I'm not 100% sure
    # of what's going on.

        import ipdb; ipdb.set_trace()

        if not value._committed and value is not None:
            value.save(value.name, value)
            return value.path

        return value.path    


    def to_python(self, value):
        # Now this is the real problem, value is the path that got saved
        # in mongo. No idea how to return a FileField obj from here.
        # self.instance and instance throw errors.
4

1 回答 1

2

我认为这将是一个很好的补充 - 可能会调用LocalFileField它以使其更加框架不可知,如果您提供测试和文档,它将成为https://github.com/MongoEngine/extras-mongoengine的一个很好的补充

我没有将它放在核心中的唯一原因是 - 如果您正在运行副本集,该文件仍将仅存储在一个节点上。

于 2013-04-18T12:32:26.763 回答