首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >当试图保存从请求下载的文件时,AttributeError

当试图保存从请求下载的文件时,AttributeError
EN

Stack Overflow用户
提问于 2021-06-18 17:27:01
回答 1查看 142关注 0票数 0

我试图保存MP3媒体文件,因为它们打包在对本地存储的请求响应中。我定义了一个模型MP3及其相应的管理器MP3Manager。在管理器中,我们有一个类方法,用于获取数据,最好是从本地数据库,但如果不存在,则从外部媒体服务器获取数据。这种检索发生在一个名为get_mp3()的类方法中。

get_mp3()内部,我们也有save_mp3(),这意味着从response.content获取字节字符串,将其保存到文件系统,并创建一个数据库条目。但是,似乎存在某种格式问题,因为我在执行save_mp3()返回语句时遇到了以下错误:

代码语言:javascript
复制
AttributeError: '_io.BufferedWriter' object has no attribute '_committed'

我该怎么解决这个问题?完整的mp3.py文件如下:

代码语言:javascript
复制
import os
import requests

from django.db import models
from django.utils.translation import gettext_lazy as _

from rest_framework import status
from rest_framework.exceptions import NotFound

from api.exceptions import InternalServerError
from api.models import TimestampedModel


class MP3Manager(models.Manager):
    """
    Class defining utility methods for downloading MP3 pronunciation audio files from the Merriam-Webster media servers.
    """
    @classmethod
    def get_mp3(cls, id, url):
        """
        Obtains an MP3 file from local storage if a database entry exists, and downloads from the Merriam-Webster database on a cache miss.
        """
        mp3 = None

        try:
            # Check the local database.
            mp3 = cls.get(id=id)
        except MP3.DoesNotExist:
            # Not in store. Download and save file.
            response = requests.get(url)

            if response.status_code == status.HTTP_404_NOT_FOUND:
                raise NotFound(_('The specified ID was invalid.'))
            elif response.status_code != status.HTTP_200_OK:
                raise InternalServerError(
                    _(
                        'The file could not retrieved. Please contact support at support@example.com.'
                    ))

            filepath = f'/tmp/{id}.mp3'

            def save_mp3():
                """
                Save the downloaded file to the filesystem and local database.
                """
                with open(filepath, 'xb') as f:
                    content = response.content
                    for i in range(0, len(content), MP3.block_size):
                        upper = min(i + MP3.block_size, len(content))
                        f.write(content[i:upper])

                    return cls.create(id=id, data=f)

            try:
                mp3 = save_mp3()
            except FileExistsError:
                os.remove(filepath)
                mp3 = save_mp3()

        return mp3


class MP3(TimestampedModel):
    """
    Timestamped model for MP3 pronunciation audio files downloaded from the Merriam-Webster media servers.
    """
    # Static Variables
    objects = MP3Manager()
    relative_path = 'mp3'
    block_size = 2**16

    # Attributes
    id = models.CharField(primary_key=True, max_length=64)
    data = models.FileField(_('MP3'), upload_to=relative_path)
    _hash = models.BinaryField(
        _('MD5 hash'), editable=False, null=True, default=None, max_length=16)

追溯到这里:

