在Django Rest框架选项请求中显示过滤器和排序

时间:2021-09-09 02:49:40

I'm using the Django Rest Framework I noticed on the web browseable part of the API there is a button called 'options' when clicked it shows the following...

我正在使用Django Rest Framework我注意到在Web上可浏览的API部分有一个名为'options'的按钮,当点击它时会显示以下内容...

HTTP 200 OK Vary: Accept Content-Type: text/html Allow: HEAD, GET, OPTIONS
{
    "parses": [
        "application/json", 
        "application/x-www-form-urlencoded", 
        "multipart/form-data"
    ], 
    "renders": [
        "application/json", 
        "text/html"
    ], 
    "name": "Products", 
    "description": "API endpoint."
} 

my question is, is there anyway I could list out here all the filter options an other stuff for this url?

我的问题是,无论如何我可以在这里列出所有过滤器选项以及此URL的其他内容吗?

2 个解决方案

#1


6  

You can make OPTIONS return whatever you want, by overriding the .metadata() method on the view.

您可以通过覆盖视图上的.metadata()方法使OPTIONS返回您想要的任何内容。

See here: https://github.com/tomchristie/django-rest-framework/blob/master/rest_framework/views.py#L340

请看:https://github.com/tomchristie/django-rest-framework/blob/master/rest_framework/views.py#L340


Update as of 2015: We now have a customizable metadata API that makes this easier: http://www.django-rest-framework.org/api-guide/metadata/

自2015年起更新:我们现在拥有一个可自定义的元数据API,使这更容易:http://www.django-rest-framework.org/api-guide/metadata/

#2


0  

You can totally do this. Here's a custom metadata class that I've been keeping up to date here on *. This simply lists all the available filters, their types, and their choices. It also lists the ordering fields that are available on a class:

你完全可以做到这一点。这是我在*上一直关注的自定义元数据类。这只列出了所有可用的过滤器,它们的类型和选择。它还列出了类中可用的排序字段:

class SimpleMetadataWithFilters(SimpleMetadata):

    def determine_metadata(self, request, view):
        metadata = super(SimpleMetadataWithFilters, self).determine_metadata(request, view)
        filters = OrderedDict()
        if not hasattr(view, 'filter_class'):
            # This is the API Root, which is not filtered.
            return metadata

        for filter_name, filter_type in view.filter_class.base_filters.items():
            filter_parts = filter_name.split('__')
            filter_name = filter_parts[0]
            attrs = OrderedDict()

            # Type
            attrs['type'] = filter_type.__class__.__name__

            # Lookup fields
            if len(filter_parts) > 1:
                # Has a lookup type (__gt, __lt, etc.)
                lookup_type = filter_parts[1]
                if filters.get(filter_name) is not None:
                    # We've done a filter with this name previously, just
                    # append the value.
                    attrs['lookup_types'] = filters[filter_name]['lookup_types']
                    attrs['lookup_types'].append(lookup_type)
                else:
                    attrs['lookup_types'] = [lookup_type]
            else:
                # Exact match or RelatedFilter
                if isinstance(filter_type, RelatedFilter):
                    model_name = (filter_type.filterset.Meta.model.
                                  _meta.verbose_name_plural.title())
                    attrs['lookup_types'] = "See available filters for '%s'" % \
                                            model_name
                else:
                    attrs['lookup_types'] = ['exact']

            # Do choices
            choices = filter_type.extra.get('choices', False)
            if choices:
                attrs['choices'] = [
                    {
                        'value': choice_value,
                        'display_name': force_text(choice_name, strings_only=True)
                    }
                    for choice_value, choice_name in choices
                ]

            # Wrap up.
            filters[filter_name] = attrs

        metadata['filters'] = filters

        if hasattr(view, 'ordering_fields'):
            metadata['ordering'] = view.ordering_fields
        return metadata

Put that somewhere in your project, then set your DEFAULT_METADATA_CLASS, and you should be all set, with a new key on your OPTIONS requests like so:

把它放在项目的某个地方,然后设置你的DEFAULT_METADATA_CLASS,你应该全部设置,在OPTIONS请求上有一个新键,如下所示:

