Beispiel #1
0
    def get_field_info(self, field):
        field_info = super(LinkMetaData, self).get_field_info(field)
        field_info = OrderedDict()
        field_info['type'] = self.label_lookup[field]
        field_info['required'] = getattr(field, 'required', False)

        attrs = [
            'read_only', 'label', 'help_text',
            'min_length', 'max_length',
            'min_value', 'max_value'
        ]

        for attr in 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 field_info.get('read_only') and hasattr(field, 'choices'):
            field_info['choices'] = []
            for data, junk in field.choices.items():
                if data and (data != 'None'):
                    data = ast.literal_eval(data)
                    field_info['choices'].append(
                        {
                            'value': data['id'],
                            'display_name': force_text(
                                data['name'],
                                strings_only=True)
                        }
                    )
        return field_info
    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)

        attrs = [
            'read_only', 'label', 'help_text',
            'min_length', 'max_length',
            'min_value', 'max_value'
        ]

        for attr in attrs:
            value = getattr(field, attr, None)
            if value is not None and value != '':
                field_info[attr] = force_text(value, strings_only=True)

        if not field_info.get('read_only') and hasattr(field, 'choices'):
            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
Beispiel #3
0
class BindingDict(object):
    """
    This dict-like object is used to store fields on a serializer.

    This ensures that whenever fields are added to the serializer we call
    `field.bind()` so that the `field_name` and `parent` attributes
    can be set correctly.
    """
    def __init__(self, serializer):
        self.serializer = serializer
        self.fields = OrderedDict()

    def __setitem__(self, key, field):
        self.fields[key] = field
        field.bind(field_name=key, parent=self.serializer)

    def __getitem__(self, key):
        return self.fields[key]

    def __delitem__(self, key):
        del self.fields[key]

    def items(self):
        return self.fields.items()

    def keys(self):
        return self.fields.keys()

    def values(self):
        return self.fields.values()
def _merge_fields_and_pk(pk, fields):
    fields_and_pk = OrderedDict()
    fields_and_pk['pk'] = pk
    fields_and_pk[pk.name] = pk
    fields_and_pk.update(fields)

    return fields_and_pk
class BindingDict(object):
    """
    This dict-like object is used to store fields on a serializer.

    This ensures that whenever fields are added to the serializer we call
    `field.bind()` so that the `field_name` and `parent` attributes
    can be set correctly.
    """
    def __init__(self, serializer):
        self.serializer = serializer
        self.fields = OrderedDict()

    def __setitem__(self, key, field):
        self.fields[key] = field
        field.bind(field_name=key, parent=self.serializer)

    def __getitem__(self, key):
        return self.fields[key]

    def __delitem__(self, key):
        del self.fields[key]

    def items(self):
        return self.fields.items()

    def keys(self):
        return self.fields.keys()

    def values(self):
        return self.fields.values()
    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)

        attrs = [
            'read_only', 'label', 'help_text', 'min_length', 'max_length',
            'min_value', 'max_value'
        ]

        for attr in attrs:
            value = getattr(field, attr, None)
            if value is not None and value != '':
                field_info[attr] = force_text(value, strings_only=True)

        if not field_info.get('read_only') and hasattr(field, 'choices'):
            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
Beispiel #7
0
    def get_field_info(self, field):
        """
        Custom get field info so extra parameters of custom fields are displayed as well.
        """
        field_info = OrderedDict()
        field_info['type'] = self.label_lookup[field]
        field_info['required'] = getattr(field, 'required', False)

        attrs = [
            'read_only', 'label', 'help_text',
            'min_length', 'max_length',
            'min_value', 'max_value'
        ]

        # This is the custom part, load extra field attrs if necessary.
        if hasattr(field, 'extra_field_attrs'):
            attrs += field.extra_field_attrs

        for attr in attrs:
            value = getattr(field, attr, None)
            if value is not None and value != '':
                field_info[attr] = force_text(value, strings_only=True)

        if not field_info.get('read_only') and hasattr(field, 'choices'):
            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 _merge_fields_and_pk(pk, fields):
    fields_and_pk = OrderedDict()
    fields_and_pk['pk'] = pk
    fields_and_pk[pk.name] = pk
    fields_and_pk.update(fields)

    return fields_and_pk
    def __init__(self, choices, **kwargs):
        # Allow either single or paired choices style:
        # choices = [1, 2, 3]
        # choices = [(1, 'First'), (2, 'Second'), (3, 'Third')]
        pairs = [
            isinstance(item, (list, tuple)) and len(item) == 2
            for item in choices
        ]
        if all(pairs):
            self.choices = OrderedDict([(key, display_value) for key, display_value in choices])
        else:
            self.choices = OrderedDict([(item, item) for item in choices])

        # Map the string representation of choices to the underlying value.
        # Allows us to deal with eg. integer choices while supporting either
        # integer or string input, but still get the correct datatype out.
        self.choice_strings_to_values = dict([
            (six.text_type(key), key) for key in self.choices.keys()
        ])

        super(ChoiceField, self).__init__(**kwargs)
        
        if not self.required:
            self.choices[''] = ''
            self.choice_strings_to_values[''] = ''
