Skip to content

Field

The base filter field. Every concrete field type extends Field and inherits the same set of common parameters. See the Fields guide for an overview and worked examples.

Field

Field(
    *,
    db_field="",
    filter_by: str
    | Callable[[Any], Any]
    | dict
    | None = None,
    lookups: LookupsType = None,
    lookup_separator: str | None = None,
    method: Callable[
        [Any, QuerySet, Any],
        tuple[Q, QuerySet] | Q | QuerySet,
    ]
    | str
    | None = None,
    negate: bool = False,
    required: bool = False,
    allow_negate: bool = True,
    **kwargs,
)

Bases: Field

Base filter field that extends rest_framework's Field with filtering capabilities.

Field inherits all validation logic from Django Rest Framework's Field class and adds support for filtering Django querysets. Each field can generate additional lookup and negation variants automatically.

Automatic Field Generation
  • Negation field: Every field creates a negation variant (e.g., "price!" for not equal) unless allow_negate=False
  • Lookup fields: Fields generate additional variants based on the lookups parameter (e.g., "price__gte", "price__lte" from lookups=["gte", "lte"])

Parameters:

Name Type Description Default
filter_by str | Callable[[Any], Any] | dict | None

Defines how to filter the queryset. Can be: - String: Django ORM lookup expression (e.g., "name__icontains", "price__gte") - Callable: Function that receives (value) and returns either a dict for Q() or a Q object directly. Cannot be used with method parameter.

None
lookups LookupsType

Additional lookup expressions to generate as separate fields. Can be: - List of lookups: ["gte", "lte", "in"] creates price__gte, price__lte, price__in - Category name: "basic" expands to ["exact", "in", "isnull"] - ALL_FIELDS: Uses all lookups from the field's lookup_categories - Alias dict mapping variant suffix -> ORM lookup, example: {"max": "lte", "min": "gte"}. Used together with lookup_separator to control how variants are named on the query string. Keys are NOT expanded via lookup categories.

None
lookup_separator str | None

Separator placed between the field name and a lookup variant suffix when building variant names. When None (the default), the FilterSet's Meta.lookup_separator is used, if Meta does not set one either, falls back to "__" to match Django's lookup syntax (e.g. price__gte).

None
method Callable[[Any, QuerySet, Any], tuple[Q, QuerySet] | Q | QuerySet] | str | None

Custom filtering method. Can be: - Callable: Function with signature (filterset, queryset, value) -> QuerySet or Q - String: Name of a method on the FilterSet class. The resolved method is called with (queryset, value), the filterset instance is reachable via self for instance methods. Either form may be async def when the FilterSet is driven via afilter_queryset, calling sync filter_queryset with an async method raises TypeError. Cannot be used with filter_by parameter.

None
allow_negate bool

If False, prevents automatic creation of the negation field. Default is True.

True
negate bool

If True, inverts the filter to exclude matching results. Default is False.

False
required bool

If True, validation fails when the field is not provided. Default is False.

False

Examples:

Basic field with simple lookup::

name = StringField(filter_by="name__icontains")

Field with multiple lookups::

price = IntegerField(lookups=["gte", "lte", "exact"])
# Creates: price, price__gte, price__lte, price__exact, price!

Field with custom method as a callable::

def filter_by_date_range(filterset, queryset, value):
    # Some extra business logic
    return queryset.filter(created_at__range=value)

date_range = Field(method=filter_by_date_range)

Field with custom method as a string referring to a FilterSet method::

class ProductFilterSet(FilterSet):
    date_range = Field(method="filter_by_date_range")

    def filter_by_date_range(self, queryset, value):
        return queryset.filter(created_at__range=value)

Field with callable filter_by::

def custom_lookup(value):
    return Q(name__icontains=value) | Q(description__icontains=value)

search = StringField(filter_by=custom_lookup)
See Also
  • IntegerField, StringField, DateTimeField: Specialized field types
  • ListField: For filtering with multiple values
  • OrderField: Special field for queryset ordering

apply_filter

apply_filter(
    filterset: FilterSet, queryset: QuerySet, value: Any
) -> tuple[QuerySet, Optional[Q]]

Apply the field's filter to a queryset based on the validated value.

The original idea is to always send a Q object to support operators, but if a user defines a method for this field, it can either return a Q object or a modified queryset.

If method is an async def callable, this returns a coroutine that yields the (queryset, q) tuple instead. Sync callers should detect the coroutine and raise, async callers should await.

Parameters:

Name Type Description Default
filterset FilterSet

The FilterSet instance that contains this field.

required
queryset QuerySet

The Django queryset to filter.

required
value Any

The validated value from query parameters (already cleaned by DRF validation).

required

Returns:

Type Description
tuple[QuerySet, Optional[Q]]

Tuple of (queryset, q_object). queryset is the modified queryset or the original when Q objects are used. q_object is the Q to combine with other filters, or None when the queryset was modified directly. Returns a coroutine yielding that tuple when method= is async.

clone

clone(_type=None, field_name=None, **inner_kwargs)

Return a copy of this field, optionally re-typed via annotation.

get_method

get_method(filterset=None)

Return the resolved filter method, looking up string method names on the filterset.