ipfabric_netbox 3.2.4__py3-none-any.whl → 3.2.4b2__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of ipfabric_netbox might be problematic. Click here for more details.

Files changed (38) hide show
  1. ipfabric_netbox/__init__.py +1 -1
  2. ipfabric_netbox/api/nested_serializers.py +0 -20
  3. ipfabric_netbox/api/serializers.py +7 -13
  4. ipfabric_netbox/api/urls.py +2 -2
  5. ipfabric_netbox/api/views.py +5 -5
  6. ipfabric_netbox/data/transform_map.json +21 -35
  7. ipfabric_netbox/filtersets.py +15 -13
  8. ipfabric_netbox/forms.py +14 -42
  9. ipfabric_netbox/jobs.py +12 -7
  10. ipfabric_netbox/migrations/0001_initial.py +1 -1
  11. ipfabric_netbox/migrations/0001_initial_squashed_0013_switch_to_branching_plugin.py +503 -0
  12. ipfabric_netbox/migrations/0007_prepare_custom_fields.py +3 -3
  13. ipfabric_netbox/migrations/0011_update_part_number_DCIM_inventory_item_template.py +57 -0
  14. ipfabric_netbox/migrations/0012_remove_status_field.py +18 -0
  15. ipfabric_netbox/migrations/0013_switch_to_branching_plugin.py +270 -0
  16. ipfabric_netbox/models.py +120 -91
  17. ipfabric_netbox/navigation.py +1 -1
  18. ipfabric_netbox/signals.py +9 -2
  19. ipfabric_netbox/tables.py +40 -46
  20. ipfabric_netbox/templates/ipfabric_netbox/{ipfabricbranch.html → ipfabricingestion.html} +14 -9
  21. ipfabric_netbox/templates/ipfabric_netbox/ipfabricsource.html +3 -3
  22. ipfabric_netbox/templates/ipfabric_netbox/ipfabricsync.html +3 -3
  23. ipfabric_netbox/templates/ipfabric_netbox/ipfabricsync_list.html +71 -0
  24. ipfabric_netbox/templates/ipfabric_netbox/ipfabrictransformmap.html +0 -4
  25. ipfabric_netbox/templates/ipfabric_netbox/partials/ingestion_all.html +10 -0
  26. ipfabric_netbox/templates/ipfabric_netbox/partials/{branch_progress.html → ingestion_progress.html} +1 -1
  27. ipfabric_netbox/templates/ipfabric_netbox/partials/sync_last_ingestion.html +1 -0
  28. ipfabric_netbox/urls.py +13 -3
  29. ipfabric_netbox/utilities/ipfutils.py +52 -19
  30. ipfabric_netbox/views.py +162 -155
  31. {ipfabric_netbox-3.2.4.dist-info → ipfabric_netbox-3.2.4b2.dist-info}/METADATA +12 -4
  32. {ipfabric_netbox-3.2.4.dist-info → ipfabric_netbox-3.2.4b2.dist-info}/RECORD +34 -31
  33. {ipfabric_netbox-3.2.4.dist-info → ipfabric_netbox-3.2.4b2.dist-info}/WHEEL +1 -1
  34. ipfabric_netbox/templates/ipfabric_netbox/inc/sync_delete.html +0 -19
  35. ipfabric_netbox/templates/ipfabric_netbox/partials/branch_all.html +0 -10
  36. ipfabric_netbox/templates/ipfabric_netbox/partials/sync_last_branch.html +0 -1
  37. ipfabric_netbox/templates/ipfabric_netbox/sync_list.html +0 -126
  38. /ipfabric_netbox/templates/ipfabric_netbox/partials/{branch_status.html → ingestion_status.html} +0 -0
