mirror of
https://github.com/netbox-community/netbox.git
synced 2025-07-27 02:48:38 -06:00
Introduce JSONSchemaProperty
This commit is contained in:
parent
93bd2ee5b8
commit
a67ea1305e
124
netbox/utilities/jsonschema.py
Normal file
124
netbox/utilities/jsonschema.py
Normal file
@ -0,0 +1,124 @@
|
||||
from dataclasses import dataclass
|
||||
from enum import Enum
|
||||
from typing import Any
|
||||
|
||||
from django import forms
|
||||
from django.contrib.postgres.forms import SimpleArrayField
|
||||
from django.core.validators import RegexValidator
|
||||
|
||||
from utilities.string import title
|
||||
from utilities.validators import MultipleOfValidator
|
||||
|
||||
__all__ = (
|
||||
'JSONSchemaProperty',
|
||||
'PropertyTypeEnum',
|
||||
'StringFormatEnum',
|
||||
)
|
||||
|
||||
|
||||
class PropertyTypeEnum(Enum):
|
||||
STRING = 'string'
|
||||
INTEGER = 'integer'
|
||||
NUMBER = 'number'
|
||||
BOOLEAN = 'boolean'
|
||||
ARRAY = 'array'
|
||||
OBJECT = 'object'
|
||||
|
||||
|
||||
class StringFormatEnum(Enum):
|
||||
EMAIL = 'email'
|
||||
URI = 'uri'
|
||||
IRI = 'iri'
|
||||
UUID = 'uuid'
|
||||
DATE = 'date'
|
||||
TIME = 'time'
|
||||
DATETIME = 'datetime'
|
||||
|
||||
|
||||
FORM_FIELDS = {
|
||||
PropertyTypeEnum.STRING.value: forms.CharField,
|
||||
PropertyTypeEnum.INTEGER.value: forms.IntegerField,
|
||||
PropertyTypeEnum.NUMBER.value: forms.FloatField,
|
||||
PropertyTypeEnum.BOOLEAN.value: forms.BooleanField,
|
||||
PropertyTypeEnum.ARRAY.value: SimpleArrayField,
|
||||
PropertyTypeEnum.OBJECT.value: forms.JSONField,
|
||||
}
|
||||
|
||||
STRING_FORM_FIELDS = {
|
||||
StringFormatEnum.EMAIL.value: forms.EmailField,
|
||||
StringFormatEnum.URI.value: forms.URLField,
|
||||
StringFormatEnum.IRI.value: forms.URLField,
|
||||
StringFormatEnum.UUID.value: forms.UUIDField,
|
||||
StringFormatEnum.DATE.value: forms.DateField,
|
||||
StringFormatEnum.TIME.value: forms.TimeField,
|
||||
StringFormatEnum.DATETIME.value: forms.DateTimeField,
|
||||
}
|
||||
|
||||
|
||||
@dataclass
|
||||
class JSONSchemaProperty:
|
||||
type: PropertyTypeEnum = PropertyTypeEnum.STRING.value
|
||||
title: str | None = None
|
||||
description: str | None = None
|
||||
default: Any = None
|
||||
enum: list | None = None
|
||||
|
||||
# Strings
|
||||
minLength: int | None = None
|
||||
maxLength: int | None = None
|
||||
pattern: str | None = None # Regex
|
||||
format: StringFormatEnum | None = None
|
||||
|
||||
# Numbers
|
||||
minimum: int | float | None = None
|
||||
maximum: int | float | None = None
|
||||
multipleOf: int | float | None = None
|
||||
|
||||
def to_form_field(self, name, required=False):
|
||||
"""
|
||||
Instantiate and return a Django form field suitable for editing the property's value.
|
||||
"""
|
||||
field_kwargs = {
|
||||
'label': self.title or title(name),
|
||||
'help_text': self.description,
|
||||
'required': required,
|
||||
}
|
||||
|
||||
# String validation
|
||||
if self.type == PropertyTypeEnum.STRING:
|
||||
if self.minLength is not None:
|
||||
field_kwargs['min_length'] = self.minLength
|
||||
if self.maxLength is not None:
|
||||
field_kwargs['max_length'] = self.maxLength
|
||||
if self.pattern is not None:
|
||||
field_kwargs['validators'] = [
|
||||
RegexValidator(regex=self.pattern)
|
||||
]
|
||||
|
||||
# Integer/number validation
|
||||
elif self.type in (PropertyTypeEnum.INTEGER, PropertyTypeEnum.NUMBER):
|
||||
if self.minimum:
|
||||
field_kwargs['min_value'] = self.minimum
|
||||
if self.maximum:
|
||||
field_kwargs['min_value'] = self.maximum
|
||||
if self.multipleOf:
|
||||
field_kwargs['validators'] = [
|
||||
MultipleOfValidator(multiple=self.multipleOf)
|
||||
]
|
||||
|
||||
return self.field_class(**field_kwargs)
|
||||
|
||||
@property
|
||||
def field_class(self):
|
||||
"""
|
||||
Resolve the property's type (and string format, if specified) to the appropriate field class.
|
||||
"""
|
||||
if self.type == PropertyTypeEnum.STRING.value and self.format is not None:
|
||||
try:
|
||||
return STRING_FORM_FIELDS[self.format]
|
||||
except KeyError:
|
||||
raise ValueError(f"Unsupported string format type: {self.format}")
|
||||
try:
|
||||
return FORM_FIELDS[self.type]
|
||||
except KeyError:
|
||||
raise ValueError(f"Unknown property type: {self.type}")
|
Loading…
Reference in New Issue
Block a user