Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 8 additions & 7 deletions s3_file_field/fields.py
Original file line number Diff line number Diff line change
Expand Up @@ -55,13 +55,11 @@ def id(self) -> str:
raise RuntimeError("contribute_to_class has not been called yet on this field.")
return str(self)

def contribute_to_class(
self, cls: type[models.Model], name: str, private_only: bool = False
) -> None:
def contribute_to_class(self, cls, name, **kwargs):
# This is executed when the Field is formally added to its containing class.
# As a side effect, self.name is set and self.__str__ becomes usable as a unique
# identifier for the Field.
super().contribute_to_class(cls, name, private_only=private_only)
super().contribute_to_class(cls, name, **kwargs)
if cls.__module__ != "__fake__":
# Django's makemigrations iteratively creates fake model instances.
# To avoid registration collisions, don't register these.
Expand All @@ -76,7 +74,7 @@ def formfield(
form_class: type[forms.Field] | None = None,
choices_form_class: type[forms.ChoiceField] | None = None,
**kwargs: Any,
) -> forms.Field | None:
) -> forms.Field:
"""
Return a forms.Field instance for this model field.

Expand All @@ -100,8 +98,11 @@ def save_form_data(self, instance: models.Model, data) -> None:
# However, we don't want the S3FileInput or S3FormFileField to emit a string value,
# since that will break most of the default validation.
if isinstance(data, S3PlaceholderFile):
data = data.name
super().save_form_data(instance, data)
# For S3PlaceholderFile, directly set the field value to avoid Django 5.1's
# new file validation that expects file objects to have proper attributes
setattr(instance, self.attname, data.name)
else:
super().save_form_data(instance, data)

def check(self, **kwargs: Any) -> list[CheckMessage]:
return [
Expand Down
20 changes: 20 additions & 0 deletions tests/test_fields.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import pytest

from test_app.models import Resource
from s3_file_field.widgets import S3PlaceholderFile


@pytest.mark.django_db()
Expand Down Expand Up @@ -62,3 +63,22 @@ def test_fields_clean_empty() -> None:

def test_fields_check_success(resource: Resource) -> None:
assert resource._meta.get_field("blob").check() == []


def test_s3_placeholder_file_save_form_data() -> None:
resource = Resource()
blob_field = resource._meta.get_field("blob")
placeholder_file = S3PlaceholderFile(name="test-file.txt")
blob_field.save_form_data(resource, placeholder_file)
assert getattr(resource, blob_field.attname) == "test-file.txt"


@pytest.mark.django_db()
def test_s3_placeholder_file_save_form_data_with_save() -> None:
resource = Resource()
blob_field = resource._meta.get_field("blob")
placeholder_file = S3PlaceholderFile(name="test-file-save.txt")
blob_field.save_form_data(resource, placeholder_file)
resource.save()
resource.refresh_from_db()
assert resource.blob.name == "test-file-save.txt"