Coverage for dcim/api/serializers_/racks.py: 99%

82 statements  

« prev     ^ index     » next       coverage.py v7.15.2, created at 2026-10-10 18:35 +0000

1from django.utils.translation import gettext as _ 

2from drf_spectacular.types import OpenApiTypes 

3from drf_spectacular.utils import extend_schema_field 

4from rest_framework import serializers 

5 

6from dcim.choices import * 

7from dcim.constants import * 

8from dcim.models import Rack, RackGroup, RackReservation, RackRole, RackType 

9from netbox.api.fields import ChoiceField, RelatedObjectCountField 

10from netbox.api.serializers import OrganizationalModelSerializer, PrimaryModelSerializer 

11from netbox.choices import * 

12from netbox.config import ConfigItem 

13from tenancy.api.serializers_.tenants import TenantSerializer 

14from users.api.serializers_.users import UserSerializer 

15 

16from .manufacturers import ManufacturerSerializer 

17from .sites import LocationSerializer, SiteSerializer 

18 

19__all__ = ( 

20 'RackElevationDetailFilterSerializer', 

21 'RackGroupSerializer', 

22 'RackReservationSerializer', 

23 'RackRoleSerializer', 

24 'RackSerializer', 

25 'RackTypeSerializer', 

26) 

27 

28 

29class RackGroupSerializer(OrganizationalModelSerializer): 

30 

31 # Related object counts 

32 rack_count = RelatedObjectCountField('racks') 

33 

34 class Meta: 

35 model = RackGroup 

36 fields = [ 

37 'id', 'url', 'display_url', 'display', 'name', 'slug', 'description', 'owner', 'comments', 'tags', 

38 'custom_fields', 'created', 'last_updated', 'rack_count', 

39 ] 

40 brief_fields = ('id', 'url', 'display', 'name', 'slug', 'description', 'rack_count') 

41 

42 

43class RackRoleSerializer(OrganizationalModelSerializer): 

44 

45 # Related object counts 

46 rack_count = RelatedObjectCountField('racks') 

47 

48 class Meta: 

49 model = RackRole 

50 fields = [ 

51 'id', 'url', 'display_url', 'display', 'name', 'slug', 'color', 'description', 'owner', 'comments', 'tags', 

52 'custom_fields', 'created', 'last_updated', 'rack_count', 

53 ] 

54 brief_fields = ('id', 'url', 'display', 'name', 'slug', 'description', 'rack_count') 

55 

56 

57class RackBaseSerializer(PrimaryModelSerializer): 

58 form_factor = ChoiceField( 

59 choices=RackFormFactorChoices, 

60 allow_blank=True, 

61 required=False, 

62 allow_null=True 

63 ) 

64 width = ChoiceField( 

65 choices=RackWidthChoices, 

66 required=False 

67 ) 

68 outer_unit = ChoiceField( 

69 choices=RackDimensionUnitChoices, 

70 allow_blank=True, 

71 required=False, 

72 allow_null=True 

73 ) 

74 weight_unit = ChoiceField( 

75 choices=WeightUnitChoices, 

76 allow_blank=True, 

77 required=False, 

78 allow_null=True 

79 ) 

80 cooling_capability = ChoiceField( 

81 choices=RackCoolingCapabilityChoices, 

82 allow_blank=True, 

83 required=False, 

84 allow_null=True 

85 ) 

86 

87 

88class RackTypeSerializer(RackBaseSerializer): 

89 # Unlike Rack.form_factor (optional & nullable), RackType.form_factor is required 

90 # (blank=False, no default), so override RackBaseSerializer's optional declaration. 

91 form_factor = ChoiceField(choices=RackFormFactorChoices, required=True) 

92 manufacturer = ManufacturerSerializer(nested=True) 

93 rack_count = serializers.IntegerField(read_only=True) 

94 

95 class Meta: 

96 model = RackType 

97 fields = [ 

98 'id', 'url', 'display_url', 'display', 'manufacturer', 'model', 'slug', 'description', 'form_factor', 

99 'width', 'u_height', 'starting_unit', 'desc_units', 'outer_width', 'outer_height', 'outer_depth', 

100 'outer_unit', 'weight', 'max_weight', 'weight_unit', 'mounting_depth', 'cooling_capability', 

101 'cooling_capacity', 'description', 'owner', 'comments', 'tags', 'custom_fields', 'created', 'last_updated', 

102 'rack_count', 

103 ] 

104 brief_fields = ('id', 'url', 'display', 'manufacturer', 'model', 'slug', 'description', 'rack_count') 

105 

106 

107class RackSerializer(RackBaseSerializer): 

108 site = SiteSerializer( 

109 nested=True 

110 ) 

