Compare commits

..

1 Commits

Author SHA1 Message Date
Arthur
8cbfe94fba fix performance regression for Site save, use bulk_update for cached fields 2026-01-14 16:30:40 -08:00
5 changed files with 17 additions and 51 deletions

View File

@@ -722,9 +722,6 @@ class DeviceForm(TenancyForm, PrimaryModelForm):
if position:
self.fields['position'].widget.choices = [(position, f'U{position}')]
# Clear face field when rack is cleared
self.fields['face'].widget.attrs['ts-clear-field'] = 'rack'
class ModuleForm(ModuleCommonForm, PrimaryModelForm):
device = DynamicModelChoiceField(

View File

@@ -211,12 +211,16 @@ def sync_cached_scope_fields(instance, created, **kwargs):
for model in (Prefix, Cluster, WirelessLAN):
qs = model.objects.filter(**filters)
# Bulk update cached fields to avoid O(N) performance issues with large datasets.
# This does not trigger post_save signals, avoiding spurious change log entries.
objects_to_update = []
for obj in qs:
# Recompute cache using the same logic as save()
obj.cache_related_objects()
obj.save(update_fields=[
'_location',
'_site',
'_site_group',
'_region',
])
objects_to_update.append(obj)
if objects_to_update:
model.objects.bulk_update(
objects_to_update,
['_location', '_site', '_site_group', '_region']
)

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -1,4 +1,3 @@
import TomSelect from 'tom-select';
import { getElements } from '../util';
function handleFormSubmit(): void {
@@ -9,37 +8,6 @@ function handleFormSubmit(): void {
}
}
/**
* Initialize clear-field dependencies.
* When a field with ts-clear-field attribute's parent field is cleared, this field will also be cleared.
*/
function initClearFieldDependencies(): void {
// Find all fields with ts-clear-field attribute
for (const field of getElements<HTMLSelectElement>('[ts-clear-field]')) {
const parentFieldName = field.getAttribute('ts-clear-field');
if (!parentFieldName) continue;
// Find the parent field
const parentField = document.querySelector<HTMLSelectElement>(`[name="${parentFieldName}"]`);
if (!parentField) continue;
// Listen for changes on the parent field
parentField.addEventListener('change', () => {
// If parent field is cleared, also clear this dependent field
if (!parentField.value || parentField.value === '') {
// Check if this field uses TomSelect
const tomselect = (field as HTMLSelectElement & { tomselect?: TomSelect }).tomselect;
if (tomselect) {
tomselect.clear();
} else {
// Regular select field
field.value = '';
}
}
});
}
}
/**
* Attach event listeners to each form's submit/reset buttons.
*/
@@ -60,7 +28,4 @@ export function initFormElements(): void {
});
}
}
// Initialize clear-field dependencies
initClearFieldDependencies();
}