Skip to content

Commit

Permalink
Can't set the value of a DateTimeField with auto_now or auto_now_add #23
Browse files Browse the repository at this point in the history
 (#451)


---------

Co-authored-by: Rust Saiargaliev <fly.amureki@gmail.com>
  • Loading branch information
rodbv and amureki committed Oct 27, 2023
1 parent 532597b commit 2a33cef
Show file tree
Hide file tree
Showing 4 changed files with 49 additions and 0 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
## [Unreleased](https://github.com/model-bakers/model_bakery/tree/main)

### Added
- Add support to `auto_now` and `auto_now_add` fields.

### Changed
- Remove unnecessary casting to string methods random_gen.gen_slug and random_gen.gen_string
Expand Down
19 changes: 19 additions & 0 deletions model_bakery/baker.py
Original file line number Diff line number Diff line change
Expand Up @@ -498,17 +498,30 @@ def instance(
self, attrs: Dict[str, Any], _commit, _save_kwargs, _from_manager
) -> M:
one_to_many_keys = {}
auto_now_keys = {}

for k in tuple(attrs.keys()):
field = getattr(self.model, k, None)

if not field:
continue

if isinstance(field, ForeignRelatedObjectsDescriptor):
one_to_many_keys[k] = attrs.pop(k)

if hasattr(field, "field") and (
getattr(field.field, "auto_now_add", False)
or getattr(field.field, "auto_now", False)
):
auto_now_keys[k] = attrs[k]

instance = self.model(**attrs)
# m2m only works for persisted instances
if _commit:
instance.save(**_save_kwargs)
self._handle_one_to_many(instance, one_to_many_keys)
self._handle_m2m(instance)
self._handle_auto_now(instance, auto_now_keys)

if _from_manager:
# Fetch the instance using the given Manager, e.g.
Expand Down Expand Up @@ -609,6 +622,12 @@ def _skip_field(self, field: Field) -> bool:

return False

def _handle_auto_now(self, instance: Model, attrs: Dict[str, Any]):
if not attrs:
return

instance.__class__.objects.filter(pk=instance.pk).update(**attrs)

def _handle_one_to_many(self, instance: Model, attrs: Dict[str, Any]):
for key, values in attrs.items():
manager = getattr(instance, key)
Expand Down
6 changes: 6 additions & 0 deletions tests/generic/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -472,3 +472,9 @@ class Issue291Model3(models.Model):
Issue291Model2, related_name="bazs", on_delete=models.CASCADE
)
name = models.CharField(max_length=32)


class ModelWithAutoNowFields(models.Model):
sent_date = models.DateTimeField()
created = models.DateTimeField(auto_now_add=True)
updated = models.DateTimeField(auto_now=True)
23 changes: 23 additions & 0 deletions tests/test_baker.py
Original file line number Diff line number Diff line change
Expand Up @@ -1069,3 +1069,26 @@ def test_seed(self, reset_seed):
@pytest.mark.django_db
def test_unseeded(self):
assert baker.Baker._global_seed is baker.Baker.SENTINEL


class TestAutoNowFields:
@pytest.mark.django_db
@pytest.mark.parametrize("use_tz", [False, True])
def test_make_with_auto_now(self, use_tz, settings):
settings.USE_TZ = use_tz
tzinfo = datetime.timezone.utc if use_tz else None

now = datetime.datetime(2023, 10, 20, 15, 30).replace(tzinfo=tzinfo)

instance = baker.make(
models.ModelWithAutoNowFields,
created=now,
updated=now,
sent_date=now,
)

instance.refresh_from_db()

assert instance.created == now
assert instance.updated == now
assert instance.sent_date == now

0 comments on commit 2a33cef

Please sign in to comment.