In your test case, actually the field itself is an ImageField.
If you look at the _meta.fields
attribute of the model, you will see it shows <class 'django.db.models.fields.files.ImageField'>
If you do something like type(instance.image)
, it will report as a FieldFile. But this does not mean that image
is a FieldFile. What it’s telling you is that what you get from the instance
class when you reference image
is a FieldFile. (This is the Model’s ModelBase “metaprogramming magic” at work.)
Consider the following class:
class TestClass:
def __init__(self, x):
self.x = x
def __getattribute__(self, attr):
return str(super().__getattribute__(attr))
Now, if I do the following in a python shell:
>>> t = TestClass(3)
>>> t.x
'3'
>>> type(t.x)
<class 'str'>
Does this now mean that the x
in this instance of TestClass is now a string? No, t.x is still an integer. Despite that, everything that I reference using that name gives me a string.
(Also, a dir(t)
is going to return an empty list, which is vastly different than if you do a dir on any regular class.)
If by “failing” you mean that it doesn’t write a file without a name and without returning some type of error, my initial reaction would have been no, I would not have expected it to behave like this.
However, I’ve worked with Django long enough at this point to work from the perspective that if something is happening that I don’t understand, it’s my understanding that is lacking. My baseline is that things are generally done for a reason, even if I don’t know what that is, or can’t think of one.
<conjecture>
This could be related to the requirements associated with “storages”, or it may be related to the behavior of the underlying Python libraries.
</conjecture>
Note: I have discovered that if you assign a name to the instance.image.name attribute, it does save the file and can subsequently be retrieved.
(e.g., instance.image.name = "test-file.gif"
before the instance.save()
.)
Side note: I can’t recreate the error you’re describing. If I follow the steps you’re describing in your last post, including using refresh_from_db
I get the same empty string from instance.image.name
, I do not get an error. This is with Django 5.0.2 / Python 3.12.1. Might there be some platform / version issue involved here?