Disallow related elements to be treated as choices

DRF will try to resolve potential candidates into the OPTIONS endpoint.
This is mainly to support their POST field in the browseable API.   We
don't need this and it can yield some expensive queries so we bypass
generating choices for any RelatedField fields
This commit is contained in:
Matthew Jones
2016-03-16 13:08:50 -04:00
parent 63b01bb04b
commit 45f95bf2b2

View File

@@ -1,6 +1,8 @@
# Copyright (c) 2016 Ansible, Inc. # Copyright (c) 2016 Ansible, Inc.
# All Rights Reserved. # All Rights Reserved.
from collections import OrderedDict
# Django # Django
from django.core.exceptions import PermissionDenied from django.core.exceptions import PermissionDenied
from django.http import Http404 from django.http import Http404
@@ -10,6 +12,7 @@ from django.utils.encoding import force_text
from rest_framework import exceptions from rest_framework import exceptions
from rest_framework import metadata from rest_framework import metadata
from rest_framework import serializers from rest_framework import serializers
from rest_framework.relations import RelatedField
from rest_framework.request import clone_request from rest_framework.request import clone_request
# Ansible Tower # Ansible Tower
@@ -37,9 +40,20 @@ class Metadata(metadata.SimpleMetadata):
return field_info return field_info
def get_field_info(self, field): def get_field_info(self, field):
field_info = super(Metadata, self).get_field_info(field) field_info = OrderedDict()
if hasattr(field, 'choices') and field.choices: field_info['type'] = self.label_lookup[field]
field_info = self._render_read_only_choices(field, field_info) field_info['required'] = getattr(field, 'required', False)
text_attrs = [
'read_only', 'label', 'help_text',
'min_length', 'max_length',
'min_value', 'max_value'
]
for attr in text_attrs:
value = getattr(field, attr, None)
if value is not None and value != '':
field_info[attr] = force_text(value, strings_only=True)
# Indicate if a field has a default value. # Indicate if a field has a default value.
# FIXME: Still isn't showing all default values? # FIXME: Still isn't showing all default values?
@@ -48,21 +62,18 @@ class Metadata(metadata.SimpleMetadata):
except serializers.SkipField: except serializers.SkipField:
pass pass
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 hasattr(field, 'choices') and not isinstance(field, RelatedField):
field_info['choices'] = [(choice_value, choice_name) for choice_value, choice_name in field.choices.items()]
# Indicate if a field is write-only. # Indicate if a field is write-only.
if getattr(field, 'write_only', False): if getattr(field, 'write_only', False):
field_info['write_only'] = True field_info['write_only'] = True
# Update choices to be a list of 2-tuples instead of list of dicts with
# value/display_name.
if 'choices' in field_info:
choices = []
for choice in field_info['choices']:
if isinstance(choice, dict):
choices.append((choice.get('value'), choice.get('display_name')))
else:
choices.append(choice)
field_info['choices'] = choices
# Special handling of inventory source_region choices that vary based on # Special handling of inventory source_region choices that vary based on
# selected inventory source. # selected inventory source.
if field.field_name == 'source_regions': if field.field_name == 'source_regions':