Skip to content

Commit

Permalink
Get ManyToOneRel fields (reverse FK) back to work (#300)
Browse files Browse the repository at this point in the history
* Get ManyToOneRel fields (reverse FK) back to work

* Update changelog

* Run linter

* Grammar fix 1

Co-authored-by: Tim Klein <timjklein36@gmail.com>

* Grammar fix 2

Co-authored-by: Tim Klein <timjklein36@gmail.com>

* Code linter

Co-authored-by: Tim Klein <timjklein36@gmail.com>
  • Loading branch information
berinhard and timjklein36 committed Mar 31, 2022
1 parent f10d0a2 commit 42bc039
Show file tree
Hide file tree
Showing 4 changed files with 47 additions and 1 deletion.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Expand Up @@ -15,10 +15,12 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
- Extend type hints in `model_bakery.recipe` module, make `Recipe` class generic [PR #292](https://github.com/model-bakers/model_bakery/pull/292)
- Explicitly add _fill_optional parameters to baker.make and baker.prepare to aid IDE autocomplete function. [PR #264](https://github.com/model-bakers/model_bakery/pull/264)
- Fixed errors with reverse M2M relationships [PR #299](https://github.com/model-bakers/model_bakery/pull/299)
- Fixed errors with reverse M2O relationships [PR #300](https://github.com/model-bakers/model_bakery/pull/300)
- Improve exception message for unknown field types [PR #301](https://github.com/model-bakers/model_bakery/pull/301)

### Removed


## [1.4.0](https://pypi.org/project/model-bakery/1.4.0/)

### Added
Expand Down
13 changes: 12 additions & 1 deletion model_bakery/baker.py
Expand Up @@ -606,7 +606,18 @@ def _handle_one_to_many(self, instance: Model, attrs: Dict[str, Any]):
manager = getattr(instance, key)

for value in values:
if not value.pk:
# Django will handle any operation to persist nested non-persisted FK because
# save doesn't do so and, thus, raises constraint errors. That's why save()
# only gets called if the object doesn't have a pk and also doesn't hold fk
# pointers.
fks = any(
[
fk
for fk in value._meta.fields
if isinstance(fk, ForeignKey) or isinstance(fk, OneToOneField)
]
)
if not value.pk and not fks:
value.save()

try:
Expand Down
17 changes: 17 additions & 0 deletions tests/generic/models.py
Expand Up @@ -455,3 +455,20 @@ class NonStandardManager(models.Model):
name = models.CharField(max_length=30)

manager = models.Manager()


# The followin models were added after issue 291
# Since they don't hold much meaning, they are only numbered ones
class Issue291Model1(models.Model):
pass


class Issue291Model2(models.Model):
m2m_model_1 = models.ManyToManyField(Issue291Model1)


class Issue291Model3(models.Model):
fk_model_2 = models.ForeignKey(
Issue291Model2, related_name="bazs", on_delete=models.CASCADE
)
name = models.CharField(max_length=32)
16 changes: 16 additions & 0 deletions tests/test_baker.py
Expand Up @@ -569,6 +569,22 @@ def test_field_lookup_for_related_field_does_not_work_with_prepare(self):
assert not person.pk
assert 0 == models.RelatedNamesModel.objects.count()

def test_ensure_reverse_fk_for_many_to_one_is_working(self):
"""This is a regression test to make sure issue 291 is fixed"""
fk1, fk2 = baker.prepare(
models.Issue291Model3, fk_model_2=None, name="custom name", _quantity=2
)
obj = baker.make(
models.Issue291Model2,
m2m_model_1=[baker.make(models.Issue291Model1)],
bazs=[fk1, fk2],
)

assert obj.bazs.count() == 2
related_1, related_2 = obj.bazs.all()
assert related_1.name == "custom name"
assert related_2.name == "custom name"


@pytest.mark.django_db
class TestHandlingUnsupportedModels:
Expand Down

0 comments on commit 42bc039

Please sign in to comment.