Beispiel #10
0
 def test_active_model_json_renderer(self):
     parents = [ParentModel.objects.create() for x in range(3)]
     children = [
         ChildModel.objects.create(parent=parents[1],
                                   old_parent=parents[2]),
         ChildModel.objects.create(parent=parents[1],
                                   old_parent=parents[2]),
         ChildModel.objects.create(parent=parents[0], old_parent=parents[1])
     ]
     obj = ChildSideloadSerializer(children, many=True).data
     expected = {
         'child_models': [
             OrderedDict([('id', c.id), ('parent_id', c.parent.id),
                          ('old_parent_id', c.old_parent.id)])
             for c in children
         ],
         'parent_models': [
             OrderedDict([('id', p.id), ('text', p.text),
                          ('child_ids', p.child_ids),
                          ('old_child_ids', p.old_child_ids)])
             for p in parents
         ]
     }
     result = convert_to_active_model_json(obj)
     assert result == expected
    def to_internal_value(self, data):
        """
        Dict of native values <- Dict of primitive datatypes.
        """
        ret = OrderedDict()
        errors = OrderedDict()
        fields = [
            field for field in self.fields.values()
            if (not field.read_only) or (field.default is not empty)
        ]

        for field in fields:
            validate_method = getattr(self, 'validate_' + field.field_name, None)
            primitive_value = field.get_value(data)
            try:
                validated_value = field.run_validation(primitive_value)
                if validate_method is not None:
                    validated_value = validate_method(validated_value)
            except ValidationError as exc:
                errors[field.field_name] = exc.detail
            except SkipField:
                pass
            else:
                set_value(ret, field.source_attrs, validated_value)

        if errors:
            raise ValidationError(errors)

        return ret
    def get_initial(self):
        if self._initial_data is not None:
            return OrderedDict([
                (field_name, field.get_value(self._initial_data))
                for field_name, field in self.fields.items()
                if field.get_value(self._initial_data) is not empty
                and not field.read_only
            ])

        return OrderedDict([(field.field_name, field.get_initial())
                            for field in self.fields.values()
                            if not field.read_only])
Beispiel #13
0
 def to_representation(self, instance):
     """
     Overrides to nest the primary record and add sideloads.
     """
     ret = OrderedDict()
     base_data = self.base_serializer.__class__(
         instance,
         many=True,
         context=self.context
     ).data
     ret[pluralize(self.base_key)] = base_data
     ret.update(self.get_sideload_objects(instance))
     return ret
Beispiel #14
0
    def to_representation(self, instance):
        """
        Overrides the DRF method to add a root key and sideloads.
        """
        # self.base_serializer.instance = instance
        base_result = self.base_serializer.data
        if self.is_nested:
            return base_result

        ret = OrderedDict()
        key = self.base_key
        ret[key] = base_result
        ret.update(self.get_sideload_objects(instance))
        return ret
Beispiel #15
0
 def test_compact(self):
     renderer = JSONRenderer()
     data = OrderedDict([('a', 1), ('b', 2)])
     context = {'indent': 4}
     assert (renderer.render(
         data,
         renderer_context=context) == b'{\n    "a": 1,\n    "b": 2\n}')
Beispiel #16
0
class ChoiceField(Field):
    default_error_messages = {
        'invalid_choice': _('`{input}` is not a valid choice.')
    }

    def __init__(self, choices, **kwargs):
        # Allow either single or paired choices style:
        # choices = [1, 2, 3]
        # choices = [(1, 'First'), (2, 'Second'), (3, 'Third')]
        pairs = [
            isinstance(item, (list, tuple)) and len(item) == 2
            for item in choices
        ]
        if all(pairs):
            self.choices = OrderedDict([(key, display_value) for key, display_value in choices])
        else:
            self.choices = OrderedDict([(item, item) for item in choices])

        # Map the string representation of choices to the underlying value.
        # Allows us to deal with eg. integer choices while supporting either
        # integer or string input, but still get the correct datatype out.
        self.choice_strings_to_values = dict([
            (six.text_type(key), key) for key in self.choices.keys()
        ])

        super(ChoiceField, self).__init__(**kwargs)

    def to_internal_value(self, data):
        try:
            return self.choice_strings_to_values[six.text_type(data)]
        except KeyError:
            self.fail('invalid_choice', input=data)

    def to_representation(self, value):
        return self.choice_strings_to_values[six.text_type(value)]
