Opened 4 months ago

Closed 3 months ago

Last modified 3 months ago

#35658 closed Bug (fixed)

InMemoryFileNode object has no attribute "name"

Reported by: David Owned by: Lucas Esposito
Component: File uploads/storage Version: 4.2
Severity: Normal Keywords: storage
Cc: Triage Stage: Ready for checkin
Has patch: yes Needs documentation: no
Needs tests: no Patch needs improvement: no
Easy pickings: no UI/UX: no

Description (last modified by David)

Using the InMemoryStorage into an other model by using:

# models.py

class MyModel(models.Model):
    attachment = models.FileField(...)

# script.py

obj = MyModel.objects.create(attachment=ContentFile(b'content', 'myfile.txt') 
repr(obj.attachment)

An excetption is raised: AttributeError("'InMemoryFileNode' object has no attribute 'name'") raised in repr()

This may be caused by the fact that InMemoryFileNode inheriths from ContentFile but does not use the name attribute nor uses the base class __init__ method:

https://github.com/django/django/blob/509763c79952cde02d9f5b584af4278bdbed77b2/django/core/files/storage/memory.py#L48-L52

This resulting in a partially initialized object without an important property.

Change History (16)

comment:1 by David, 4 months ago

Description: modified (diff)

comment:2 by David, 4 months ago

Description: modified (diff)

comment:3 by Lucas Esposito, 4 months ago

Owner: set to Lucas Esposito
Status: newassigned

comment:4 by Lucas Esposito, 4 months ago

Has patch: set

I agree about the need of the issue. I also found other places were the 'name' attribute may be accessed, which would result in a similar error as described above.

I just made a PR: https://github.com/django/django/pull/18453

Version 0, edited 4 months ago by Lucas Esposito (next)

comment:5 by Lucas Esposito, 4 months ago

Triage Stage: UnreviewedAccepted

comment:6 by Sarah Boyce, 4 months ago

Patch needs improvement: set

comment:7 by Sarah Boyce, 4 months ago

Component: Core (Other)File uploads/storage
Summary: [Bug] InMemoryFileNode has no attribute "name"InMemoryFileNode object has no attribute "name"

comment:8 by Lucas Esposito, 4 months ago

Patch needs improvement: unset

comment:9 by Sarah Boyce, 4 months ago

Resolution: worksforme
Status: assignedclosed

Hi David, I have not been able to replicate the error on main or Django 4.2

@override_settings(
    STORAGES={"default": {"BACKEND": "django.core.files.storage.InMemoryStorage"}}
)
class FileFieldModelTest(TestCase):
    def test_repr(self):
        test = FileFieldModel.objects.create(
            file=ContentFile(b'content', 'myfile.txt')
        )
        self.assertEqual(repr(test.file), "<FieldFile: myfile.txt>")

Can you share the full traceback or give more instructions on how to replicate the error?

comment:10 by Sarah Boyce, 4 months ago

Resolution: worksforme
Status: closednew

Ah I found an error

@override_settings(
    STORAGES={"default": {"BACKEND": "django.core.files.storage.InMemoryStorage"}}
)
class FileFieldModelTest(TestCase):
    def test_repr(self):
        test = FileFieldModel()
        test.file.save(None, ContentFile(b'content', 'myfile.txt'))
        self.assertEqual(repr(test.file), "<FieldFile: myfile.txt>")

Breaks with

Traceback (most recent call last):
  File "test-django-package/mysite/app3/tests.py", line 13, in test_repr
    test.file.save(None, ContentFile(b'content', 'myfile.txt'))
  File "test-django-package/venv/lib/python3.10/site-packages/django/db/models/fields/files.py", line 92, in save
    name = self.field.generate_filename(self.instance, name)
  File "test-django-package/venv/lib/python3.10/site-packages/django/db/models/fields/files.py", line 335, in generate_filename
    filename = posixpath.join(dirname, filename)
  File "/usr/lib/python3.10/posixpath.py", line 90, in join
    genericpath._check_arg_types('join', a, *p)
  File "/usr/lib/python3.10/genericpath.py", line 152, in _check_arg_types
    raise TypeError(f'{funcname}() argument must be str, bytes, or '
TypeError: join() argument must be str, bytes, or os.PathLike object, not 'NoneType'

comment:11 by Sarah Boyce, 4 months ago

Patch needs improvement: set

Still don't get the error as reported in the ticket so further details would be welcome

comment:12 by Lucas Esposito, 4 months ago

Patch needs improvement: unset

in reply to:  11 comment:13 by David, 4 months ago

Replying to Sarah Boyce:

Still don't get the error as reported in the ticket so further details would be welcome

Sorry I have miss-interpreted a stack trace of an other error coming from pytest and pasted the wrong part

The stacktrace frame showed up

instance   = <[AttributeError("'InMemoryFileNode' object has no attribute 'name'") raised in repr()] MyModel

Because the model uses attachment.name in its __str__ method.

Whatching back the behaviour now I have isolated a test which fails:

obj = MyModel.objects.create(attachment=ContentFile(b'content', 'myfile.txt'))
obj2 = MyModel.objects.create(attachment=obj.attachment.file)

Which raises the following stacktrace:

Traceback (most recent call last):
  File "<workspace>/db_35658/db_35658/tests.py", line 24, in test_copy_file
    obj2 = MyModel.objects.create(attachment=obj.attachment.file)
  File "<workspace>/db_35658/.venv/lib/python3.10/site-packages/django/db/models/manager.py", line 87, in manager_method
    return getattr(self.get_queryset(), name)(*args, **kwargs)
  File "<workspace>/db_35658/.venv/lib/python3.10/site-packages/django/db/models/query.py", line 658, in create
    obj.save(force_insert=True, using=self.db)
  File "<workspace>/db_35658/.venv/lib/python3.10/site-packages/django/db/models/base.py", line 814, in save
    self.save_base(
  File "<workspace>/db_35658/.venv/lib/python3.10/site-packages/django/db/models/base.py", line 877, in save_base
    updated = self._save_table(
  File "<workspace>/db_35658/.venv/lib/python3.10/site-packages/django/db/models/base.py", line 1020, in _save_table
    results = self._do_insert(
  File "<workspace>/db_35658/.venv/lib/python3.10/site-packages/django/db/models/base.py", line 1061, in _do_insert
    return manager._insert(
  File "<workspace>/db_35658/.venv/lib/python3.10/site-packages/django/db/models/manager.py", line 87, in manager_method
    return getattr(self.get_queryset(), name)(*args, **kwargs)
  File "<workspace>/db_35658/.venv/lib/python3.10/site-packages/django/db/models/query.py", line 1805, in _insert
    return query.get_compiler(using=using).execute_sql(returning_fields)
  File "<workspace>/db_35658/.venv/lib/python3.10/site-packages/django/db/models/sql/compiler.py", line 1821, in execute_sql
    for sql, params in self.as_sql():
  File "<workspace>/db_35658/.venv/lib/python3.10/site-packages/django/db/models/sql/compiler.py", line 1745, in as_sql
    value_rows = [
  File "<workspace>/db_35658/.venv/lib/python3.10/site-packages/django/db/models/sql/compiler.py", line 1746, in <listcomp>
    [
  File "<workspace>/db_35658/.venv/lib/python3.10/site-packages/django/db/models/sql/compiler.py", line 1747, in <listcomp>
    self.prepare_value(field, self.pre_save_val(field, obj))
  File "<workspace>/db_35658/.venv/lib/python3.10/site-packages/django/db/models/sql/compiler.py", line 1695, in pre_save_val
    return field.pre_save(obj, add=True)
  File "<workspace>/db_35658/.venv/lib/python3.10/site-packages/django/db/models/fields/files.py", line 314, in pre_save
    file = super().pre_save(model_instance, add)
  File "<workspace>/db_35658/.venv/lib/python3.10/site-packages/django/db/models/fields/__init__.py", line 932, in pre_save
    return getattr(model_instance, self.attname)
  File "<workspace>/db_35658/.venv/lib/python3.10/site-packages/django/db/models/fields/files.py", line 200, in __get__
    file_copy = self.field.attr_class(instance, self.field, file.name)
AttributeError: 'InMemoryFileNode' object has no attribute 'name'

comment:14 by Sarah Boyce, 3 months ago

Triage Stage: AcceptedReady for checkin

Thank you for the follow up David - that helped a lot!

comment:15 by Sarah Boyce <42296566+sarahboyce@…>, 3 months ago

Resolution: fixed
Status: newclosed

In f16a9a55:

Fixed #35658 -- Initialized InMemoryFileNode instances with a name.

comment:16 by Sarah Boyce <42296566+sarahboyce@…>, 3 months ago

In a57596e:

Refs #35658 -- Fixed test_create_file_field_from_another_file_field_in_memory_storage when run in reverse.

Note: See TracTickets for help on using tickets.
Back to Top