jumpserver/apps/common/drf/metadata.py

127 lines
4.7 KiB
Python
Raw Normal View History

2019-05-16 06:41:11 +00:00
# -*- coding: utf-8 -*-
#
from __future__ import unicode_literals
from collections import OrderedDict
import datetime
2019-05-16 06:41:11 +00:00
from django.core.exceptions import PermissionDenied
from django.http import Http404
from django.utils.encoding import force_text
2020-10-19 12:13:01 +00:00
from rest_framework.fields import empty
2019-05-16 06:41:11 +00:00
from rest_framework.metadata import SimpleMetadata
from rest_framework import exceptions, serializers
from rest_framework.request import clone_request
class SimpleMetadataWithFilters(SimpleMetadata):
"""Override SimpleMetadata, adding info about filters"""
methods = {"PUT", "POST", "GET"}
attrs = [
'read_only', 'label', 'help_text',
'min_length', 'max_length',
'min_value', 'max_value', "write_only",
2019-05-16 06:41:11 +00:00
]
def determine_actions(self, request, view):
"""
For generic class based views we return information about
the fields that are accepted for 'PUT' and 'POST' methods.
"""
actions = {}
for method in self.methods & set(view.allowed_methods):
view.request = clone_request(request, method)
try:
# Test global permissions
if hasattr(view, 'check_permissions'):
view.check_permissions(view.request)
# Test object permissions
if method == 'PUT' and hasattr(view, 'get_object'):
view.get_object()
except (exceptions.APIException, PermissionDenied, Http404):
pass
else:
# If user has appropriate permissions for the view, include
# appropriate metadata about the fields that should be supplied.
serializer = view.get_serializer()
actions[method] = self.get_serializer_info(serializer)
finally:
view.request = request
return actions
def get_field_info(self, field):
"""
Given an instance of a serializer field, return a dictionary
of metadata about it.
"""
field_info = OrderedDict()
field_info['type'] = self.label_lookup[field]
field_info['required'] = getattr(field, 'required', False)
default = getattr(field, 'default', None)
if default is not None and default != empty:
if isinstance(default, (str, int, bool, datetime.datetime, list)):
field_info['default'] = default
2020-10-19 12:13:01 +00:00
2019-05-16 06:41:11 +00:00
for attr in self.attrs:
value = getattr(field, attr, None)
if value is not None and value != '':
field_info[attr] = force_text(value, strings_only=True)
if getattr(field, 'child', None):
field_info['child'] = self.get_field_info(field.child)
elif getattr(field, 'fields', None):
field_info['children'] = self.get_serializer_info(field)
if not isinstance(field, (serializers.RelatedField, serializers.ManyRelatedField)) \
and hasattr(field, 'choices'):
2019-05-16 06:41:11 +00:00
field_info['choices'] = [
{
'value': choice_value,
'display_name': force_text(choice_name, strings_only=True)
}
for choice_value, choice_name in field.choices.items()
]
return field_info
def get_filters_fields(self, request, view):
fields = []
if hasattr(view, 'get_filter_fields'):
fields = view.get_filter_fields(request)
2019-05-16 06:41:11 +00:00
elif hasattr(view, 'filter_fields'):
fields = view.filter_fields
elif hasattr(view, 'filterset_fields'):
fields = view.filterset_fields
elif hasattr(view, 'get_filterset_fields'):
fields = view.get_filterset_fields(request)
2021-02-22 10:35:53 +00:00
elif hasattr(view, 'filterset_class'):
fields = view.filterset_class.Meta.fields
if isinstance(fields, dict):
fields = list(fields.keys())
2019-05-16 06:41:11 +00:00
return fields
def get_ordering_fields(self, request, view):
fields = []
if hasattr(view, 'get_ordering_fields'):
fields = view.get_ordering_fields(request)
2019-05-16 06:41:11 +00:00
elif hasattr(view, 'ordering_fields'):
fields = view.ordering_fields
2019-05-16 06:41:11 +00:00
return fields
def determine_metadata(self, request, view):
metadata = super(SimpleMetadataWithFilters, self).determine_metadata(request, view)
filterset_fields = self.get_filters_fields(request, view)
2019-05-16 06:41:11 +00:00
order_fields = self.get_ordering_fields(request, view)
meta_get = metadata.get("actions", {}).get("GET", {})
for k, v in meta_get.items():
if k in filterset_fields:
2019-05-16 06:41:11 +00:00
v["filter"] = True
if k in order_fields:
v["order"] = True
return metadata