Temporarily disable auto_now and auto_now_add option in Django's DateField and DateTimeField, so that you can save the desired value to these fields.
Project description
django-override-autonow is a testing tool for Django’s project. django-override-autonow makes it easy to create model instance using DateField or DateTimeField with auto_now or auto_now_add options.
An example of django’s model:
from django.db import models
class Order(models.Model):
amount = models.IntegerField()
status = models.CharField(max_length=100)
created_time = models.DateTimeField(auto_now_add=True)
updated_time = models.DateTimeField(auto_now=True)
To test this model:
from unittest import mock
from django.test import TestCase
from django.utils import timezone
from override_autonow import override_autonow
from .models import Order
class TestOrder(TestCase):
@override_autonow
def test_with_django_override_autonow(self):
# We need a order with desired created_time and updated_time for test
order = Order.objects.create(
amount=200,
status='PAID',
created_time=timezone.datetime(year=2022, month=1, day=1, hour=23, minute=59, second=59),
updated_time=timezone.datetime(year=2022, month=1, day=2, hour=0, minute=0, second=0),
)
# test order
def test_without_django_override_autonow(self):
# Django's standard way is to mock timezone.now and save the model.
# First, create object with mocking timezone.now and set desired value to created_time field
with mock.patch('django.db.models.fields.timezone') as mock_timezone:
mock_timezone.now.return_value = timezone.datetime(year=2022, month=1, day=1, hour=23, minute=59, second=59)
order = Order.objects.create(
amount=200,
status='PAID',
)
# Second, save object again with mocking timezone.now and set desired value to updated_time field
with mock.patch('django.db.models.fields.timezone') as mock_timezone:
mock_timezone.now.return_value = timezone.datetime(year=2022, month=1, day=2, hour=0, minute=0, second=0)
order.save()
# test order
Features
Support Django 2.2+ and Python 3.7+
- Compatible with major testing packages
pytest’s class based test and function based test with pytest-django
factory-boy’s model factory
- Choose suitable style for your situation
Method decorator
Class decorator
Context manager
- Flexible override target selection
Affects only specified field names and exclude specified field names
Affects only specified models and exclude specified field names
Affects only auto_now option or auto_now_add option
Affects only DateField or DateTimeField
Installation
Installing from PyPI:
pip install django-override-autonow
Use Cases
Test with Django’s TestCase:
from django.test import TestCase
from override_autonow import override_autonow
from .models import Order
class TestOrder(TestCase):
# as method decorator
@override_autonow
def test_with_method_decorator(self):
order = Order.objects.create(
amount=200,
status='PAID',
created_time=timezone.datetime(year=2022, month=1, day=1, hour=23, minute=59, second=59),
updated_time=timezone.datetime(year=2022, month=1, day=2, hour=0, minute=0, second=0),
)
# test order
def test_with_context_manager(self):
# as context manager
with override_autonow():
order_with_override = Order.objects.create(
amount=200,
status='PAID',
created_time=timezone.datetime(year=2022, month=1, day=1, hour=23, minute=59, second=59),
updated_time=timezone.datetime(year=2022, month=1, day=2, hour=0, minute=0, second=0),
)
order_without_override = Order.objects.create(
amount=200,
status='PAID',
)
# test order
# as class decorator
@override_autonow
class TestWithClassDecorator(TestCase):
def test_with_class_decorator(self):
order = Order.objects.create(
amount=200,
status='PAID',
created_time=timezone.datetime(year=2022, month=1, day=1, hour=23, minute=59, second=59),
updated_time=timezone.datetime(year=2022, month=1, day=2, hour=0, minute=0, second=0),
)
# test order
Test with pytest(pytest-django):
import pytest
from override_autonow import override_autonow
from .models import Order
@pytest.mark.django_db
class TestOrder:
# as method decorator
@override_autonow
def test_with_method_decorator(self):
order = Order.objects.create(
amount=200,
status='PAID',
created_time=timezone.datetime(year=2022, month=1, day=1, hour=23, minute=59, second=59),
updated_time=timezone.datetime(year=2022, month=1, day=2, hour=0, minute=0, second=0),
)
# test order
def test_with_context_manager(self):
# as context manager
with override_autonow():
order_without_autonow = Order.objects.create(
amount=200,
status='PAID',
created_time=timezone.datetime(year=2022, month=1, day=1, hour=23, minute=59, second=59),
updated_time=timezone.datetime(year=2022, month=1, day=2, hour=0, minute=0, second=0),
)
order_with_autonow = Order.objects.create(
amount=200,
status='PAID',
)
# test order
# as class decorator
@override_autonow
@pytest.mark.django_db
class TestWithClassDecorator:
def test_with_class_decorator(self):
order = Order.objects.create(
amount=200,
status='PAID',
created_time=timezone.datetime(year=2022, month=1, day=1, hour=23, minute=59, second=59),
updated_time=timezone.datetime(year=2022, month=1, day=2, hour=0, minute=0, second=0),
)
# test order
Override specific targets:
from django.test import TestCase
from override_autonow import override_autonow
from .models import Order
class TestOrder(TestCase):
@override_autonow(exclude_auto_now=True)
def test_exclude_auto_now_option(self):
# Override only auto_now_add option
...
@override_autonow(exclude_auto_now_add=True)
def test_exclude_auto_now_add_option(self):
# Override only auto_now option
...
@override_autonow(exclude_date_field=True)
def test_exclude_date_field(self):
# Override only DateTimeField
...
@override_autonow(exclude_datetime_field=True)
def test_exclude_datetime_field(self):
# Override only DateField
...
@override_autonow(exclude_field_names={'created_time'})
def test_exclude_field_names(self):
# Override except fields named created_time
...
@override_autonow(exclude_models=(Order,))
def test_exclude_models(self):
# Override except the Order model
...
@override_autonow(override_field_names={'created_time'})
def test_override_field_names(self):
# Override only fields named created_time
...
@override_autonow(override_models=(Order,))
def test_override_models(self):
# Override only the Order model
...
Test with factory-bot:
from django.test import TestCase
from django.utils import timezone
from factory.django import DjangoModelFactory
from override_autonow import override_autonow
from .models import Order
class OrderFactory:
class Meta:
model = Order
amount = 200,
status = 'PAID',
created_time = timezone.datetime(year=2022, month=1, day=1, hour=23, minute=59, second=59)
updated_time = timezone.datetime(year=2022, month=1, day=2, hour=0, minute=0, second=0)
class TestOrder(TestCase):
@override_autonow
def test_with_method_decorator(self):
# Override created_time and updated_time with factory
order = OrderFactory()
# test order
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Hashes for django-override-autonow-0.0.1.tar.gz
Algorithm | Hash digest | |
---|---|---|
SHA256 | 017c39a926851a9ae070cb9ade39be8e7ead88a834e284016b6014f0050629f7 |
|
MD5 | 633160d800dec7ac7e3063e334c0d293 |
|
BLAKE2b-256 | b10ee02cd80245c7b69ea79adf2120d90a662c93d7b461e177ad79f69e6c7dc3 |
Hashes for django_override_autonow-0.0.1-py3-none-any.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | cd838fd3a27859721c22b4e034c1993a3bb5ee500403499be4620c9223ac0108 |
|
MD5 | a5e25c277aab050a20943cc89abf6d80 |
|
BLAKE2b-256 | 08f629ee4148c46c98352ef98d74207f9ab9ab5c9674252b196524233d8501b8 |