Skip to content

Commit

Permalink
Fix #498 -- Reset GFK fields when content object is None (#499)
Browse files Browse the repository at this point in the history
  • Loading branch information
amureki authored Aug 26, 2024
1 parent 2121a08 commit 8b60451
Show file tree
Hide file tree
Showing 4 changed files with 38 additions and 11 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
### Added

### Changed
- Reset `content_type` and `object_id` fields when the content object is `None`

### Removed

Expand Down
28 changes: 17 additions & 11 deletions model_bakery/baker.py
Original file line number Diff line number Diff line change
Expand Up @@ -695,21 +695,27 @@ def _handle_m2m(self, instance: Model):
def _handle_generic_foreign_keys(self, instance: Model, attrs: Dict[str, Any]):
"""Set content type and object id for GenericForeignKey fields."""
for field_name, data in attrs.items():
content_type_field = data["content_type_field"]
object_id_field = data["object_id_field"]
ct_field_name = data["content_type_field"]
oid_field_name = data["object_id_field"]
value = data["value"]
if is_iterator(value):
value = next(value)
if value is None:
continue

setattr(instance, field_name, value)
setattr(
instance,
content_type_field,
contenttypes_models.ContentType.objects.get_for_model(value),
)
setattr(instance, object_id_field, value.pk)
# when GFK is None, we should try to set the content type and object id to None
content_type_field = instance._meta.get_field(ct_field_name)
object_id_field = instance._meta.get_field(oid_field_name)
if content_type_field.null:
setattr(instance, ct_field_name, None)
if object_id_field.null:
setattr(instance, oid_field_name, None)
else:
setattr(instance, field_name, value)
setattr(
instance,
ct_field_name,
contenttypes_models.ContentType.objects.get_for_model(value),
)
setattr(instance, oid_field_name, value.pk)

def _remote_field(
self, field: Union[ForeignKey, OneToOneField]
Expand Down
10 changes: 10 additions & 0 deletions tests/generic/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -295,6 +295,16 @@ class DummyGenericForeignKeyModel(models.Model):
class DummyGenericRelationModel(models.Model):
relation = GenericRelation(DummyGenericForeignKeyModel)

class GenericForeignKeyModelWithOptionalData(models.Model):
content_type = models.ForeignKey(
contenttypes.ContentType, on_delete=models.CASCADE, blank=True, null=True
)
object_id = models.PositiveIntegerField(blank=True, null=True)
content_object = GenericForeignKey("content_type", "object_id")

class GenericRelationModelWithOptionalData(models.Model):
relation = GenericRelation(GenericForeignKeyModelWithOptionalData)


class DummyNullFieldsModel(models.Model):
null_foreign_key = models.ForeignKey(
Expand Down
10 changes: 10 additions & 0 deletions tests/test_filling_fields.py
Original file line number Diff line number Diff line change
Expand Up @@ -374,6 +374,16 @@ def test_with_fill_optional(self):
assert isinstance(dummy.content_type, ContentType)
assert dummy.content_type.model_class() is not None

def test_with_fill_optional_but_content_object_none(self):
dummy = baker.make(
models.GenericForeignKeyModelWithOptionalData,
content_object=None,
_fill_optional=True,
)
assert dummy.content_object is None
assert dummy.content_type is None
assert dummy.object_id is None


@pytest.mark.django_db
class TestFillingForeignKeyFieldWithDefaultFunctionReturningId:
Expand Down

0 comments on commit 8b60451

Please sign in to comment.