Avoid redundant uniqueness checks in ValidatedModelSerializer #463

Closed
opened 2026-04-05 16:34:13 +02:00 by MrUnknownDE · 0 comments
Owner

Originally created by @jeremystretch on 1/26/2026

NetBox Version

v4.5.1

Python Version

3.12

Area(s) of Concern

  • User Interface
  • REST API
  • GraphQL API
  • Python ORM
  • Other

Details

When creating a new object via the REST API, unique fields are currently validated twice: First by the serializer field's validator, and again by our custom validate() method.

IIRC, the custom validate() method was originally added to ensure that unique constraints were enforced properly. (However, that change was made years ago and probably deserves to be re-evaluated.) It may suffice to just call validate_constraints() directly rather than the entire set of model validation. At a minimum, it should be acceptable to disable uniqueness validation specifically, as that is already handled at the field level:

instance.full_clean(validate_unique=False)
*Originally created by @jeremystretch on 1/26/2026* ### NetBox Version v4.5.1 ### Python Version 3.12 ### Area(s) of Concern - [ ] User Interface - [x] REST API - [ ] GraphQL API - [ ] Python ORM - [ ] Other ### Details When creating a new object via the REST API, unique fields are currently validated twice: First by the serializer field's validator, and again by our custom [`validate()` method](https://github.com/netbox-community/netbox/blob/a9e50238ebba8fda7462ed1b0723d9012205fd28/netbox/netbox/api/serializers/base.py#L85). IIRC, the custom `validate()` method was originally added to ensure that unique constraints were enforced properly. (However, that change was made years ago and probably deserves to be re-evaluated.) It may suffice to just call `validate_constraints()` directly rather than the entire set of model validation. At a minimum, it should be acceptable to disable uniqueness validation specifically, as that is already handled at the field level: ```python instance.full_clean(validate_unique=False) ```
MrUnknownDE added the type: performancestatus: acceptedcomplexity: lownetboxtype: performancetype: performancetype: performancetype: performancetype: performancetype: performancetype: performancetype: performancetype: performancetype: performancetype: performancetype: performancetype: performancetype: performancetype: performancetype: performancestatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptedstatus: acceptednetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxcomplexity: lowcomplexity: lowcomplexity: lowcomplexity: lowcomplexity: lowcomplexity: lowcomplexity: lowcomplexity: lowcomplexity: lowcomplexity: lowcomplexity: lowcomplexity: lowcomplexity: lowcomplexity: lowcomplexity: lowcomplexity: lowcomplexity: lowcomplexity: lowcomplexity: lowcomplexity: lowcomplexity: lowcomplexity: lowcomplexity: lowcomplexity: lowcomplexity: low labels 2026-04-05 16:34:21 +02:00
Sign in to join this conversation.
No Label complexity: low complexity: low complexity: low complexity: low complexity: low complexity: low complexity: low complexity: low complexity: low complexity: low complexity: low complexity: low complexity: low complexity: low complexity: low complexity: low complexity: low complexity: low complexity: low complexity: low complexity: low complexity: low complexity: low complexity: low complexity: low complexity: low netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted status: accepted type: performance type: performance type: performance type: performance type: performance type: performance type: performance type: performance type: performance type: performance type: performance type: performance type: performance type: performance type: performance type: performance type: performance
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: github/netbox#463