Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Get ManyToOneRel fields (reverse FK) back to work #300

Merged
merged 7 commits into from Mar 31, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
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