Django 与可插拔 MongoDB 存储的问题

发布于 2024-10-18 07:44:50 字数 1664 浏览 6 评论 0原文

我正在尝试使用 django 和 mongoengine 仅通过 GridFS 提供存储后端。我还有一个 MySQL 数据库。

当我从 django 管理中删除时,我遇到了一个奇怪的(对我来说)错误,我想知道我是否做错了什么。

我的代码如下所示:

# settings.py
from mongoengine import connect
connect("mongo_storage")

# models.py
from mongoengine.django.storage import GridFSStorage
class MyFile(models.Model):
    name = models.CharField(max_length=50)
    content = models.FileField(upload_to="appsfiles", storage=GridFSStorage())
    creation_time = models.DateTimeField(auto_now_add=True)
    last_update_time = models.DateTimeField(auto_now=True)

我可以很好地上传文件,但是当我删除它们时,某些东西似乎会损坏,并且 mongo 数据库似乎处于无法工作的状态,直到我手动删除所有 FileDocument.objects。发生这种情况时,我无法上传文件或从 django 界面删除它们。

从堆栈跟踪中我可以看出:

/home/projects/vector/src/mongoengine/django/storage.py in _get_doc_with_name
        doc = [d for d in docs if getattr(d, self.field).name == name] ...
▼ Local vars
Variable    Value
_[1]    
[]
d   

docs    
Error in formatting: cannot set options after executing query
name    
u'testfile.pdf'
self    

/home/projects/vector/src/mongoengine/fields.py in __getattr__
        raise AttributeError 

我是否错误地使用了此功能?

更新:

感谢@zeekay的回答,我能够让一个有效的gridfs存储插件正常工作。我最终根本没有使用 mongoengine 。我将改编后的解决方案放在 github 上。有一个清晰的示例项目展示了如何使用它。我还将项目上传到 pypi

另一个更新:

我强烈推荐 django-storages 项目。它有很多存储支持的选项,并且比我最初提出的解决方案使用的人更多。

I'm trying to use django, and mongoengine to provide the storage backend only with GridFS. I still have a MySQL database.

I'm running into a strange (to me) error when I'm deleting from the django admin and am wondering if I am doing something incorrectly.

my code looks like this:

# settings.py
from mongoengine import connect
connect("mongo_storage")

# models.py
from mongoengine.django.storage import GridFSStorage
class MyFile(models.Model):
    name = models.CharField(max_length=50)
    content = models.FileField(upload_to="appsfiles", storage=GridFSStorage())
    creation_time = models.DateTimeField(auto_now_add=True)
    last_update_time = models.DateTimeField(auto_now=True)

I am able to upload files just fine, but when I delete them, something seems to break and the mongo database seems to get in an unworkable state until I manually delete all FileDocument.objects. When this happens I can't upload files or delete them from the django interface.

From the stack trace I have:

/home/projects/vector/src/mongoengine/django/storage.py in _get_doc_with_name
        doc = [d for d in docs if getattr(d, self.field).name == name] ...
▼ Local vars
Variable    Value
_[1]    
[]
d   

docs    
Error in formatting: cannot set options after executing query
name    
u'testfile.pdf'
self    

/home/projects/vector/src/mongoengine/fields.py in __getattr__
        raise AttributeError 

Am I using this feature incorrectly?

UPDATE:

thanks to @zeekay's answer I was able to get a working gridfs storage plugin to work. I ended up not using mongoengine at all. I put my adapted solution on github. There is a clear sample project showing how to use it. I also uploaded the project to pypi.

Another Update:

I'd highly recommend the django-storages project. It has lots of storage backed options and is used by many more people than my original proposed solution.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

酒与心事 2024-10-25 07:44:50

我认为你最好不要使用 MongoEngine,我也没有太多运气。这是 mongoengine.django.storage.GridFSStorage 的直接替代品,可与管理员一起使用。

from django.core.files.storage import Storage
from django.conf import settings

from pymongo import Connection
from gridfs import GridFS

class GridFSStorage(Storage):
    def __init__(self, host='localhost', port=27017, collection='fs'):
        for s in ('host', 'port', 'collection'):
            name = 'GRIDFS_' + s.upper()
            if hasattr(settings, name):
                setattr(self, s, getattr(settings, name))
        for s, v in zip(('host', 'port', 'collection'), (host, port, collection)):
            if v:
                setattr(self, s, v)
        self.db = Connection(host=self.host, port=self.port)[self.collection]
        self.fs = GridFS(self.db)

    def _save(self, name, content):
        self.fs.put(content, filename=name)
        return name

    def _open(self, name, *args, **kwars):
        return self.fs.get_last_version(filename=name)

    def delete(self, name):
        oid = fs.get_last_version(filename=name)._id
        self.fs.delete(oid)

    def exists(self, name):
        return self.fs.exists({'filename': name})

    def size(self, name):
        return self.fs.get_last_version(filename=name).length

GRIDFS_HOSTGRIDFS_PORTGRIDFS_COLLECTION 可以在您的设置中定义或作为 hostport 传递code>、collection 关键字参数传递给模型的 FileField 中的 GridFSStorage

我参考了 Django 的 自定义存储 文档,并大致遵循此答案类似的问题。

I think you are better off not using MongoEngine for this, I haven't had much luck with it either. Here is a drop-in replacement for mongoengine.django.storage.GridFSStorage, which works with the admin.

from django.core.files.storage import Storage
from django.conf import settings

from pymongo import Connection
from gridfs import GridFS

class GridFSStorage(Storage):
    def __init__(self, host='localhost', port=27017, collection='fs'):
        for s in ('host', 'port', 'collection'):
            name = 'GRIDFS_' + s.upper()
            if hasattr(settings, name):
                setattr(self, s, getattr(settings, name))
        for s, v in zip(('host', 'port', 'collection'), (host, port, collection)):
            if v:
                setattr(self, s, v)
        self.db = Connection(host=self.host, port=self.port)[self.collection]
        self.fs = GridFS(self.db)

    def _save(self, name, content):
        self.fs.put(content, filename=name)
        return name

    def _open(self, name, *args, **kwars):
        return self.fs.get_last_version(filename=name)

    def delete(self, name):
        oid = fs.get_last_version(filename=name)._id
        self.fs.delete(oid)

    def exists(self, name):
        return self.fs.exists({'filename': name})

    def size(self, name):
        return self.fs.get_last_version(filename=name).length

GRIDFS_HOST, GRIDFS_PORT and GRIDFS_COLLECTION can be defined in your settings or passed as host, port, collection keyword arguments to GridFSStorage in your model's FileField.

I referred to Django's custom storage documenation, and loosely followed this answer to a similar question.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文