Beispiel #17
0
def format_keys(obj, format_type=None):
    """
    Takes either a dict or list and returns it with camelized keys only if
    REST_EMBER_FORMAT_KEYS is set.

    :format_type: Either 'camelize' or 'underscore'
    """
    if (getattr(settings, 'REST_EMBER_FORMAT_KEYS', False)
            and format_type in ('camelize', 'underscore')):

        if isinstance(obj, dict):
            formatted = OrderedDict()
            for key, value in obj.items():
                if format_type == 'camelize':
                    formatted[inflection.camelize(key, False)]\
                        = format_keys(value, format_type)
                elif format_type == 'underscore':
                    formatted[inflection.underscore(key)]\
                        = format_keys(value, format_type)
            return formatted
        if isinstance(obj, list):
            return [format_keys(item, format_type) for item in obj]
        else:
            return obj
    else:
        return obj
Beispiel #18
0
def _get_reverse_relationships(opts):
    """
    Returns an `OrderedDict` of field names to `RelationInfo`.
    """
    reverse_relations = OrderedDict()
    for relation in opts.get_all_related_objects():
        accessor_name = relation.get_accessor_name()
        reverse_relations[accessor_name] = RelationInfo(
            model_field=None,
            related=relation.model,
            to_many=relation.field.rel.multiple,
            has_through_model=False
        )

    # Deal with reverse many-to-many relationships.
    for relation in opts.get_all_related_many_to_many_objects():
        accessor_name = relation.get_accessor_name()
        reverse_relations[accessor_name] = RelationInfo(
            model_field=None,
            related=relation.model,
            to_many=True,
            has_through_model=(
                (getattr(relation.field.rel, 'through', None) is not None)
                and not relation.field.rel.through._meta.auto_created
            )
        )

    return reverse_relations
Beispiel #19
0
    def to_representation(self, obj):
        answer = {}

        self.tryKeysOnDict(answer, 'guid', obj, ['guid'])
        self.tryKeysOnDict(answer, 'title', obj, ['title'])
        self.tryKeysOnDict(answer, 'description', obj, ['description'])
        self.tryKeysOnDict(answer, 'user', obj, ['author', 'owner_nick'])
        self.tryKeysOnDict(answer, 'tags', obj, ['tags'])
        self.tryKeysOnDict(answer, 'created_at', obj, ['created_at'])
        self.tryKeysOnDict(answer, 'endpoint', obj, ['endpoint', 'end_point'])
        self.tryKeysOnDict(answer, 'link', obj, ['permalink'])
        self.tryKeysOnDict(answer, 'category_name', obj, ['category_name'])
        self.tryKeysOnDict(answer, 'parameters', obj, ['parameters'])
        self.tryKeysOnDict(answer, 'result', obj, ['result'])
        self.tryKeysOnDict(answer, 'timestamp', obj, ['timestamp'])
        self.tryKeysOnDict(answer, 'category_id', obj, ['category', 'category_id'])

        try:
            if 'format' in obj and obj['format'].startswith('application/json'):
                answer['result'] = json.loads(answer['result']) 
        except AttributeError:
            # TODO: ver esto, plis
            pass

        if answer['tags']:
            answer['tags'] = map(lambda x: x['tag__name'] if type(x) == dict else x, answer['tags'])

        if answer['link']:
            domain = self.context['request'].auth['microsite_domain']
            answer['link'] = domain + answer['link']
        return OrderedDict(answer)
Beispiel #20
0
def _get_forward_relationships(opts):
    """
    Returns an `OrderedDict` of field names to `RelationInfo`.
    """
    forward_relations = OrderedDict()
    for field in [field for field in opts.fields if field.serialize and field.rel]:
        forward_relations[field.name] = RelationInfo(
            model_field=field,
            related_model=_resolve_model(field.rel.to),
            to_many=False,
            has_through_model=False
        )

    # Deal with forward many-to-many relationships.
    for field in [field for field in opts.many_to_many if field.serialize]:
        forward_relations[field.name] = RelationInfo(
            model_field=field,
            related_model=_resolve_model(field.rel.to),
            to_many=True,
            has_through_model=(
                not field.rel.through._meta.auto_created
            )
        )

    return forward_relations