111 location = LocationSerializer( 

112 nested=True, 

113 required=False, 

114 allow_null=True, 

115 default=None 

116 ) 

117 group = RackGroupSerializer( 

118 nested=True, 

119 required=False, 

120 allow_null=True 

121 ) 

122 tenant = TenantSerializer( 

123 nested=True, 

124 required=False, 

125 allow_null=True 

126 ) 

127 status = ChoiceField( 

128 choices=RackStatusChoices, 

129 required=False 

130 ) 

131 airflow = ChoiceField( 

132 choices=RackAirflowChoices, 

133 allow_blank=True, 

134 required=False 

135 ) 

136 role = RackRoleSerializer( 

137 nested=True, 

138 required=False, 

139 allow_null=True 

140 ) 

141 facility_id = serializers.CharField( 

142 max_length=50, 

143 allow_blank=True, 

144 allow_null=True, 

145 label=_('Facility ID'), 

146 default=None 

147 ) 

148 rack_type = RackTypeSerializer( 

149 nested=True, 

150 required=False, 

151 allow_null=True, 

152 default=None 

153 ) 

154 

155 # Related object counts 

156 device_count = RelatedObjectCountField('devices') 

157 powerfeed_count = RelatedObjectCountField('powerfeeds') 

158 

159 class Meta: 

160 model = Rack 

161 fields = [ 

162 'id', 'url', 'display_url', 'display', 'name', 'facility_id', 'site', 'location', 'group', 'tenant', 

163 'status', 'role', 'serial', 'asset_tag', 'rack_type', 'form_factor', 'width', 'u_height', 'starting_unit', 

164 'weight', 'max_weight', 'weight_unit', 'desc_units', 'outer_width', 'outer_height', 'outer_depth', 

165 'outer_unit', 'mounting_depth', 'airflow', 'cooling_capability', 'cooling_capacity', 

166 'description', 'owner', 'comments', 'tags', 'custom_fields', 'created', 'last_updated', 'device_count', 

167 'powerfeed_count', 

168 ] 

169 brief_fields = ('id', 'url', 'display', 'name', 'description', 'device_count') 

170 

171 

172class RackReservationSerializer(PrimaryModelSerializer): 

173 rack = RackSerializer( 

174 nested=True, 

175 ) 

176 status = ChoiceField( 

177 choices=RackReservationStatusChoices, 

178 required=False, 

179 ) 

180 user = UserSerializer( 

181 nested=True, 

182 ) 

183 tenant = TenantSerializer( 

184 nested=True, 

185 required=False, 

186 allow_null=True, 

187 ) 

188 

189 unit_count = serializers.SerializerMethodField() 

190 

191 @extend_schema_field(OpenApiTypes.INT32) 

192 def get_unit_count(self, obj): 

193 return len(obj.units) 

194 

195 class Meta: 

196 model = RackReservation 

197 fields = [ 

198 'id', 'url', 'display_url', 'display', 'rack', 'units', 'unit_count', 'status', 'created', 'last_updated', 

199 'user', 'tenant', 'description', 'owner', 'comments', 'tags', 'custom_fields', 

200 ] 

201 brief_fields = ('id', 'url', 'display', 'status', 'user', 'description', 'units') 

202 

203 

204class RackElevationDetailFilterSerializer(serializers.Serializer): 

205 q = serializers.CharField( 

206 required=False, 

207 default=None 

208 ) 

209 face = serializers.ChoiceField( 

210 choices=DeviceFaceChoices, 

211 default=DeviceFaceChoices.FACE_FRONT 

212 ) 

213 render = serializers.ChoiceField( 

214 choices=RackElevationDetailRenderChoices, 

215 default=RackElevationDetailRenderChoices.RENDER_JSON 

216 ) 

217 unit_width = serializers.IntegerField( 

218 default=ConfigItem('RACK_ELEVATION_DEFAULT_UNIT_WIDTH') 

219 ) 

220 unit_height = serializers.IntegerField( 

221 default=ConfigItem('RACK_ELEVATION_DEFAULT_UNIT_HEIGHT') 

222 ) 

223 legend_width = serializers.IntegerField( 

224 default=RACK_ELEVATION_DEFAULT_LEGEND_WIDTH 

225 ) 

226 margin_width = serializers.IntegerField( 

227 default=RACK_ELEVATION_DEFAULT_MARGIN_WIDTH 

228 ) 

229 exclude = serializers.IntegerField( 

230 required=False, 

231 default=None 

232 ) 

233 expand_devices = serializers.BooleanField( 

234 required=False, 

235 default=True 

236 ) 

237 include_images = serializers.BooleanField( 

238 required=False, 

239 default=True 

240 )