@@ -0,0 +1,503 @@
1
+ # Generated by Django 5.2.1 on 2025-05-19 15:01
2
+ from typing import TYPE_CHECKING
3
+
4
+ import django.core.validators
5
+ import django.db.migrations.operations.special
6
+ import django.db.models.deletion
7
+ import taggit.managers
8
+ import utilities.json
9
+ from django.conf import settings
10
+ from django.db import migrations
11
+ from django.db import models
12
+ from extras.choices import CustomFieldTypeChoices
13
+ from extras.choices import CustomFieldUIEditableChoices
14
+ from extras.choices import CustomFieldUIVisibleChoices
15
+ from extras.choices import CustomLinkButtonClassChoices
16
+
17
+ from ipfabric_netbox.utilities.transform_map import build_transform_maps
18
+ from ipfabric_netbox.utilities.transform_map import get_transform_map
19
+
20
+ if TYPE_CHECKING:
21
+ from django.apps import apps as apps_type
22
+ from django.db.backends.base.schema import BaseDatabaseSchemaEditor
23
+
24
+ # This is squashed migration since when StagedChanges were removed, NetBox Branch model
25
+ # was moved to netbox branching. But IPFabricBranch was extending it and I had to remove it.
26
+ # We need to avoid creating IPFabricBranch on NetBox >4.3.0 since Branch is not there.
27
+ # So instead the squash does not create it and conditionally removed the table.
28
+
29
+
30
+ def create_custom_field(
31
+ apps: "apps_type",
32
+ field_name: str,
33
+ label: str,
34
+ target_models: list,
35
+ object_type=None,
36
+ cf_type: str | None = "type_text",
37
+ ):
38
+ """Create a single custom field and link it to required models."""
39
+ ObjectType = apps.get_model("core", "ObjectType")
40
+
41
+ defaults = {
42
+ "label": label,
43
+ "related_object_type": (
44
+ ObjectType.objects.get_for_model(object_type) if object_type else None
45
+ ),
46
+ "ui_visible": getattr(CustomFieldUIVisibleChoices, "ALWAYS"),
47
+ "ui_editable": getattr(CustomFieldUIEditableChoices, "NO"),
48
+ }
49
+
50
+ custom_field, _ = apps.get_model("extras", "CustomField").objects.update_or_create(
51
+ type=getattr(CustomFieldTypeChoices, cf_type.upper()),
52
+ name=field_name,
53
+ defaults=defaults,
54
+ )
55
+
56
+ for model in target_models:
57
+ custom_field.object_types.add(ObjectType.objects.get_for_model(model))
58
+
59
+
60
+ def prepare_custom_fields(apps: "apps_type", schema_editor: "BaseDatabaseSchemaEditor"):
61
+ """Forward migration to prepare ipfabric_netbox custom fields and links."""
62
+ Device = apps.get_model("dcim", "Device")
63
+ Site = apps.get_model("dcim", "Site")
64
+
65
+ create_custom_field(
66
+ apps,
67
+ "ipfabric_source",
68
+ "IP Fabric Source",
69
+ [Device, Site],
70
+ cf_type="type_object",
71
+ object_type=apps.get_model("ipfabric_netbox", "IPFabricSource"),
72
+ )
73
+ create_custom_field(
74
+ apps,
75
+ "ipfabric_ingestion",
76
+ "IP Fabric Last Ingestion",
77
+ [Device, Site],
78
+ cf_type="type_object",
79
+ object_type=apps.get_model("ipfabric_netbox", "IPFabricIngestion"),
80
+ )
81
+ cl, _ = apps.get_model("extras", "CustomLink").objects.update_or_create(
82
+ defaults={
83
+ "link_text": "{% if object.custom_field_data.ipfabric_source is defined %}{% set SOURCE_ID = object.custom_field_data.ipfabric_source %}{% if SOURCE_ID %}IP Fabric{% endif %}{% endif %}",
84
+ "link_url": '{% if object.custom_field_data.ipfabric_source is defined %}{% set SOURCE_ID = object.custom_field_data.ipfabric_source %}{% if SOURCE_ID %}{% set BASE_URL = object.custom_fields.filter(related_object_type__model="ipfabricsource").first().related_object_type.model_class().objects.get(pk=SOURCE_ID).url %}{{ BASE_URL }}/inventory/devices?options={"filters":{"sn": ["like","{{ object.serial }}"]}}{% endif %}{%endif%}',
85
+ "new_window": True,
86
+ "button_class": CustomLinkButtonClassChoices.BLUE,
87
+ },
88
+ name="ipfabric",
89
+ )
90
+ cl.object_types.add(
91
+ apps.get_model("core", "ObjectType").objects.get_for_model(Device)
92
+ )
93
+
94
+
95
+ def cleanup_custom_fields(apps: "apps_type", schema_editor: "BaseDatabaseSchemaEditor"):
96
+ """Reverse migration to prepare ipfabric_netbox custom fields and links."""
97
+ for field_name in ["ipfabric_source", "ipfabric_ingestion"]:
98
+ custom_field = apps.get_model("extras", "CustomField").objects.get(
99
+ name=field_name
100
+ )
101
+ for model in custom_field.object_types.all()[:]:
102
+ custom_field.object_types.remove(model)
103
+ custom_field.delete()
104
+
105
+
106
+ def prepare_transform_maps(
107
+ apps: "apps_type", schema_editor: "BaseDatabaseSchemaEditor"
108
+ ):
109
+ """Create transform maps if they do not exist yet.
110
+ They used to be created during plugin.ready() so they might be present on older DBs.
111
+ """
112
+ build_transform_maps(data=get_transform_map())
113
+
114
+
115
+ class Migration(migrations.Migration):
116
+ replaces = [
117
+ ("ipfabric_netbox", "0001_initial"),
118
+ ("ipfabric_netbox", "0002_ipfabricsnapshot_status"),
119
+ ("ipfabric_netbox", "0003_ipfabricsource_type_and_more"),
120
+ ("ipfabric_netbox", "0004_ipfabricsync_auto_merge"),
121
+ (
122
+ "ipfabric_netbox",
123
+ "0005_alter_ipfabricrelationshipfield_source_model_and_more",
124
+ ),
125
+ ("ipfabric_netbox", "0006_alter_ipfabrictransformmap_target_model"),
126
+ ("ipfabric_netbox", "0007_prepare_custom_fields"),
127
+ ("ipfabric_netbox", "0008_prepare_transform_maps"),
128
+ ("ipfabric_netbox", "0009_transformmap_changes_for_netbox_v4_2"),
129
+ ("ipfabric_netbox", "0010_remove_uuid_from_get_or_create"),
130
+ ("ipfabric_netbox", "0011_update_part_number_DCIM_inventory_item_template"),
131
+ ("ipfabric_netbox", "0012_remove_status_field"),
132
+ ("ipfabric_netbox", "0013_switch_to_branching_plugin"),
133
+ ]
134
+
135
+ dependencies = [
136
+ ("contenttypes", "0002_remove_content_type_name"),
137
+ ("core", "0012_job_object_type_optional"),
138
+ ("dcim", "0191_module_bay_rebuild"),
139
+ ("extras", "0123_journalentry_kind_default"),
140
+ ("ipam", "0070_vlangroup_vlan_id_ranges"),
141
+ ("netbox_branching", "0003_rename_indexes"),
142
+ migrations.swappable_dependency(settings.AUTH_USER_MODEL),
143
+ ]
144
+
145
+ operations = [
146
+ migrations.CreateModel(
147
+ name="IPFabricSource",
148
+ fields=[
149
+ (
150
+ "id",
151
+ models.BigAutoField(
152
+ auto_created=True, primary_key=True, serialize=False
153
+ ),
154
+ ),
155
+ ("created", models.DateTimeField(auto_now_add=True, null=True)),
156
+ ("last_updated", models.DateTimeField(auto_now=True, null=True)),
157
+ (
158
+ "custom_field_data",
159
+ models.JSONField(
160
+ blank=True,
161
+ default=dict,
162
+ encoder=utilities.json.CustomFieldJSONEncoder,
163
+ ),
164
+ ),
165
+ ("description", models.CharField(blank=True, max_length=200)),
166
+ ("comments", models.TextField(blank=True)),
167
+ ("name", models.CharField(max_length=100, unique=True)),
168
+ ("url", models.CharField(max_length=200)),
169
+ (
170
+ "status",
171
+ models.CharField(default="new", editable=False, max_length=50),
172
+ ),
173
+ ("parameters", models.JSONField(blank=True, null=True)),
174
+ ("last_synced", models.DateTimeField(blank=True, null=True)),
175
+ (
176
+ "tags",
177
+ taggit.managers.TaggableManager(
178
+ through="extras.TaggedItem", to="extras.Tag"
179
+ ),
180
+ ),
181
+ ("type", models.CharField(default="local", max_length=50)),
182
+ ],
183
+ options={
184
+ "verbose_name": "IP Fabric Source",
185
+ "verbose_name_plural": "IP Fabric Sources",
186
+ "ordering": ("name",),
187
+ },
188
+ ),
189
+ migrations.CreateModel(
190
+ name="IPFabricSnapshot",
191
+ fields=[
192
+ (
193
+ "id",
194
+ models.BigAutoField(
195
+ auto_created=True, primary_key=True, serialize=False
196
+ ),
197
+ ),
198
+ ("created", models.DateTimeField(auto_now_add=True)),
199
+ ("last_updated", models.DateTimeField(editable=False)),
200
+ ("name", models.CharField(max_length=200)),
201
+ (
202
+ "source",
203
+ models.ForeignKey(
204
+ editable=False,
205
+ on_delete=django.db.models.deletion.CASCADE,
206
+ related_name="snapshots",
207
+ to="ipfabric_netbox.ipfabricsource",
208
+ ),
209
+ ),
210
+ ("snapshot_id", models.CharField(max_length=100)),
211
+ ("status", models.CharField(default="unloaded", max_length=50)),
212
+ ("data", models.JSONField(blank=True, null=True)),
213
+ ("date", models.DateTimeField(blank=True, editable=False, null=True)),
214
+ ],
215
+ options={
216
+ "verbose_name": "IP Fabric Snapshot",
217
+ "verbose_name_plural": "IP Fabric Snapshots",
218
+ "ordering": ("source", "-date"),
219
+ },
220
+ ),
221
+ migrations.CreateModel(
222
+ name="IPFabricTransformMap",
223
+ fields=[
224
+ (
225
+ "id",
226
+ models.BigAutoField(
227
+ auto_created=True, primary_key=True, serialize=False
228
+ ),
229
+ ),
230
+ ("created", models.DateTimeField(auto_now_add=True, null=True)),
231
+ ("last_updated", models.DateTimeField(auto_now=True, null=True)),
232
+ (
233
+ "custom_field_data",
234
+ models.JSONField(
235
+ blank=True,
236
+ default=dict,
237
+ encoder=utilities.json.CustomFieldJSONEncoder,
238
+ ),
239
+ ),
240
+ ("name", models.CharField(max_length=100, unique=True)),
241
+ ("source_model", models.CharField(max_length=50)),
242
+ (
243
+ "tags",
244
+ taggit.managers.TaggableManager(
245
+ through="extras.TaggedItem", to="extras.Tag"
246
+ ),
247
+ ),
248
+ (
249
+ "target_model",
250
+ models.ForeignKey(
251
+ limit_choices_to=models.Q(
252
+ models.Q(
253
+ models.Q(("app_label", "dcim"), ("model", "site")),
254
+ models.Q(
255
+ ("app_label", "dcim"), ("model", "manufacturer")
256
+ ),
257
+ models.Q(("app_label", "dcim"), ("model", "platform")),
258
+ models.Q(
259
+ ("app_label", "dcim"), ("model", "devicerole")
260
+ ),
261
+ models.Q(
262
+ ("app_label", "dcim"), ("model", "devicetype")
263
+ ),
264
+ models.Q(("app_label", "dcim"), ("model", "device")),
265
+ models.Q(
266
+ ("app_label", "dcim"), ("model", "virtualchassis")
267
+ ),
268
+ models.Q(("app_label", "dcim"), ("model", "interface")),
269
+ models.Q(
270
+ ("app_label", "dcim"), ("model", "macaddress")
271
+ ),
272
+ models.Q(("app_label", "ipam"), ("model", "vlan")),
273
+ models.Q(("app_label", "ipam"), ("model", "vrf")),
274
+ models.Q(("app_label", "ipam"), ("model", "prefix")),
275
+ models.Q(("app_label", "ipam"), ("model", "ipaddress")),
276
+ models.Q(
277
+ ("app_label", "contenttypes"),
278
+ ("model", "contenttype"),
279
+ ),
280
+ models.Q(("app_label", "tenancy"), ("model", "tenant")),
281
+ models.Q(
282
+ ("app_label", "dcim"), ("model", "inventoryitem")
283
+ ),
284
+ _connector="OR",
285
+ )
286
+ ),
287
+ on_delete=django.db.models.deletion.PROTECT,
288
+ related_name="+",
289
+ to="contenttypes.contenttype",
290
+ ),
291
+ ),
292
+ ],
293
+ options={
294
+ "verbose_name": "IP Fabric Transform Map",
295
+ "verbose_name_plural": "IP Fabric Transform Maps",
296
+ },
297
+ ),
298
+ migrations.CreateModel(
299
+ name="IPFabricTransformField",
300
+ fields=[
301
+ (
302
+ "id",
303
+ models.BigAutoField(
304
+ auto_created=True, primary_key=True, serialize=False
305
+ ),
306
+ ),
307
+ ("source_field", models.CharField(max_length=100)),
308
+ ("target_field", models.CharField(max_length=100)),
309
+ ("coalesce", models.BooleanField(default=False)),
310
+ ("template", models.TextField(blank=True, default="")),
311
+ (
312
+ "transform_map",
313
+ models.ForeignKey(
314
+ on_delete=django.db.models.deletion.CASCADE,
315
+ related_name="field_maps",
316
+ to="ipfabric_netbox.ipfabrictransformmap",
317
+ ),
318
+ ),
319
+ ],
320
+ options={
321
+ "verbose_name": "IP Fabric Transform Field",
322
+ "verbose_name_plural": "IP Fabric Transform Fields",
323
+ "ordering": ("transform_map",),
324
+ },
325
+ ),
326
+ migrations.CreateModel(
327
+ name="IPFabricSync",
328
+ fields=[
329
+ (
330
+ "id",
331
+ models.BigAutoField(
332
+ auto_created=True, primary_key=True, serialize=False
333
+ ),
334
+ ),
335
+ ("created", models.DateTimeField(auto_now_add=True, null=True)),
336
+ ("last_updated", models.DateTimeField(auto_now=True, null=True)),
337
+ ("name", models.CharField(max_length=100, unique=True)),
338
+ ("type", models.CharField(default="dcim", max_length=50)),
339
+ (
340
+ "status",
341
+ models.CharField(default="new", editable=False, max_length=50),
342
+ ),
343
+ ("parameters", models.JSONField(blank=True, null=True)),
344
+ (
345
+ "last_synced",
346
+ models.DateTimeField(blank=True, editable=False, null=True),
347
+ ),
348
+ ("scheduled", models.DateTimeField(blank=True, null=True)),
349
+ (
350
+ "interval",
351
+ models.PositiveIntegerField(
352
+ blank=True,
353
+ null=True,
354
+ validators=[django.core.validators.MinValueValidator(1)],
355
+ ),
356
+ ),
357
+ (
358
+ "snapshot_data",
359
+ models.ForeignKey(
360
+ on_delete=django.db.models.deletion.CASCADE,
361
+ related_name="snapshots",
362
+ to="ipfabric_netbox.ipfabricsnapshot",
363
+ ),
364
+ ),
365
+ (
366
+ "tags",
367
+ taggit.managers.TaggableManager(
368
+ through="extras.TaggedItem", to="extras.Tag"
369
+ ),
370
+ ),
371
+ (
372
+ "user",
373
+ models.ForeignKey(
374
+ blank=True,
375
+ null=True,
376
+ on_delete=django.db.models.deletion.SET_NULL,
377
+ related_name="+",
378
+ to=settings.AUTH_USER_MODEL,
379
+ ),
380
+ ),
381
+ ("auto_merge", models.BooleanField(default=False)),
382
+ ],
383
+ options={
384
+ "verbose_name": "IP Fabric Sync",
385
+ "ordering": ["pk"],
386
+ },
387
+ ),
388
+ migrations.CreateModel(
389
+ name="IPFabricData",
390
+ fields=[
391
+ (
392
+ "id",
393
+ models.BigAutoField(
394
+ auto_created=True, primary_key=True, serialize=False
395
+ ),
396
+ ),
397
+ ("data", models.JSONField(blank=True, null=True)),
398
+ ("type", models.CharField(max_length=50)),
399
+ (
400
+ "snapshot_data",
401
+ models.ForeignKey(
402
+ on_delete=django.db.models.deletion.CASCADE,
403
+ related_name="ipf_data",
404
+ to="ipfabric_netbox.ipfabricsnapshot",
405
+ ),
406
+ ),
407
+ ],
408
+ ),
409
+ migrations.CreateModel(
410
+ name="IPFabricRelationshipField",
411
+ fields=[
412
+ (
413
+ "id",
414
+ models.BigAutoField(
415
+ auto_created=True, primary_key=True, serialize=False
416
+ ),
417
+ ),
418
+ ("target_field", models.CharField(max_length=100)),
419
+ ("coalesce", models.BooleanField(default=False)),
420
+ ("template", models.TextField(blank=True, default="")),
421
+ (
422
+ "source_model",
423
+ models.ForeignKey(
424
+ limit_choices_to=models.Q(
425
+ models.Q(
426
+ ("app_label", "dcim"),
427
+ ("app_label", "ipam"),
428
+ ("app_label", "tenancy"),
429
+ models.Q(
430
+ ("app_label", "contenttypes"),
431
+ ("model", "contenttype"),
432
+ ),
433
+ _connector="OR",
434
+ )
435
+ ),
436
+ on_delete=django.db.models.deletion.PROTECT,
437
+ related_name="ipfabric_transform_fields",
438
+ to="contenttypes.contenttype",
439
+ ),
440
+ ),
441
+ (
442
+ "transform_map",
443
+ models.ForeignKey(
444
+ on_delete=django.db.models.deletion.CASCADE,
445
+ related_name="relationship_maps",
446
+ to="ipfabric_netbox.ipfabrictransformmap",
447
+ ),
448
+ ),
449
+ ],
450
+ options={
451
+ "verbose_name": "IP Fabric Relationship Field",
452
+ "verbose_name_plural": "IP Fabric Relationship Fields",
453
+ "ordering": ("transform_map",),
454
+ },
455
+ ),
456
+ migrations.CreateModel(
457
+ name="IPFabricIngestion",
458
+ fields=[
459
+ (
460
+ "id",
461
+ models.BigAutoField(
462
+ auto_created=True, primary_key=True, serialize=False
463
+ ),
464
+ ),
465
+ (
466
+ "branch",
467
+ models.OneToOneField(
468
+ null=True,
469
+ on_delete=django.db.models.deletion.SET_NULL,
470
+ to="netbox_branching.branch",
471
+ ),
472
+ ),
473
+ (
474
+ "job",
475
+ models.ForeignKey(
476
+ null=True,
477
+ on_delete=django.db.models.deletion.SET_NULL,
478
+ to="core.job",
479
+ ),
480
+ ),
481
+ (
482
+ "sync",
483
+ models.ForeignKey(
484
+ on_delete=django.db.models.deletion.CASCADE,
485
+ to="ipfabric_netbox.ipfabricsync",
486
+ ),
487
+ ),
488
+ ],
489
+ options={
490
+ "verbose_name": "IP Fabric Ingestion",
491
+ "verbose_name_plural": "IP Fabric Ingestion",
492
+ "ordering": ("pk",),
493
+ },
494
+ ),
495
+ migrations.RunPython(
496
+ code=prepare_custom_fields,
497
+ reverse_code=cleanup_custom_fields,
498
+ ),
499
+ migrations.RunPython(
500
+ code=prepare_transform_maps,
501
+ reverse_code=migrations.RunPython.noop,
502
+ ),
503
+ ]
@@ -25,9 +25,9 @@ def create_custom_field(
25
25
 
26
26
  defaults = {
27
27
  "label": label,
28
- "related_object_type": ObjectType.objects.get_for_model(object_type)
29
- if object_type
30
- else None,
28
+ "related_object_type": (
29
+ ObjectType.objects.get_for_model(object_type) if object_type else None
30
+ ),
31
31
  "ui_visible": getattr(CustomFieldUIVisibleChoices, "ALWAYS"),
32
32
  "ui_editable": getattr(CustomFieldUIEditableChoices, "NO"),
33
33
  }
@@ -0,0 +1,57 @@
1
+ """
2
+ NIM-18852.
3
+ Update to truncate name and description fields because they can
4
+ exceed DB field limits.
5
+ """
6
+ from django.db import migrations
7
+
8
+ # Keep the original template here rather than loading it from transform_map.json
9
+ # so our revert won’t break if that template ever changes.
10
+ OLD_TEMPLATE = (
11
+ "{% if object.name is not none %}"
12
+ "{{ object.name }}"
13
+ "{% elif object.dscr is not none %}"
14
+ "{{ object.dscr}}"
15
+ "{% else %}Default Name{% endif %}"
16
+ )
17
+
18
+ NEW_TEMPLATE = (
19
+ "{% if object.name is not none %}"
20
+ "{{ object.name | string | truncate(64, True) }}"
21
+ "{% elif object.dscr is not none %}"
22
+ "{{ object.dscr | string | truncate(64, True) }}"
23
+ "{% else %}Default Name{% endif %}"
24
+ )
25
+
26
+
27
+ def apply_truncate_template(apps, schema_editor):
28
+ """Replace old template with truncated version on all matching transform fields."""
29
+ TransformField = apps.get_model("ipfabric_netbox", "IPFabricTransformField")
30
+ TransformField.objects.filter(
31
+ template=OLD_TEMPLATE,
32
+ source_field="name",
33
+ target_field="name",
34
+ ).update(template=NEW_TEMPLATE)
35
+
36
+
37
+ def revert_truncate_template(apps, schema_editor):
38
+ """Revert truncated template back to the original exact template."""
39
+ TransformField = apps.get_model("ipfabric_netbox", "IPFabricTransformField")
40
+ TransformField.objects.filter(
41
+ template=NEW_TEMPLATE,
42
+ source_field="name",
43
+ target_field="name",
44
+ ).update(template=OLD_TEMPLATE)
45
+
46
+
47
+ class Migration(migrations.Migration):
48
+ dependencies = [
49
+ ("ipfabric_netbox", "0010_remove_uuid_from_get_or_create"),
50
+ ]
51
+
52
+ operations = [
53
+ migrations.RunPython(
54
+ apply_truncate_template,
55
+ revert_truncate_template,
56
+ ),
57
+ ]
@@ -0,0 +1,18 @@
1
+ """
2
+ NIM-18527.
3
+ Remove status field from TransformMap.
4
+ """
5
+ from django.db import migrations
6
+
7
+
8
+ class Migration(migrations.Migration):
9
+ dependencies = [
10
+ ("ipfabric_netbox", "0011_update_part_number_DCIM_inventory_item_template"),
11
+ ]
12
+
13
+ operations = [
14
+ migrations.RemoveField(
15
+ model_name="ipfabrictransformmap",
16
+ name="status",
17
+ ),
18
+ ]