Beispiel #21
0
 def get_paginated_response(self, data):
     return Response(OrderedDict([
         ('count', self.count),
         ('next', self.get_next_link()),
         ('previous', self.get_previous_link()),
         ('results', data)
     ]))
Beispiel #22
0
    def get_meta(self):
        pagination = {
            'pages': self.page.paginator.num_pages,
            'first': None,
            'previous': None,
            'next': None,
            'last': None,
            'before': 0,
            'more': 0,
        }

        if self.page.has_previous():
            pagination['first'] = 1
            if self.page.previous_page_number() > 1:
                pagination['previous'] = self.page.previous_page_number()

        if self.page.has_next():
            pagination['last'] = self.page.paginator.num_pages
            if self.page.next_page_number() < self.page.paginator.num_pages:
                pagination['next'] = self.page.next_page_number()

        if self.page.start_index():
            pagination['before'] = self.page.start_index() - 1
        pagination['more'] = self.page.paginator.count - self.page.end_index()

        return OrderedDict([('count', self.page.paginator.count),
                            ('pages', pagination['pages']),
                            ('first', pagination['first']),
                            ('previous', pagination['previous']),
                            ('next', pagination['next']),
                            ('last', pagination['last']),
                            ('before', pagination['before']),
                            ('more', pagination['more'])])
def _get_reverse_relationships(opts):
    """
    Returns an `OrderedDict` of field names to `RelationInfo`.
    """
    # Note that we have a hack here to handle internal API differences for
    # this internal API across Django 1.7 -> Django 1.8.
    # See: https://code.djangoproject.com/ticket/24208

    reverse_relations = OrderedDict()
    for relation in opts.get_all_related_objects():
        accessor_name = relation.get_accessor_name()
        related = getattr(relation, 'related_model', relation.model)
        reverse_relations[accessor_name] = RelationInfo(
            model_field=None,
            related_model=related,
            to_many=relation.field.rel.multiple,
            has_through_model=False)

    # Deal with reverse many-to-many relationships.
    for relation in opts.get_all_related_many_to_many_objects():
        accessor_name = relation.get_accessor_name()
        related = getattr(relation, 'related_model', relation.model)
        reverse_relations[accessor_name] = RelationInfo(
            model_field=None,
            related_model=related,
            to_many=True,
            has_through_model=(
                (getattr(relation.field.rel, 'through', None) is not None)
                and not relation.field.rel.through._meta.auto_created))

    return reverse_relations
    def get_api_root_view(self):
        """
        Return a view to use as the API root.
        """
        api_root_dict = OrderedDict()
        list_name = self.routes[0].name
        for prefix, viewset, basename in self.registry:
            api_root_dict[prefix] = list_name.format(basename=basename)

        class APIRoot(views.APIView):
            _ignore_model_permissions = True

            def get(self, request, *args, **kwargs):
                ret = OrderedDict()
                namespace = get_resolver_match(request).namespace
                for key, url_name in api_root_dict.items():
                    if namespace:
                        url_name = namespace + ':' + url_name
                    try:
                        ret[key] = reverse(url_name,
                                           args=args,
                                           kwargs=kwargs,
                                           request=request,
                                           format=kwargs.get('format', None))
                    except NoReverseMatch:
                        # Don't bail out if eg. no list routes exist, only detail routes.
                        continue

                return Response(ret)

        return APIRoot.as_view()
 def get_paginated_response(self, data):
     return Response(
         OrderedDict([('count', self.page.paginator.count),
                      ('next', self.get_next_link()),
                      ('previous', self.get_previous_link()),
                      ('facets', self.facets),
                      ('suggestions', self.suggestions),
                      ('results', data)]))
def _get_fields(opts):
    fields = OrderedDict()
    for field in [
            field for field in opts.fields if field.serialize and not field.rel
    ]:
        fields[field.name] = field

    return fields
    def test_default_display_value(self):
        class TestSerializer(serializers.ModelSerializer):
            class Meta:
                model = DisplayValueModel

        serializer = TestSerializer()
        expected = OrderedDict([('1', 'Red Color'), ('2', 'Yellow Color'), ('3', 'Green Color')])
        self.assertEqual(serializer.fields['color'].choices, expected)
Beispiel #28
0
 def get_paginated_response(self, data):
     print "Entra en paginado"
     return Response(OrderedDict([
         ('total', self.count),
         ('next', self.get_next_link()),
         ('previous', self.get_previous_link()),
         ('items', data )
     ]))
