【问题标题】:Custom storage system for GridFS (MongoDB)?GridFS(MongoDB)的自定义存储系统?
【发布时间】:2010-11-29 17:19:36
【问题描述】:

谁能指出我提供可插入自定义存储系统的任何项目/django 应用程序,以便我可以将 GridFS 与 Django 一起使用来存储文件上传?

我找到了 django-mongodb,但它似乎不支持 GridFS,django-storages 也不支持。

我计划为正常的数据库要求运行 mysql,并且只使用 mongodb 进行文件存储,所以要明确我不想使用 mongodb 作为我的主数据库。

【问题讨论】:

    标签: python django mongodb


    【解决方案1】:

    我在 PyMongo(MongoDB Python 驱动程序)上工作,但还没有听说过任何使用 GridFS 为 Django 提供自定义存储的项目。这看起来在 PyMongo 上编写起来并不难:可能是将GridFS API 直接翻译成Django storage API。也许可以考虑在某个时候将一些东西放在一起,但这对于任何想要参与的人来说都是一个很棒的开源项目。

    【讨论】:

    • 刚刚添加了一个包含gridfs存储后端的github repo goo.gl/tCFvf
    【解决方案2】:

    django-mongodb-engine 可能值得一看,因为它使您无需更改现有的 Django 代码即可做到这一点。

    【讨论】:

      【解决方案3】:

      我最近实现了GridFS support in Mongoengine,您可能想结帐。这包括一个 Django 存储后端,您可以将其直接插入到您的项目中并与 ImageField 等一起使用。我在生产中使用这些技术,到目前为止它的表现非常好。

      【讨论】:

        【解决方案4】:

        Mayan EDMS、可插入存储和数据库分离正是我需要的。使用 Michael Dirolf 最新的 PyMongo 库,让基础类运行起来相当简单。

        使用它:

        from gridfsstorage import GridFSStorage
        file = models.FileField(storage=GridFSStorage())
        

        gridfsstorage.py 文件:

        import os
        
        from django.core.files.storage import Storage
        from django.utils.encoding import force_unicode
        from django.conf import settings
        
        from pymongo import Connection
        from gridfs import GridFS
        
        class GridFSStorage(Storage):
            def __init__(self, *args, **kwargs):
                self.db = Connection(host=settings.GRIDFS_HOST,
                    port=settings.GRIDFS_PORT)[settings.DATABASE_NAME]
                self.fs = GridFS(self.db)
        
        
            def save(self, name, content):
                while True:
                    try:
                        # This file has a file path that we can move.
                        if hasattr(content, 'temporary_file_path'):
                            self.move(content.temporary_file_path(), name)
                            content.close()
                        # This is a normal uploadedfile that we can stream.
                        else:
                            # This fun binary flag incantation makes os.open throw an
                            # OSError if the file already exists before we open it.
                            newfile = self.fs.new_file(filename=name)
                            try:
                                for chunk in content.chunks():
                                    newfile.write(chunk)
                            finally:
                                newfile.close()
                except Exception, e:
                    raise
                else:
                    # OK, the file save worked. Break out of the loop.
                    break
        
                return name
        
        
            def open(self, name, *args, **kwars):
                return self.fs.get_last_version(name)
        
        
            def delete(self, name):
                oid = self.fs.get_last_version(name)._id
                self.fs.delete(oid)
        
        
            def exists(self, name):
                return self.fs.exists(filename=name)        
        
        
            def path(self, name):
                return force_unicode(name)
        
        
            def size(self, name):
                return self.fs.get_last_version(name).length
        
            def move(self, old_file_name, name, chunk_size=1024*64):
                # first open the old file, so that it won't go away
                old_file = open(old_file_name, 'rb')
                try:
                    newfile = self.fs.new_file(filename=name)
        
                    try:
                        current_chunk = None
                        while current_chunk != '':
                            current_chunk = old_file.read(chunk_size)
                            newfile.write(current_chunk)
                    finally:
                        newfile.close()
                finally:
                    old_file.close()
        
                try:
                    os.remove(old_file_name)
                except OSError, e:
                    # Certain operating systems (Cygwin and Windows) 
                    # fail when deleting opened files, ignore it.  (For the 
                    # systems where this happens, temporary files will be auto-deleted
                    # on close anyway.)
                    if getattr(e, 'winerror', 0) != 32 and getattr(e, 'errno', 0) != 13:
                        raise
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2012-02-06
          • 2013-05-04
          • 1970-01-01
          • 2018-04-02
          • 2016-10-14
          • 2017-06-16
          • 1970-01-01
          相关资源
          最近更新 更多