"filters": {
    "sub_opinions": {
        "type": "RelatedFilter"
    },
    "source": {
        "type": "MultipleChoiceFilter",
        "choices": [
            {
                "display_name": "court website",
                "value": "C"
            },
        ]
    }
    ...more...
}

This will also display choices, mirroring the way it's handled elsewhere in DRF.

这也将显示选择,反映在DRF中其他地方处理的方式。

#1


6  

You can make OPTIONS return whatever you want, by overriding the .metadata() method on the view.

您可以通过覆盖视图上的.metadata()方法使OPTIONS返回您想要的任何内容。

See here: https://github.com/tomchristie/django-rest-framework/blob/master/rest_framework/views.py#L340

请看:https://github.com/tomchristie/django-rest-framework/blob/master/rest_framework/views.py#L340


Update as of 2015: We now have a customizable metadata API that makes this easier: http://www.django-rest-framework.org/api-guide/metadata/

自2015年起更新:我们现在拥有一个可自定义的元数据API,使这更容易:http://www.django-rest-framework.org/api-guide/metadata/

#2


0  

You can totally do this. Here's a custom metadata class that I've been keeping up to date here on *. This simply lists all the available filters, their types, and their choices. It also lists the ordering fields that are available on a class:

你完全可以做到这一点。这是我在*上一直关注的自定义元数据类。这只列出了所有可用的过滤器,它们的类型和选择。它还列出了类中可用的排序字段:

class SimpleMetadataWithFilters(SimpleMetadata):

    def determine_metadata(self, request, view):
        metadata = super(SimpleMetadataWithFilters, self).determine_metadata(request, view)
        filters = OrderedDict()
        if not hasattr(view, 'filter_class'):
            # This is the API Root, which is not filtered.
            return metadata

        for filter_name, filter_type in view.filter_class.base_filters.items():
            filter_parts = filter_name.split('__')
            filter_name = filter_parts[0]
            attrs = OrderedDict()

            # Type
            attrs['type'] = filter_type.__class__.__name__

            # Lookup fields
            if len(filter_parts) > 1:
                # Has a lookup type (__gt, __lt, etc.)
                lookup_type = filter_parts[1]
                if filters.get(filter_name) is not None:
                    # We've done a filter with this name previously, just
                    # append the value.
                    attrs['lookup_types'] = filters[filter_name]['lookup_types']
                    attrs['lookup_types'].append(lookup_type)
                else:
                    attrs['lookup_types'] = [lookup_type]
            else:
                # Exact match or RelatedFilter
                if isinstance(filter_type, RelatedFilter):
                    model_name = (filter_type.filterset.Meta.model.
                                  _meta.verbose_name_plural.title())
                    attrs['lookup_types'] = "See available filters for '%s'" % \
                                            model_name
                else:
                    attrs['lookup_types'] = ['exact']

            # Do choices
            choices = filter_type.extra.get('choices', False)
            if choices:
                attrs['choices'] = [
                    {
                        'value': choice_value,
                        'display_name': force_text(choice_name, strings_only=True)
                    }
                    for choice_value, choice_name in choices
                ]

            # Wrap up.
            filters[filter_name] = attrs

        metadata['filters'] = filters

        if hasattr(view, 'ordering_fields'):
            metadata['ordering'] = view.ordering_fields
        return metadata

Put that somewhere in your project, then set your DEFAULT_METADATA_CLASS, and you should be all set, with a new key on your OPTIONS requests like so:

把它放在项目的某个地方,然后设置你的DEFAULT_METADATA_CLASS,你应该全部设置,在OPTIONS请求上有一个新键,如下所示:

"filters": {
    "sub_opinions": {
        "type": "RelatedFilter"
    },
    "source": {
        "type": "MultipleChoiceFilter",
        "choices": [
            {
                "display_name": "court website",
                "value": "C"
            },
        ]
    }
    ...more...
}

This will also display choices, mirroring the way it's handled elsewhere in DRF.

这也将显示选择,反映在DRF中其他地方处理的方式。