def get_field_info(model):
    """
    Given a model class, returns a `FieldInfo` instance containing metadata
    about the various field types on the model.
    """
    # Deal with the primary key.
    pk = model.id if not issubclass(model, mongoengine.EmbeddedDocument) else None

    # Deal with regular fields.
    fields = OrderedDict()

    for field_name in model._fields_ordered:
        fields[field_name] = model._fields[field_name]

    # Deal with forward relationships.
    # Pass forward relations since there is no relations on mongodb
    forward_relations = OrderedDict()

    # Deal with reverse relationships.
    # Pass reverse relations since there is no relations on mongodb
    reverse_relations = OrderedDict()

    # Shortcut that merges both regular fields and the pk,
    # for simplifying regular field lookup.
    fields_and_pk = OrderedDict()
    fields_and_pk["pk"] = pk
    fields_and_pk[getattr(pk, "name", "pk")] = pk
    fields_and_pk.update(fields)

    # Shortcut that merges both forward and reverse relationships

    relations = OrderedDict(list(forward_relations.items()) + list(reverse_relations.items()))

    return FieldInfo(pk, fields, forward_relations, reverse_relations, fields_and_pk, relations)
 def get_paginated_response(self, data):
     return Response(OrderedDict([
         ('count', self.page.paginator.count),
         ('next', self.get_next_link()),
         ('previous', self.get_previous_link()),
         ('current_page', self.page.number),
         ('total_pages', self.page.paginator.num_pages),
         ('results', data)
     ]))
Beispiel #31
0
 def get_paginated_response(self, data):
     return OrderedDict([('start_index', self.page.start_index()),
                         ('end_index', self.page.end_index()),
                         ('num_pages', self.page.paginator.num_pages),
                         ('current_page', self.page.number),
                         ('count', self.page.paginator.count),
                         ('next', self.get_next_link()),
                         ('previous', self.get_previous_link()),
                         ('results', data)])
 def __init__(self, renderer, serialized_data, serializer=None):
     self.renderer = renderer
     self.serialized_data = serialized_data
     if serializer:
         self.serializer = get_serializer(serializer)
     else:
         self.serializer = get_serializer(serialized_data.serializer)
     self.hash = OrderedDict({"data": []})
     self.included_set = set()
    def choices(self):
        queryset = self.get_queryset()
        if queryset is None:
            # Ensure that field.choices returns something sensible
            # even when accessed with a read-only field.
            return {}

        return OrderedDict([(six.text_type(self.to_representation(item)),
                             six.text_type(item)) for item in queryset])
Beispiel #34
0
    def get_fields(self):
        """
        Get the required fields for serializing the result.
        """

        fields = getattr(self.Meta, "fields", [])
        exclude = getattr(self.Meta, "exclude", [])

        if fields and exclude:
            raise ImproperlyConfigured(
                "Cannot set both `fields` and `exclude`.")

        ignore_fields = getattr(self.Meta, "ignore_fields", [])
        indices = getattr(self.Meta, "index_classes")

        declared_fields = copy.deepcopy(self._declared_fields)
        prefix_field_names = len(indices) > 1
        field_mapping = OrderedDict()

        # overlapping fields on multiple indices is supported by internally prefixing the field
        # names with the index class to which they belong or, optionally, a user-provided alias
        # for the index.
        for index_cls in self.Meta.index_classes:
            prefix = ""
            if prefix_field_names:
                prefix = "_%s__" % self._get_index_class_name(index_cls)
            for field_name, field_type in six.iteritems(index_cls.fields):
                orig_name = field_name
                field_name = "%s%s" % (prefix, field_name)

                # This has become a little more complex, but provides convenient flexibility for users
                if not exclude:
                    if orig_name not in fields and field_name not in fields:
                        continue
                elif orig_name in exclude or field_name in exclude or orig_name in ignore_fields or field_name in ignore_fields:
                    continue

                # Look up the field attributes on the current index model,
                # in order to correctly instantiate the serializer field.
                model = index_cls().get_model()
                kwargs = self._get_default_field_kwargs(model, field_type)
                kwargs['prefix_field_names'] = prefix_field_names
                field_mapping[field_name] = self._field_mapping[field_type](
                    **kwargs)

        # Add any explicitly declared fields. They *will* override any index fields
        # in case of naming collision!.
        if declared_fields:
            for field_name in declared_fields:
                if field_name in field_mapping:
                    warnings.warn(
                        "Field '{field}' already exists in the field list. This *will* "
                        "overwrite existing field '{field}'".format(
                            field=field_name))
                field_mapping[field_name] = declared_fields[field_name]
        return field_mapping
 def determine_metadata(self, request, view):
     metadata = OrderedDict()
     metadata['name'] = view.get_view_name()
     metadata['description'] = view.get_view_description()
     metadata['renders'] = [renderer.media_type for renderer in view.renderer_classes]
     metadata['parses'] = [parser.media_type for parser in view.parser_classes]
     if hasattr(view, 'get_serializer'):
         actions = self.determine_actions(request, view)
         if actions:
             metadata['actions'] = actions
     return metadata