代码语言:javascript
复制
Traceback (most recent call last):
  File "/home/matt/Repositories/Iconopedia/back-end/api/dictionary/models/mp3.py", line 51, in get_mp3
    mp3 = MP3.objects.get(id=id)
  File "/home/matt/Repositories/Iconopedia/back-end/.venv/lib/python3.9/site-packages/django/db/models/manager.py", line 85, in manager_method
    return getattr(self.get_queryset(), name)(*args, **kwargs)
  File "/home/matt/Repositories/Iconopedia/back-end/.venv/lib/python3.9/site-packages/django/db/models/query.py", line 435, in get
    raise self.model.DoesNotExist(
api.dictionary.models.mp3.MP3.DoesNotExist: MP3 matching query does not exist.

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/home/matt/Repositories/Iconopedia/back-end/api/dictionary/models/mp3.py", line 85, in get_mp3
    mp3 = save_mp3()
  File "/home/matt/Repositories/Iconopedia/back-end/api/dictionary/models/mp3.py", line 76, in save_mp3
    with open(filepath, 'xb') as f:
FileExistsError: [Errno 17] File exists: '/tmp/apple001.mp3'

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/home/matt/Repositories/Iconopedia/back-end/api/dictionary/tests/test_mp3.py", line 42, in test_success_miss
    response = self.client.get(self.url_path, format='json')
  File "/home/matt/Repositories/Iconopedia/back-end/.venv/lib/python3.9/site-packages/rest_framework/test.py", line 288, in get
    response = super().get(path, data=data, **extra)
  File "/home/matt/Repositories/Iconopedia/back-end/.venv/lib/python3.9/site-packages/rest_framework/test.py", line 205, in get
    return self.generic('GET', path, **r)
  File "/home/matt/Repositories/Iconopedia/back-end/.venv/lib/python3.9/site-packages/rest_framework/test.py", line 233, in generic
    return super().generic(
  File "/home/matt/Repositories/Iconopedia/back-end/.venv/lib/python3.9/site-packages/django/test/client.py", line 473, in generic
    return self.request(**r)
  File "/home/matt/Repositories/Iconopedia/back-end/.venv/lib/python3.9/site-packages/rest_framework/test.py", line 285, in request
    return super().request(**kwargs)
  File "/home/matt/Repositories/Iconopedia/back-end/.venv/lib/python3.9/site-packages/rest_framework/test.py", line 237, in request
    request = super().request(**kwargs)
  File "/home/matt/Repositories/Iconopedia/back-end/.venv/lib/python3.9/site-packages/django/test/client.py", line 719, in request
    self.check_exception(response)
  File "/home/matt/Repositories/Iconopedia/back-end/.venv/lib/python3.9/site-packages/django/test/client.py", line 580, in check_exception
    raise exc_value
  File "/home/matt/Repositories/Iconopedia/back-end/.venv/lib/python3.9/site-packages/django/core/handlers/exception.py", line 47, in inner
    response = get_response(request)
  File "/home/matt/Repositories/Iconopedia/back-end/.venv/lib/python3.9/site-packages/django/core/handlers/base.py", line 181, in _get_response
    response = wrapped_callback(request, *callback_args, **callback_kwargs)
  File "/home/matt/Repositories/Iconopedia/back-end/.venv/lib/python3.9/site-packages/django/views/decorators/csrf.py", line 54, in wrapped_view
    return view_func(*args, **kwargs)
  File "/home/matt/Repositories/Iconopedia/back-end/.venv/lib/python3.9/site-packages/django/views/generic/base.py", line 70, in view
    return self.dispatch(request, *args, **kwargs)
  File "/home/matt/Repositories/Iconopedia/back-end/.venv/lib/python3.9/site-packages/rest_framework/views.py", line 509, in dispatch
    response = self.handle_exception(exc)
  File "/home/matt/Repositories/Iconopedia/back-end/.venv/lib/python3.9/site-packages/rest_framework/views.py", line 469, in handle_exception
    self.raise_uncaught_exception(exc)
  File "/home/matt/Repositories/Iconopedia/back-end/.venv/lib/python3.9/site-packages/rest_framework/views.py", line 480, in raise_uncaught_exception
    raise exc
  File "/home/matt/Repositories/Iconopedia/back-end/.venv/lib/python3.9/site-packages/rest_framework/views.py", line 506, in dispatch
    response = handler(request, *args, **kwargs)
  File "/home/matt/Repositories/Iconopedia/back-end/api/dictionary/views/mp3_views.py", line 28, in get
    mp3 = MP3.objects.get_mp3(id)
  File "/home/matt/Repositories/Iconopedia/back-end/api/dictionary/models/mp3.py", line 88, in get_mp3
    mp3 = save_mp3()
  File "/home/matt/Repositories/Iconopedia/back-end/api/dictionary/models/mp3.py", line 82, in save_mp3
    return MP3.objects.create(id=id, data=f)
  File "/home/matt/Repositories/Iconopedia/back-end/.venv/lib/python3.9/site-packages/django/db/models/manager.py", line 85, in manager_method
    return getattr(self.get_queryset(), name)(*args, **kwargs)
  File "/home/matt/Repositories/Iconopedia/back-end/.venv/lib/python3.9/site-packages/django/db/models/query.py", line 453, in create
    obj.save(force_insert=True, using=self.db)
  File "/home/matt/Repositories/Iconopedia/back-end/.venv/lib/python3.9/site-packages/django/db/models/base.py", line 726, in save
    self.save_base(using=using, force_insert=force_insert,
  File "/home/matt/Repositories/Iconopedia/back-end/.venv/lib/python3.9/site-packages/django/db/models/base.py", line 763, in save_base
    updated = self._save_table(
  File "/home/matt/Repositories/Iconopedia/back-end/.venv/lib/python3.9/site-packages/django/db/models/base.py", line 868, in _save_table
    results = self._do_insert(cls._base_manager, using, fields, returning_fields, raw)
  File "/home/matt/Repositories/Iconopedia/back-end/.venv/lib/python3.9/site-packages/django/db/models/base.py", line 906, in _do_insert
    return manager._insert(
  File "/home/matt/Repositories/Iconopedia/back-end/.venv/lib/python3.9/site-packages/django/db/models/manager.py", line 85, in manager_method
    return getattr(self.get_queryset(), name)(*args, **kwargs)
  File "/home/matt/Repositories/Iconopedia/back-end/.venv/lib/python3.9/site-packages/django/db/models/query.py", line 1270, in _insert
    return query.get_compiler(using=using).execute_sql(returning_fields)
  File "/home/matt/Repositories/Iconopedia/back-end/.venv/lib/python3.9/site-packages/django/db/models/sql/compiler.py", line 1415, in execute_sql
    for sql, params in self.as_sql():
  File "/home/matt/Repositories/Iconopedia/back-end/.venv/lib/python3.9/site-packages/django/db/models/sql/compiler.py", line 1358, in as_sql
    value_rows = [
  File "/home/matt/Repositories/Iconopedia/back-end/.venv/lib/python3.9/site-packages/django/db/models/sql/compiler.py", line 1359, in <listcomp>
    [self.prepare_value(field, self.pre_save_val(field, obj)) for field in fields]
  File "/home/matt/Repositories/Iconopedia/back-end/.venv/lib/python3.9/site-packages/django/db/models/sql/compiler.py", line 1359, in <listcomp>
    [self.prepare_value(field, self.pre_save_val(field, obj)) for field in fields]
  File "/home/matt/Repositories/Iconopedia/back-end/.venv/lib/python3.9/site-packages/django/db/models/sql/compiler.py", line 1310, in pre_save_val
    return field.pre_save(obj, add=True)
  File "/home/matt/Repositories/Iconopedia/back-end/.venv/lib/python3.9/site-packages/django/db/models/fields/files.py", line 300, in pre_save
    if file and not file._committed:
AttributeError: '_io.BufferedWriter' object has no attribute '_committed'
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2021-06-18 18:13:08

内置的python文件对象不能直接传递给Django的FileField,我们需要这样包装它:

代码语言:javascript
复制
from django.core.files import File

content = File(f)
mp3.id = id
mp3.data.save("your_file_name.mp3", content, save=False) 
mp3.save()

参见:Django Shell image upload _io.BufferedReader no attribute size

https://docs.djangoproject.com/en/3.2/ref/files/file/#django.core.files.File

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/68039276

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档