如何从 django API 返回保存在 mongodb 中的文件?

发布于 2025-01-14 05:45:12 字数 2369 浏览 4 评论 0原文

我正在努力返回一个文件,例如上传到 mongodb 的 pdf。 我可以将文件上传到数据库,但无法再次检索该文件。 我的端点(视图)应该如何返回文件? 我正在使用 django Rest Framework v3.12.4 和 djongo v1.3.6。我使用 drf-yasg v1.20.0 作为 API 文档。 这是我的设置,models.py、serializers.py、views.py 和 urls.py:

# app settings.py
DATABASES = {
    'default': {
            'ENGINE': 'djongo',
            'NAME': 'TAST_DB2',
            'CLIENT': {
                'host': 'localhost',
                'port': 27017,
                'username': 'root',
                'password': 'reallychangeme',        # :-)
                'authSource': 'admin',
                'authMechanism': 'SCRAM-SHA-1'
            } 
        }
}
DEFAULT_FILE_STORAGE = 'mongo_storage.storage.GridFSStorage'
GRIDFS_DATABASE = 'myfiles'
BASE_URL = 'http://localhost:8085/'
UPLOADED_FILES_USE_URL = True

# models.py
from django.db import models
from djongo.storage import GridFSStorage

grid_fs_storage = GridFSStorage(collection='myfiles', base_url=''.join([settings.BASE_URL, 'myfiles/']))

class TestStandardFile(models.Model):
    myfile = models.FileField(upload_to='teststandards1', storage=grid_fs_storage)

# serializers.py
from rest_framework import serializers 
from teststandards.models import TestStandardFile

class TestStandardFileSerializer(serializers.ModelSerializer):
    class Meta:
        model = TestStandardFile
        fields = '__all__'

# views.py
from rest_framework.generics import ListCreateAPIView
from .models import TestStandard
from .serializers import TestStandardFileSerializer
from rest_framework.parsers import MultiPartParser

# used for the upload
class FileView(ListCreateAPIView):
    parser_classes = ( MultiPartParser,)
    serializer_class = TestStandardFileSerializer
    queryset = TestStandardFile.objects.all()

<----------      !ENDPOINT FOR FILE RETRIEVAL MISSING HERE???

# urls.py
urlpatterns = [ 
   re_path(r'^api/teststandards/file', api.FileView.as_view(), name='teststandard-file'),
   re_path(r'^myfiles/(?P<pk>[0-9]+)$', api.myfiles.as_view(), name='get-file'),
]

我可以看到我的文件已使用 mongodb compass 正确上传到 mongodb。 其中包含三个集合:

  1. TAST_DB2.teststandardsFiles
  2. TAST_DB2.myfiles.teststandards1.files
  3. TAST_DB2.myfiles.teststandards1.chunks

我假设我需要一个端点来返回文件作为响应。 我试图覆盖“myfiles”端点的“get”功能。但我不知道 如何从请求的文件中获取文件句柄。我不知道如何 将文件作为 HttpResponse 返回。

任何帮助表示赞赏!

I am struggeling to return a file e.g. a pdf which was uploaded to a mongodb.
I am able to upload a file to the database but I am not able to retrieve the file again.
How shoud my endpoint (view) look like to return the file?
I am using django rest framework v3.12.4 with djongo v1.3.6. I use drf-yasg v1.20.0 for the documentation of the API.
Here are my settings, models.py, serializers.py, views.py and urls.py:

# app settings.py
DATABASES = {
    'default': {
            'ENGINE': 'djongo',
            'NAME': 'TAST_DB2',
            'CLIENT': {
                'host': 'localhost',
                'port': 27017,
                'username': 'root',
                'password': 'reallychangeme',        # :-)
                'authSource': 'admin',
                'authMechanism': 'SCRAM-SHA-1'
            } 
        }
}
DEFAULT_FILE_STORAGE = 'mongo_storage.storage.GridFSStorage'
GRIDFS_DATABASE = 'myfiles'
BASE_URL = 'http://localhost:8085/'
UPLOADED_FILES_USE_URL = True

# models.py
from django.db import models
from djongo.storage import GridFSStorage

grid_fs_storage = GridFSStorage(collection='myfiles', base_url=''.join([settings.BASE_URL, 'myfiles/']))

