Coverage for netbox/api/metadata.py: 87%
30 statements
« prev ^ index » next coverage.py v7.15.2, created at 2026-10-10 18:35 +0000
« prev ^ index » next coverage.py v7.15.2, created at 2026-10-10 18:35 +0000
1from django.core.exceptions import PermissionDenied
2from django.http import Http404
3from django.utils.encoding import force_str
4from rest_framework import exceptions
5from rest_framework.metadata import SimpleMetadata
6from rest_framework.request import clone_request
8from netbox.api.fields import ContentTypeField
11class BulkOperationMetadata(SimpleMetadata):
13 def determine_actions(self, request, view):
14 """
15 Replace the stock determine_actions() method to assess object permissions only
16 when viewing a specific object. This is necessary to support OPTIONS requests
17 with bulk update in place (see #5470).
18 """
19 actions = {}
20 for method in {'PUT', 'POST'} & set(view.allowed_methods):
21 view.request = clone_request(request, method)
22 try:
23 # Test global permissions
24 if hasattr(view, 'check_permissions'): 24 ↛ 27line 24 didn't jump to line 27 because the condition on line 24 was always true
25 view.check_permissions(view.request)
26 # Test object permissions (if viewing a specific object)
27 if method == 'PUT' and view.lookup_url_kwarg and hasattr(view, 'get_object'): 27 ↛ 28line 27 didn't jump to line 28 because the condition on line 27 was never true
28 view.get_object()
29 except (exceptions.APIException, PermissionDenied, Http404):
30 pass
31 else:
32 # If user has appropriate permissions for the view, include
33 # appropriate metadata about the fields that should be supplied.
34 serializer = view.get_serializer()
35 actions[method] = self.get_serializer_info(serializer)
36 finally:
37 view.request = request
39 return actions
42class ContentTypeMetadata(BulkOperationMetadata):
44 def get_field_info(self, field):
45 field_info = super().get_field_info(field)
46 if hasattr(field, 'queryset') and not field_info.get('read_only') and isinstance(field, ContentTypeField):
47 field_info['choices'] = [
48 {
49 'value': choice_value,
50 'display_name': force_str(choice_name, strings_only=True)
51 }
52 for choice_value, choice_name in field.choices.items()
53 ]
54 field_info['choices'].sort(key=lambda item: item['display_name'])
55 return field_info