From 272d6e7437dc4543e8f4c41a66637c371c236411 Mon Sep 17 00:00:00 2001 From: jeremystretch Date: Tue, 8 Feb 2022 14:41:44 -0500 Subject: [PATCH] Closes #8463: Change the created field on all change-logged models from date to datetime --- docs/release-notes/version-3.2.md | 2 + .../migrations/0034_created_datetimefield.py | 38 ++++ .../migrations/0153_created_datetimefield.py | 208 ++++++++++++++++++ .../migrations/0072_created_datetimefield.py | 53 +++++ netbox/extras/models/models.py | 7 - .../migrations/0057_created_datetimefield.py | 88 ++++++++ netbox/netbox/filtersets.py | 6 +- netbox/netbox/models/features.py | 2 +- .../migrations/0006_created_datetimefield.py | 43 ++++ netbox/utilities/testing/filtersets.py | 8 +- .../migrations/0029_created_datetimefield.py | 38 ++++ .../migrations/0003_created_datetimefield.py | 28 +++ 12 files changed, 506 insertions(+), 15 deletions(-) create mode 100644 netbox/circuits/migrations/0034_created_datetimefield.py create mode 100644 netbox/dcim/migrations/0153_created_datetimefield.py create mode 100644 netbox/extras/migrations/0072_created_datetimefield.py create mode 100644 netbox/ipam/migrations/0057_created_datetimefield.py create mode 100644 netbox/tenancy/migrations/0006_created_datetimefield.py create mode 100644 netbox/virtualization/migrations/0029_created_datetimefield.py create mode 100644 netbox/wireless/migrations/0003_created_datetimefield.py diff --git a/docs/release-notes/version-3.2.md b/docs/release-notes/version-3.2.md index 8fc733e04..1c97e9570 100644 --- a/docs/release-notes/version-3.2.md +++ b/docs/release-notes/version-3.2.md @@ -11,6 +11,7 @@ * The `asn` field has been removed from the site model. Please replicate any site ASN assignments to the ASN model introduced in NetBox v3.1 prior to upgrading. * The `asn` query filter for sites now matches against the AS number of assigned ASN objects. * The `contact_name`, `contact_phone`, and `contact_email` fields have been removed from the site model. Please replicate any data remaining in these fields to the contact model introduced in NetBox v3.1 prior to upgrading. +* The `created` field of all change-logged models now conveys a full datetime object, rather than only a date. (Previous date-only values will receive a timestamp of 00:00.) While this change is largely innocuous, strictly-typed API consumers may need to be updated. * A `pre_run()` method has been added to the base Report class. While unlikely to affect most installations, you may need to alter any reports which already use this name for a method. ### New Features @@ -130,6 +131,7 @@ A new REST API endpoint has been added at `/api/ipam/vlan-groups//available- * [#8295](https://github.com/netbox-community/netbox/issues/8295) - Jinja2 rendering is now supported for webhook URLs * [#8296](https://github.com/netbox-community/netbox/issues/8296) - Allow disabling custom links * [#8307](https://github.com/netbox-community/netbox/issues/8307) - Add `data_type` indicator to REST API serializer for custom fields +* [#8463](https://github.com/netbox-community/netbox/issues/8463) - Change the `created` field on all change-logged models from date to datetime * [#8572](https://github.com/netbox-community/netbox/issues/8572) - Add a `pre_run()` method for reports ### Other Changes diff --git a/netbox/circuits/migrations/0034_created_datetimefield.py b/netbox/circuits/migrations/0034_created_datetimefield.py new file mode 100644 index 000000000..4af78c1a2 --- /dev/null +++ b/netbox/circuits/migrations/0034_created_datetimefield.py @@ -0,0 +1,38 @@ +# Generated by Django 4.0.2 on 2022-02-08 18:54 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('circuits', '0033_standardize_id_fields'), + ] + + operations = [ + migrations.AlterField( + model_name='circuit', + name='created', + field=models.DateTimeField(auto_now_add=True, null=True), + ), + migrations.AlterField( + model_name='circuittermination', + name='created', + field=models.DateTimeField(auto_now_add=True, null=True), + ), + migrations.AlterField( + model_name='circuittype', + name='created', + field=models.DateTimeField(auto_now_add=True, null=True), + ), + migrations.AlterField( + model_name='provider', + name='created', + field=models.DateTimeField(auto_now_add=True, null=True), + ), + migrations.AlterField( + model_name='providernetwork', + name='created', + field=models.DateTimeField(auto_now_add=True, null=True), + ), + ] diff --git a/netbox/dcim/migrations/0153_created_datetimefield.py b/netbox/dcim/migrations/0153_created_datetimefield.py new file mode 100644 index 000000000..c1cc4132e --- /dev/null +++ b/netbox/dcim/migrations/0153_created_datetimefield.py @@ -0,0 +1,208 @@ +# Generated by Django 4.0.2 on 2022-02-08 18:54 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('dcim', '0152_standardize_id_fields'), + ] + + operations = [ + migrations.AlterField( + model_name='cable', + name='created', + field=models.DateTimeField(auto_now_add=True, null=True), + ), + migrations.AlterField( + model_name='consoleport', + name='created', + field=models.DateTimeField(auto_now_add=True, null=True), + ), + migrations.AlterField( + model_name='consoleporttemplate', + name='created', + field=models.DateTimeField(auto_now_add=True, null=True), + ), + migrations.AlterField( + model_name='consoleserverport', + name='created', + field=models.DateTimeField(auto_now_add=True, null=True), + ), + migrations.AlterField( + model_name='consoleserverporttemplate', + name='created', + field=models.DateTimeField(auto_now_add=True, null=True), + ), + migrations.AlterField( + model_name='device', + name='created', + field=models.DateTimeField(auto_now_add=True, null=True), + ), + migrations.AlterField( + model_name='devicebay', + name='created', + field=models.DateTimeField(auto_now_add=True, null=True), + ), + migrations.AlterField( + model_name='devicebaytemplate', + name='created', + field=models.DateTimeField(auto_now_add=True, null=True), + ), + migrations.AlterField( + model_name='devicerole', + name='created', + field=models.DateTimeField(auto_now_add=True, null=True), + ), + migrations.AlterField( + model_name='devicetype', + name='created', + field=models.DateTimeField(auto_now_add=True, null=True), + ), + migrations.AlterField( + model_name='frontport', + name='created', + field=models.DateTimeField(auto_now_add=True, null=True), + ), + migrations.AlterField( + model_name='frontporttemplate', + name='created', + field=models.DateTimeField(auto_now_add=True, null=True), + ), + migrations.AlterField( + model_name='interface', + name='created', + field=models.DateTimeField(auto_now_add=True, null=True), + ), + migrations.AlterField( + model_name='interfacetemplate', + name='created', + field=models.DateTimeField(auto_now_add=True, null=True), + ), + migrations.AlterField( + model_name='inventoryitem', + name='created', + field=models.DateTimeField(auto_now_add=True, null=True), + ), + migrations.AlterField( + model_name='inventoryitemrole', + name='created', + field=models.DateTimeField(auto_now_add=True, null=True), + ), + migrations.AlterField( + model_name='inventoryitemtemplate', + name='created', + field=models.DateTimeField(auto_now_add=True, null=True), + ), + migrations.AlterField( + model_name='location', + name='created', + field=models.DateTimeField(auto_now_add=True, null=True), + ), + migrations.AlterField( + model_name='manufacturer', + name='created', + field=models.DateTimeField(auto_now_add=True, null=True), + ), + migrations.AlterField( + model_name='module', + name='created', + field=models.DateTimeField(auto_now_add=True, null=True), + ), + migrations.AlterField( + model_name='modulebay', + name='created', + field=models.DateTimeField(auto_now_add=True, null=True), + ), + migrations.AlterField( + model_name='modulebaytemplate', + name='created', + field=models.DateTimeField(auto_now_add=True, null=True), + ), + migrations.AlterField( + model_name='moduletype', + name='created', + field=models.DateTimeField(auto_now_add=True, null=True), + ), + migrations.AlterField( + model_name='platform', + name='created', + field=models.DateTimeField(auto_now_add=True, null=True), + ), + migrations.AlterField( + model_name='powerfeed', + name='created', + field=models.DateTimeField(auto_now_add=True, null=True), + ), + migrations.AlterField( + model_name='poweroutlet', + name='created', + field=models.DateTimeField(auto_now_add=True, null=True), + ), + migrations.AlterField( + model_name='poweroutlettemplate', + name='created', + field=models.DateTimeField(auto_now_add=True, null=True), + ), + migrations.AlterField( + model_name='powerpanel', + name='created', + field=models.DateTimeField(auto_now_add=True, null=True), + ), + migrations.AlterField( + model_name='powerport', + name='created', + field=models.DateTimeField(auto_now_add=True, null=True), + ), + migrations.AlterField( + model_name='powerporttemplate', + name='created', + field=models.DateTimeField(auto_now_add=True, null=True), + ), + migrations.AlterField( + model_name='rack', + name='created', + field=models.DateTimeField(auto_now_add=True, null=True), + ), + migrations.AlterField( + model_name='rackreservation', + name='created', + field=models.DateTimeField(auto_now_add=True, null=True), + ), + migrations.AlterField( + model_name='rackrole', + name='created', + field=models.DateTimeField(auto_now_add=True, null=True), + ), + migrations.AlterField( + model_name='rearport', + name='created', + field=models.DateTimeField(auto_now_add=True, null=True), + ), + migrations.AlterField( + model_name='rearporttemplate', + name='created', + field=models.DateTimeField(auto_now_add=True, null=True), + ), + migrations.AlterField( + model_name='region', + name='created', + field=models.DateTimeField(auto_now_add=True, null=True), + ), + migrations.AlterField( + model_name='site', + name='created', + field=models.DateTimeField(auto_now_add=True, null=True), + ), + migrations.AlterField( + model_name='sitegroup', + name='created', + field=models.DateTimeField(auto_now_add=True, null=True), + ), + migrations.AlterField( + model_name='virtualchassis', + name='created', + field=models.DateTimeField(auto_now_add=True, null=True), + ), + ] diff --git a/netbox/extras/migrations/0072_created_datetimefield.py b/netbox/extras/migrations/0072_created_datetimefield.py new file mode 100644 index 000000000..827e99e54 --- /dev/null +++ b/netbox/extras/migrations/0072_created_datetimefield.py @@ -0,0 +1,53 @@ +# Generated by Django 4.0.2 on 2022-02-08 18:54 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('extras', '0071_standardize_id_fields'), + ] + + operations = [ + migrations.AlterField( + model_name='configcontext', + name='created', + field=models.DateTimeField(auto_now_add=True, null=True), + ), + migrations.AlterField( + model_name='customfield', + name='created', + field=models.DateTimeField(auto_now_add=True, null=True), + ), + migrations.AlterField( + model_name='customlink', + name='created', + field=models.DateTimeField(auto_now_add=True, null=True), + ), + migrations.AlterField( + model_name='exporttemplate', + name='created', + field=models.DateTimeField(auto_now_add=True, null=True), + ), + migrations.AlterField( + model_name='imageattachment', + name='created', + field=models.DateTimeField(auto_now_add=True, null=True), + ), + migrations.AlterField( + model_name='journalentry', + name='created', + field=models.DateTimeField(auto_now_add=True, null=True), + ), + migrations.AlterField( + model_name='tag', + name='created', + field=models.DateTimeField(auto_now_add=True, null=True), + ), + migrations.AlterField( + model_name='webhook', + name='created', + field=models.DateTimeField(auto_now_add=True, null=True), + ), + ] diff --git a/netbox/extras/models/models.py b/netbox/extras/models/models.py index afcb6556c..9cbacca6a 100644 --- a/netbox/extras/models/models.py +++ b/netbox/extras/models/models.py @@ -367,10 +367,6 @@ class ImageAttachment(WebhooksMixin, ChangeLoggedModel): max_length=50, blank=True ) - # ChangeLoggingMixin.created is a DateField - created = models.DateTimeField( - auto_now_add=True - ) objects = RestrictedQuerySet.as_manager() @@ -438,9 +434,6 @@ class JournalEntry(WebhooksMixin, ChangeLoggedModel): ct_field='assigned_object_type', fk_field='assigned_object_id' ) - created = models.DateTimeField( - auto_now_add=True - ) created_by = models.ForeignKey( to=User, on_delete=models.SET_NULL, diff --git a/netbox/ipam/migrations/0057_created_datetimefield.py b/netbox/ipam/migrations/0057_created_datetimefield.py new file mode 100644 index 000000000..f2ca7ab95 --- /dev/null +++ b/netbox/ipam/migrations/0057_created_datetimefield.py @@ -0,0 +1,88 @@ +# Generated by Django 4.0.2 on 2022-02-08 18:54 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('ipam', '0056_standardize_id_fields'), + ] + + operations = [ + migrations.AlterField( + model_name='aggregate', + name='created', + field=models.DateTimeField(auto_now_add=True, null=True), + ), + migrations.AlterField( + model_name='asn', + name='created', + field=models.DateTimeField(auto_now_add=True, null=True), + ), + migrations.AlterField( + model_name='fhrpgroup', + name='created', + field=models.DateTimeField(auto_now_add=True, null=True), + ), + migrations.AlterField( + model_name='fhrpgroupassignment', + name='created', + field=models.DateTimeField(auto_now_add=True, null=True), + ), + migrations.AlterField( + model_name='ipaddress', + name='created', + field=models.DateTimeField(auto_now_add=True, null=True), + ), + migrations.AlterField( + model_name='iprange', + name='created', + field=models.DateTimeField(auto_now_add=True, null=True), + ), + migrations.AlterField( + model_name='prefix', + name='created', + field=models.DateTimeField(auto_now_add=True, null=True), + ), + migrations.AlterField( + model_name='rir', + name='created', + field=models.DateTimeField(auto_now_add=True, null=True), + ), + migrations.AlterField( + model_name='role', + name='created', + field=models.DateTimeField(auto_now_add=True, null=True), + ), + migrations.AlterField( + model_name='routetarget', + name='created', + field=models.DateTimeField(auto_now_add=True, null=True), + ), + migrations.AlterField( + model_name='service', + name='created', + field=models.DateTimeField(auto_now_add=True, null=True), + ), + migrations.AlterField( + model_name='servicetemplate', + name='created', + field=models.DateTimeField(auto_now_add=True, null=True), + ), + migrations.AlterField( + model_name='vlan', + name='created', + field=models.DateTimeField(auto_now_add=True, null=True), + ), + migrations.AlterField( + model_name='vlangroup', + name='created', + field=models.DateTimeField(auto_now_add=True, null=True), + ), + migrations.AlterField( + model_name='vrf', + name='created', + field=models.DateTimeField(auto_now_add=True, null=True), + ), + ] diff --git a/netbox/netbox/filtersets.py b/netbox/netbox/filtersets.py index e36b9dd1d..3cfd226b0 100644 --- a/netbox/netbox/filtersets.py +++ b/netbox/netbox/filtersets.py @@ -197,12 +197,12 @@ class BaseFilterSet(django_filters.FilterSet): class ChangeLoggedModelFilterSet(BaseFilterSet): - created = django_filters.DateFilter() - created__gte = django_filters.DateFilter( + created = django_filters.DateTimeFilter() + created__gte = django_filters.DateTimeFilter( field_name='created', lookup_expr='gte' ) - created__lte = django_filters.DateFilter( + created__lte = django_filters.DateTimeFilter( field_name='created', lookup_expr='lte' ) diff --git a/netbox/netbox/models/features.py b/netbox/netbox/models/features.py index 24b9a4bff..e443dde5f 100644 --- a/netbox/netbox/models/features.py +++ b/netbox/netbox/models/features.py @@ -33,7 +33,7 @@ class ChangeLoggingMixin(models.Model): """ Provides change logging support for a model. Adds the `created` and `last_updated` fields. """ - created = models.DateField( + created = models.DateTimeField( auto_now_add=True, blank=True, null=True diff --git a/netbox/tenancy/migrations/0006_created_datetimefield.py b/netbox/tenancy/migrations/0006_created_datetimefield.py new file mode 100644 index 000000000..a972809e2 --- /dev/null +++ b/netbox/tenancy/migrations/0006_created_datetimefield.py @@ -0,0 +1,43 @@ +# Generated by Django 4.0.2 on 2022-02-08 18:54 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('tenancy', '0005_standardize_id_fields'), + ] + + operations = [ + migrations.AlterField( + model_name='contact', + name='created', + field=models.DateTimeField(auto_now_add=True, null=True), + ), + migrations.AlterField( + model_name='contactassignment', + name='created', + field=models.DateTimeField(auto_now_add=True, null=True), + ), + migrations.AlterField( + model_name='contactgroup', + name='created', + field=models.DateTimeField(auto_now_add=True, null=True), + ), + migrations.AlterField( + model_name='contactrole', + name='created', + field=models.DateTimeField(auto_now_add=True, null=True), + ), + migrations.AlterField( + model_name='tenant', + name='created', + field=models.DateTimeField(auto_now_add=True, null=True), + ), + migrations.AlterField( + model_name='tenantgroup', + name='created', + field=models.DateTimeField(auto_now_add=True, null=True), + ), + ] diff --git a/netbox/utilities/testing/filtersets.py b/netbox/utilities/testing/filtersets.py index 98bb0d1ac..9c90f5530 100644 --- a/netbox/utilities/testing/filtersets.py +++ b/netbox/utilities/testing/filtersets.py @@ -24,12 +24,12 @@ class ChangeLoggedFilterSetTests(BaseFilterSetTests): def test_created(self): pk_list = self.queryset.values_list('pk', flat=True)[:2] - self.queryset.filter(pk__in=pk_list).update(created=date(2021, 1, 1)) - params = {'created': '2021-01-01'} + self.queryset.filter(pk__in=pk_list).update(created=datetime(2021, 1, 1, 0, 0, 0, tzinfo=timezone.utc)) + params = {'created': '2021-01-01T00:00:00'} self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) def test_last_updated(self): pk_list = self.queryset.values_list('pk', flat=True)[:2] - self.queryset.filter(pk__in=pk_list).update(last_updated=datetime(2021, 1, 1, 0, 0, 0, tzinfo=timezone.utc)) - params = {'last_updated': '2021-01-01T00:00:00'} + self.queryset.filter(pk__in=pk_list).update(last_updated=datetime(2021, 1, 2, 0, 0, 0, tzinfo=timezone.utc)) + params = {'last_updated': '2021-01-02T00:00:00'} self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) diff --git a/netbox/virtualization/migrations/0029_created_datetimefield.py b/netbox/virtualization/migrations/0029_created_datetimefield.py new file mode 100644 index 000000000..d22547a25 --- /dev/null +++ b/netbox/virtualization/migrations/0029_created_datetimefield.py @@ -0,0 +1,38 @@ +# Generated by Django 4.0.2 on 2022-02-08 18:54 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('virtualization', '0028_vminterface_vrf'), + ] + + operations = [ + migrations.AlterField( + model_name='cluster', + name='created', + field=models.DateTimeField(auto_now_add=True, null=True), + ), + migrations.AlterField( + model_name='clustergroup', + name='created', + field=models.DateTimeField(auto_now_add=True, null=True), + ), + migrations.AlterField( + model_name='clustertype', + name='created', + field=models.DateTimeField(auto_now_add=True, null=True), + ), + migrations.AlterField( + model_name='virtualmachine', + name='created', + field=models.DateTimeField(auto_now_add=True, null=True), + ), + migrations.AlterField( + model_name='vminterface', + name='created', + field=models.DateTimeField(auto_now_add=True, null=True), + ), + ] diff --git a/netbox/wireless/migrations/0003_created_datetimefield.py b/netbox/wireless/migrations/0003_created_datetimefield.py new file mode 100644 index 000000000..fe251248c --- /dev/null +++ b/netbox/wireless/migrations/0003_created_datetimefield.py @@ -0,0 +1,28 @@ +# Generated by Django 4.0.2 on 2022-02-08 18:54 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('wireless', '0002_standardize_id_fields'), + ] + + operations = [ + migrations.AlterField( + model_name='wirelesslan', + name='created', + field=models.DateTimeField(auto_now_add=True, null=True), + ), + migrations.AlterField( + model_name='wirelesslangroup', + name='created', + field=models.DateTimeField(auto_now_add=True, null=True), + ), + migrations.AlterField( + model_name='wirelesslink', + name='created', + field=models.DateTimeField(auto_now_add=True, null=True), + ), + ]