class TestStandardFile(models.Model):
    myfile = models.FileField(upload_to='teststandards1', storage=grid_fs_storage)

# serializers.py
from rest_framework import serializers 
from teststandards.models import TestStandardFile

class TestStandardFileSerializer(serializers.ModelSerializer):
    class Meta:
        model = TestStandardFile
        fields = '__all__'

# views.py
from rest_framework.generics import ListCreateAPIView
from .models import TestStandard
from .serializers import TestStandardFileSerializer
from rest_framework.parsers import MultiPartParser

# used for the upload
class FileView(ListCreateAPIView):
    parser_classes = ( MultiPartParser,)
    serializer_class = TestStandardFileSerializer
    queryset = TestStandardFile.objects.all()

<----------      !ENDPOINT FOR FILE RETRIEVAL MISSING HERE???

# urls.py
urlpatterns = [ 
   re_path(r'^api/teststandards/file', api.FileView.as_view(), name='teststandard-file'),
   re_path(r'^myfiles/(?P<pk>[0-9]+)

I can see my file properly uploaded to mongodb with mongodb compass.
There are three collections in it:

  1. TAST_DB2.teststandardsFiles
  2. TAST_DB2.myfiles.teststandards1.files
  3. TAST_DB2.myfiles.teststandards1.chunks

I assume that I need an endpoint which gives the file back as a response.
I tried to overwrite the 'get'-function of my 'myfiles' endpoint. But I don't know
how to get the file handle from the requested file. And I do not know how to
return the file as a HttpResponse.

Any help is appreciated!

, api.myfiles.as_view(), name='get-file'), ]

I can see my file properly uploaded to mongodb with mongodb compass.
There are three collections in it:

  1. TAST_DB2.teststandardsFiles
  2. TAST_DB2.myfiles.teststandards1.files
  3. TAST_DB2.myfiles.teststandards1.chunks

I assume that I need an endpoint which gives the file back as a response.
I tried to overwrite the 'get'-function of my 'myfiles' endpoint. But I don't know
how to get the file handle from the requested file. And I do not know how to
return the file as a HttpResponse.

Any help is appreciated!

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

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

发布评论

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

评论(1

就此别过 2025-01-21 05:45:12

我终于让它发挥作用了。我创建了一个 RetrieveAPIView 来检索一个条目并覆盖了检索函数。这就是我的views.py 的样子:

    # for upload
    class FileView(ListCreateAPIView):
        parser_classes = ( MultiPartParser,)
        serializer_class = TestStandardFileSerializer
        queryset = TestStandardFile.objects.all()
    
    # download
    class myfiles(RetrieveAPIView):
        parser_classes = ( MultiPartParser,)
        serializer_class = TestStandardFileSerializer
        queryset = TestStandardFile.objects.all()
    
        def retrieve(self, request, *args, **kwargs):
            obj = self.get_object()        
            response = HttpResponse(obj.myfile, content_type='application/octet-stream')
            response['Content-Disposition'] = 'attachment; filename=%s' % obj.myfile
            return response

“myfile”是我的模型中FileField 的名称。使用 drf_spectaulous 作为 swagger 文档。这为文件检索生成了一个很好的下载按钮。它在测试上传/下载功能期间提供了很大帮助。

I finally got it to work. I created an RetrieveAPIView for the retrieval of one entry and overwrote the retrieve function. THis is how my views.py looked like:

    # for upload
    class FileView(ListCreateAPIView):
        parser_classes = ( MultiPartParser,)
        serializer_class = TestStandardFileSerializer
        queryset = TestStandardFile.objects.all()
    
    # download
    class myfiles(RetrieveAPIView):
        parser_classes = ( MultiPartParser,)
        serializer_class = TestStandardFileSerializer
        queryset = TestStandardFile.objects.all()
    
        def retrieve(self, request, *args, **kwargs):
            obj = self.get_object()        
            response = HttpResponse(obj.myfile, content_type='application/octet-stream')
            response['Content-Disposition'] = 'attachment; filename=%s' % obj.myfile
            return response

"myfile" is the name of the FileField from my model. With using drf_spectacular for the swagger documentation. This generated a nice download button for the file retrieval. It helped a lot during testing the upload / download functionality.

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