Beispiel #36
0
 def choices(self):
     queryset = self.child_relation.queryset
     iterable = queryset.all() if (hasattr(queryset, 'all')) else queryset
     items_and_representations = [
         (item, self.child_relation.to_representation(item))
         for item in iterable
     ]
     return OrderedDict([
         (six.text_type(item_representation),
          six.text_type(item) + ' - ' + six.text_type(item_representation))
         for item, item_representation in items_and_representations
     ])
Beispiel #37
0
 def get_serializer_info(self, serializer):
     """
     Given an instance of a serializer, return a dictionary of metadata
     about its fields.
     """
     if hasattr(serializer, 'child'):
         # If this is a `ListSerializer` then we want to examine the
         # underlying child serializer instance instead.
         serializer = serializer.child
     return OrderedDict([(field_name, self.get_field_info(field))
                         for field_name, field in serializer.fields.items()
                         ])
Beispiel #38
0
            def get(self, request, *args, **kwargs):
                ret = OrderedDict()
                for key, url_name in api_root_dict.items():
                    try:
                        ret[key] = reverse(url_name,
                                           request=request,
                                           format=kwargs.get('format', None))
                    except NoReverseMatch:
                        # Don't bail out if eg. no list routes exist, only detail routes.
                        continue

                return Response(ret)
Beispiel #39
0
    def post(self, request, *args, **kwargs):
        lng, lat = request.data.get('longitude'), request.data.get('latitude')

        err = self._validate_lat_long(lat, lng)
        if err:
            return views.Response(err, status=400)

        try:
            point = Point(x=lng, y=lat)
        except TypeError:  # pragma: no cover
            # this is one wiered edgecase
            return views.Response(
                {
                    rest_settings.api_settings.NON_FIELD_ERRORS_KEY: [
                        "Invalid value given for longitude or latitude",
                    ],
                },
                status=400)

        try:
            data = WardBoundary.objects.values(
                'area',
                'area__name',
                'area__code',
                'area__constituency',
                'area__constituency__name',
                'area__constituency__code',
                'area__constituency__county',
                'area__constituency__county__name',
                'area__constituency__county__code',
            ).get(mpoly__contains=point)

            return views.Response(
                OrderedDict([
                    ('ward', data['area']),
                    ('ward_name', data['area__name']),
                    ('ward_code', data['area__code']),
                    ('constituency', data['area__constituency']),
                    ('constituency_name', data['area__constituency__name']),
                    ('constituency_code', data['area__constituency__code']),
                    ('county', data['area__constituency__county']),
                    ('county_name', data['area__constituency__county__name']),
                    ('county_code', data['area__constituency__county__code']),
                ]))
        except WardBoundary.DoesNotExist:
            return views.Response(
                {
                    rest_settings.api_settings.NON_FIELD_ERRORS_KEY: [
                        "No ward contains the coordinates ({}, {})".format(
                            lng, lat)
                    ]
                },
                status=400)
Beispiel #40
0
    def __init__(self, choices, **kwargs):
        # Allow either single or paired choices style:
        # choices = [1, 2, 3]
        # choices = [(1, 'First'), (2, 'Second'), (3, 'Third')]
        pairs = [
            isinstance(item, (list, tuple)) and len(item) == 2
            for item in choices
        ]
        if all(pairs):
            self.choices = OrderedDict([(key, display_value)
                                        for key, display_value in choices])
        else:
            self.choices = OrderedDict([(item, item) for item in choices])

        # Map the string representation of choices to the underlying value.
        # Allows us to deal with eg. integer choices while supporting either
        # integer or string input, but still get the correct datatype out.
        self.choice_strings_to_values = dict([(six.text_type(key), key)
                                              for key in self.choices.keys()])

        super(ChoiceField, self).__init__(**kwargs)
Beispiel #41
0
 def get_paginated_response(self, data):
     response = Response(
         OrderedDict([
             ('count', len(data)),
             ('time-to-update-participant-number',
              Settings.manager.first().update_time_participant_number),
             ('next', None), ('previous', None), ('results', data)
         ]))
     if not self.show_all_elements():
         response.data.update(
             super(StandardResultsSetPagination,
                   self).get_paginated_response(data).data)
     return response
