Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

15671 save module before sync_classes #15675

Merged
merged 2 commits into from
Apr 15, 2024
Merged

Conversation

arthanson
Copy link
Collaborator

Fixes: #15671

save Module before doing sync_classes as it can cause M2M error: ValueError: save() prohibited to prevent data loss due to unsaved related object 'module'.

@arthanson arthanson marked this pull request as ready for review April 9, 2024 16:49
@peteeckel
Copy link
Contributor

Hi @arthanson, pardon me if this is a stupid question, but does save() really return a value? The Django docs say no, but is there any place in NetBox where this is overridden and the returned value is actually used?

    def save(self, *args, **kwargs):
        self.file_root = ManagedFileRootPathChoices.SCRIPTS
        obj = super().save(*args, **kwargs)
        self.sync_classes()
        return obj

@arthanson
Copy link
Collaborator Author

Hi @arthanson, pardon me if this is a stupid question, but does save() really return a value? The Django docs say no, but is there any place in NetBox where this is overridden and the returned value is actually used?

    def save(self, *args, **kwargs):
        self.file_root = ManagedFileRootPathChoices.SCRIPTS
        obj = super().save(*args, **kwargs)
        self.sync_classes()
        return obj

Good catch, fixed.

@peteeckel
Copy link
Contributor

peteeckel commented Apr 11, 2024

There are some other places in the NetBox code where save() also returns a value, which made me think that this could be intentional after all.

# git grep -n 'return super().save' 
netbox/core/forms/model_forms.py:86:        return super().save(*args, **kwargs)
netbox/core/forms/model_forms.py:120:        return super().save(*args, **kwargs)
netbox/dcim/models/device_components.py:567:        return super().save(*args, **kwargs)
netbox/extras/models/change_logging.py:131:        return super().save(*args, **kwargs)
netbox/extras/models/customfields.py:784:        return super().save(*args, **kwargs)
netbox/extras/models/scripts.py:169:        return super().save(*args, **kwargs)
netbox/users/forms/bulk_import.py:34:        return super().save(*args, **kwargs)
netbox/users/forms/model_forms.py:98:        return super().save(*args, **kwargs)
netbox/users/models/tokens.py:92:        return super().save(*args, **kwargs)
netbox/vpn/forms/bulk_import.py:140:        return super().save(*args, **kwargs)

git grep -n '= super().save'
netbox/core/forms/model_forms.py:218:        instance = super().save(commit=False)
netbox/dcim/forms/object_create.py:439:        instance = super().save(*args, **kwargs)
netbox/dcim/models/devices.py:341:        ret = super().save(*args, **kwargs)
netbox/ipam/forms/bulk_import.py:377:        ipaddress = super().save(*args, **kwargs)
netbox/ipam/forms/model_forms.py:177:        instance = super().save(*args, **kwargs)
netbox/ipam/forms/model_forms.py:393:        ipaddress = super().save(*args, **kwargs)
netbox/ipam/forms/model_forms.py:475:        instance = super().save(*args, **kwargs)
netbox/netbox/models/features.py:494:        ret = super().save(*args, **kwargs)
netbox/users/forms/model_forms.py:211:        instance = super().save(*args, **kwargs)
netbox/users/forms/model_forms.py:259:        instance = super().save(*args, **kwargs)
netbox/users/forms/model_forms.py:379:        instance = super().save(*args, **kwargs)
netbox/vpn/forms/model_forms.py:201:        instance = super().save(*args, **kwargs)

(in all likelihood not a complete list)

@jeremystretch jeremystretch added the beta Concerns a bug/feature in a beta release label Apr 15, 2024
@jeremystretch
Copy link
Member

Django's Model.save() always returns None, so technically nothing needs to be returned. However, when invoking the method of a parent class using super(), it's common to always return its original output (if any) just out of convention. (Also, many of the instances above are actually forms, not models, and ModelForm.save() does return an instance.)

@jeremystretch jeremystretch merged commit 5e05041 into feature Apr 15, 2024
6 checks passed
@jeremystretch jeremystretch deleted the 15671-script-save branch April 15, 2024 17:22
@peteeckel
Copy link
Contributor

Django's Model.save() always returns None, so technically nothing needs to be returned. However, when invoking the method of a parent class using super(), it's common to always return its original output (if any) just out of convention.

I would totally agree with you (I love consistency) if the convention in NetBox wouldn't seem to be to not return the value of super().save():

netbox/dcim/models/cables.py:        super().save(*args, **kwargs)
netbox/dcim/models/cables.py:        super().save(*args, **kwargs)
netbox/dcim/models/cables.py:        super().save(*args, **kwargs)
netbox/dcim/models/device_components.py:        return super().save(*args, **kwargs)
netbox/dcim/models/device_components.py:        super().save(*args, **kwargs)
netbox/dcim/models/devices.py:        ret = super().save(*args, **kwargs)
netbox/dcim/models/devices.py:        super().save(*args, **kwargs)
netbox/dcim/models/devices.py:        super().save(*args, **kwargs)
netbox/dcim/models/mixins.py:        super().save(*args, **kwargs)
netbox/dcim/models/power.py:        super().save(*args, **kwargs)
netbox/dcim/models/racks.py:        super().save(*args, **kwargs)
netbox/extras/models/change_logging.py:        return super().save(*args, **kwargs)
netbox/extras/models/customfields.py:        return super().save(*args, **kwargs)
netbox/extras/models/scripts.py:        super().save(*args, **kwargs)
netbox/ipam/models/ip.py:        super().save(*args, **kwargs)
netbox/ipam/models/ip.py:        super().save(*args, **kwargs)
netbox/ipam/models/ip.py:        super().save(*args, **kwargs)
netbox/netbox/models/features.py:        ret = super().save(*args, **kwargs)
netbox/users/models/tokens.py:        return super().save(*args, **kwargs)
netbox/virtualization/models/virtualmachines.py:        super().save(*args, **kwargs)
netbox/wireless/models.py:        super().save(*args, **kwargs)

That's 6 "return" vs. 15 "don't return" - for models, I was mistaken about the forms, sorry.

@github-actions github-actions bot locked as resolved and limited conversation to collaborators May 17, 2024
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
beta Concerns a bug/feature in a beta release
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants