# -*- coding: utf-8 -*-
from __future__ import absolute_import, print_function, unicode_literals
import coreapi
import coreschema
from django import forms
from django.db.models.constants import LOOKUP_SEP
from ..fields import MultipleValuesField
from ..filtersets import FilterSet
from .drf import URLFilterBackend
DESCRIPTION = {
'contains': 'Match when string contains given substring',
'day': 'Match by day of the month',
'endswith': 'Match when string ends with given substring',
'exact': 'Match exactly the value as is',
'gt': 'Match when value is greater then given value',
'gte': 'Match when value is greater or equal then given value',
'hour': 'Match by the hour (24 hour) value of the timestamp',
'icontains': 'Case insensitive match when string contains given substring',
'iendswith': 'Case insensitive match when string ends with given substring',
'iexact': 'Case insensitive match exactly the value as is',
'iin': 'Case insensitive match when value is any of given comma separated values',
'in': 'Match when value is any of given comma separated values',
'iregex': 'Case insensitive match when value is within comma separated range',
'isnull': 'Match when value is NULL',
'istartswith': 'Case insensitive match when string starts with given substring',
'lt': 'Match when value is less then given value',
'lte': 'Match when value is less or equal then given value',
'minute': 'Match by the minute value of the timestamp',
'month': 'Match by the month value of the timestamp',
'range': 'Match when value is within comma separated range',
'regex': 'Match string by regex pattern',
'second': 'Match by the second value of the timestamp',
'startswith': 'Match when string starts with given substring',
'week_day': 'Match by week day (1-Sunday to 7-Saturday) of the timestamp',
'year': 'Match by the year value of the timestamp',
}
FORM_FIELD_TO_SCHEMA = {
MultipleValuesField: coreschema.Array,
forms.BooleanField: coreschema.Boolean,
forms.IntegerField: coreschema.Integer,
forms.FloatField: coreschema.Number,
}
def _field_to_schema(field, lookup):
form_field = field.get_form_field(lookup)
return FORM_FIELD_TO_SCHEMA.get(type(form_field), coreschema.String)(description=DESCRIPTION.get(lookup))
def _all_filters(filterset, prefix=()):
for name, field in filterset.filters.items():
if isinstance(field, FilterSet):
for i in _all_filters(field, prefix=prefix + (name,)):
yield i
else:
yield coreapi.Field(
name=LOOKUP_SEP.join(prefix + (name,)),
required=False,
location="query",
schema=_field_to_schema(field, field.default_lookup),
)
if field.no_lookup:
continue
for lookup in field.lookups:
yield coreapi.Field(
name=LOOKUP_SEP.join(prefix + (name, lookup)),
required=False,
location="query",
schema=_field_to_schema(field, lookup),
)
[docs]class CoreAPIURLFilterBackend(URLFilterBackend):
"""
Same as :py:class:`url_filter.integrations.drf.DjangoFilterBackend` except
this backend also implements coreapi interface for autogenerated API docs.
"""
[docs] def get_schema_fields(self, view):
"""
Get coreapi filter definitions
Returns all filters including their supported lookups.
"""
queryset = view.get_queryset()
filter_class = self.get_filter_class(view, queryset)
return (
[]
if not filter_class
else list(_all_filters(filter_class(data={}, queryset=queryset)))
)