Beispiel #42
0
    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)

        attrs = ["read_only", "label", "help_text", "min_length", "max_length", "min_value", "max_value"]

        for attr in attrs:
            value = getattr(field, attr, None)
            if value is not None and value != "":
                field_info[attr] = force_text(value, strings_only=True)

        if not field_info.get("read_only") and hasattr(field, "choices"):
            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 __init__(self, serializer):
     self.serializer = serializer
     self.fields = OrderedDict()
class JsonApiAdapter(object):
    def __init__(self, renderer, serialized_data, serializer=None):
        self.renderer = renderer
        self.serialized_data = serialized_data
        if serializer:
            self.serializer = get_serializer(serializer)
        else:
            self.serializer = get_serializer(serialized_data.serializer)
        self.hash = OrderedDict({"data": []})
        self.included_set = set()

    def serializable_hash(self):
        if isinstance(self.serialized_data, list):
            for obj in self.serialized_data:
                result = JsonApiAdapter(self.renderer, obj,
                                        self.serializer).serializable_hash()
                self.hash["data"].append(result.get("data"))
                if result.get("included"):
                    if "included" not in self.hash:
                        self.hash["included"] = []
                    for result in result.get("included"):
                        set_key = "-".join([result.get("type"),
                                            result.get("id")])
                        if set_key not in self.included_set:
                            self.hash["included"].append(result)
                            self.included_set.add(set_key)
        else:
            self.hash["data"] = self.attributes_for_serialized_data(
                self.serialized_data, self.serializer)
            self.add_resource_relationships(
                self.hash["data"], self.serialized_data, self.serializer)
        return self.hash

    def add_relationships(self, resource, rel_name, relationship):
        dash_name = dasherize(rel_name)
        if dash_name not in resource["relationships"]:
            resource["relationships"][dash_name] = OrderedDict({
                "data": []
            })
        if relationship.get("data"):
            for data in relationship.get("data"):
                try:
                    rel_id = data.get("id")  # Serialized data
                except AttributeError:
                    rel_id = data  # Only IDs
                resource["relationships"][dash_name]["data"].append(
                    OrderedDict([
                        ("id", force_text(rel_id)),
                        ("type", relationship.get("type")),
                    ])
                )

    def add_relationship(self, resource, rel_name, relationship):
        dash_name = dasherize(rel_name)
        if dash_name not in resource["relationships"]:
            resource["relationships"][dash_name] = OrderedDict({
                "data": None
            })
        if relationship.get("data"):
            try:
                rel_id = relationship.get("data").get("id")  # Serialized data
            except AttributeError:
                rel_id = relationship.get("data")  # Only ID
            resource["relationships"][dasherize(rel_name)]["data"] = \
                OrderedDict([
                    ("id", force_text(rel_id)),
                    ("type", relationship.get("type")),
                ])

    def add_included(self, rel_name, relationship, parent=None):
        included_serializer = self.get_included_serializer(
            relationship.get("parent_serializer"), rel_name)
        if not included_serializer:
            return
        serialized_data = relationship.get("data")
        if not isinstance(serialized_data, list):
            serialized_data = [serialized_data]
        included_data = []
        for item in serialized_data:
            if isinstance(item, six.integer_types):
                # Only ID
                data = self.get_included_data(
                    rel_name, item, included_serializer)
                if data:
                    included_data.append(data)

        resource_path = ".".join([parent, rel_name] if parent else [rel_name])
        if self.include_assoc(resource_path):
            if "included" not in self.hash:
                self.hash["included"] = []
            for data in included_data:
                attrs = self.attributes_for_serialized_data(
                    data, included_serializer)
                self.add_resource_relationships(
                    attrs, data, included_serializer, add_included=False)
                if attrs not in self.hash.get("included"):
                    self.hash["included"].append(attrs)
        if self.include_nested_assoc(resource_path):
            for data in included_data:
                relationships = self.get_relationships_data(
                    data, included_serializer)
                for rel_name, relationship in six.iteritems(relationships):
                    self.add_included(rel_name, relationship, resource_path)

    def get_included_serializer(self, serializer, rel_name):
        return getattr(serializer.Meta, "include", {}).get(rel_name)

    def get_included_data(self, rel_name, pk, included_serializer):
        model = included_serializer.Meta.model
        obj = model.objects.get(pk=pk)
        return included_serializer.to_representation(obj)

    def attributes_for_serialized_data(self, serialized_data, serializer):
        if isinstance(serialized_data, list):
            result = []
            for obj in serialized_data:
                result.append(self.resource_object_for(obj, serializer))
        else:
            result = self.resource_object_for(serialized_data, serializer)
        return result

    def resource_object_for(self, obj, serializer):
        attributes = self.get_attributes_data(obj, serializer)
        result = OrderedDict([
            ("id", force_text(attributes.pop("id"))),
            ("type", attributes.pop("type")),
        ])
        if attributes:
            result["attributes"] = attributes
        return result

    def add_resource_relationships(self, attrs, serialized_data, serializer,
                                   add_included=True):
        relationships = self.get_relationships_data(serialized_data,
                                                    serializer)
        if relationships and "relationships" not in attrs:
            attrs["relationships"] = OrderedDict()
        for rel_name, relationship in six.iteritems(relationships):
            if isinstance(relationship.get("data"), list):
                self.add_relationships(attrs, rel_name, relationship)
            else:
                self.add_relationship(attrs, rel_name, relationship)
            if add_included:
                self.add_included(rel_name, relationship)

    def include_assoc(self, assoc):
        return self.check_assoc("{}$".format(assoc))

    def include_nested_assoc(self, assoc):
        return self.check_assoc("{}.".format(assoc))

    def check_assoc(self, assoc):
        include_opt = self.renderer.request.query_params.get("include")
        if not include_opt:
            return False
        include_opt = include_opt.split(",")
        for opt in include_opt:
            if re.match(r"^{}".format(
                    dasherize(assoc.replace(".", "\."))), opt):
                return True
        return False

    def get_attributes_data(self, obj, serializer):
        model = serializer.Meta.model
        resource_type = get_resource_type(model)
        attributes = OrderedDict([("id", None), ("type", resource_type)])

        for field_name, field in six.iteritems(serializer.get_fields()):
            if isinstance(field, (RelatedField, ManyRelatedField)):
                continue
            attributes[dasherize(field_name)] = obj.get(field_name)
        return attributes

    def get_relationships_data(self, serialized_data, serializer):
        relationships = OrderedDict()
        for field_name, field in serializer.get_fields().items():
            if isinstance(field, (RelatedField, ManyRelatedField)):
                relationships[field_name] = {
                    "field": field,
                    "parent_serializer": serializer,
                    "data": serialized_data.get(field_name)
                }
                related_field = get_serializer(field)
                relationships[field_name]["type"] = get_resource_type(
                    get_model(related_field, field_name, serializer))
        return relationships
def get_field_info(model):
    """
    Given a model class, returns a `FieldInfo` instance containing metadata
    about the various field types on the model.
    """
    opts = model._meta.concrete_model._meta

    # Deal with the primary key.
    pk = opts.pk
    while pk.rel and pk.rel.parent_link:
        # If model is a child via multitable inheritance, use parent's pk.
        pk = pk.rel.to._meta.pk

    # Deal with regular fields.
    fields = OrderedDict()
    for field in [field for field in opts.fields if field.serialize and not field.rel]:
        fields[field.name] = field

    # Deal with forward relationships.
    forward_relations = OrderedDict()
    for field in [field for field in opts.fields if field.serialize and field.rel]:
        forward_relations[field.name] = RelationInfo(
            model_field=field,
            related=_resolve_model(field.rel.to),
            to_many=False,
            has_through_model=False
        )

    # Deal with forward many-to-many relationships.
    for field in [field for field in opts.many_to_many if field.serialize]:
        forward_relations[field.name] = RelationInfo(
            model_field=field,
            related=_resolve_model(field.rel.to),
            to_many=True,
            has_through_model=(
                not field.rel.through._meta.auto_created
            )
        )

    # Deal with reverse relationships.
    reverse_relations = OrderedDict()
    for relation in opts.get_all_related_objects():
        accessor_name = relation.get_accessor_name()
        reverse_relations[accessor_name] = RelationInfo(
            model_field=None,
            related=relation.model,
            to_many=relation.field.rel.multiple,
            has_through_model=False
        )

    # Deal with reverse many-to-many relationships.
    for relation in opts.get_all_related_many_to_many_objects():
        accessor_name = relation.get_accessor_name()
        reverse_relations[accessor_name] = RelationInfo(
            model_field=None,
            related=relation.model,
            to_many=True,
            has_through_model=(
                (getattr(relation.field.rel, 'through', None) is not None)
                and not relation.field.rel.through._meta.auto_created
            )
        )

    # Shortcut that merges both regular fields and the pk,
    # for simplifying regular field lookup.
    fields_and_pk = OrderedDict()
    fields_and_pk['pk'] = pk
    fields_and_pk[pk.name] = pk
    fields_and_pk.update(fields)

    # Shortcut that merges both forward and reverse relationships

    relations = OrderedDict(
        list(forward_relations.items()) +
        list(reverse_relations.items())
    )

    return FieldInfo(pk, fields, forward_relations, reverse_relations, fields_and_pk, relations)