Available on crate feature filter only.
Expand description

Create filters for Rust objects from query URLs

Django encodes database queries into URL query strings in a way that can be frustrating to replicate ad-hoc. The simplest query parts are things like foo=3 which means the column foo must have the exact value 3. More precisely, it means: “apply the default operator for column foo, to the contents of that column for each row, with a right hand side of 3, and only include the row if the result is true. The default operator is usually exact.

There are three ways Django extends this simple model. Firstly, it’s possible to specify a different operator than the default for some columns. Standard Django operators include contains, gt, lt, in, iexact and isnull. These are written in the query string as, for example, foo__lt=3, which filters on foo < 3.

Secondly, columns can be multivalued. If in the preceding example column foo an array of integers, then foo=3 would mean that the array must contain 3. In general, for collection valued columns, a filter is considered to pass if any individual element passes.

Thirdly, there can be relations between tables. For example, if the column foo was actually of some complex type, drawn from a different table, then it’s possible to filter within foo. Suppose the table for the type of member foo has a column bar, then our query string could be foo__bar=3 to mean “select all objects whose member foo has a member bar whose value is 3”.

All of the preceding features combine, so it’s possible to end up with query strings like foo__bar__baz__lt=5 with the meaning (due to the structure with collections): “include objects within whose collection for member foo, one item has a member bar, and within that object’s member bar one item has a member baz, and within the collection of integers for that object’s member baz one integer is less than 5”.

Overview

The main trait in this module is Filterable which has an associated derive macro Filterable. Deriving Filterable means the type can describe the filtering it supports, and the derive macro allows you to set up the filters inline in the type definition. An OperatorSet can be constructed for any Filterable type, which can convert a URL fragment from a django-style query string into a boxed Filter object.

Example:

use django_query::filtering::{Filterable, OperatorSet};

#[derive(Filterable)]
struct Bar {
  #[django(op(lt))]
  a: i32,
}

#[derive(Filterable)]
struct Foo {
  #[django(op(lt))]
  a: i32,
  #[django(traverse)]
  b: Bar,
}

let foo = Foo { a: 5, b: Bar { a: 0 } };
let qr = OperatorSet::<Foo>::new();
let filter = qr.create_filter_from_query("b__a__lt=1").unwrap();
assert!(filter.filter_one(&foo));
let filter = qr.create_filter_from_query("b__a__lt=0").unwrap();
assert!(!filter.filter_one(&foo));

Because Filter objects produced by parsing are boxed, there is virtual function call overhead when using them. This can be minimised by using the provided filter_vec method to filter an entire Vec at a time, instead of testing values individually with filter_one.

Note that self-including types - types that have members of their own type at any level of indirection - cannot be handled by this crate because of its commitment to monomorphism within filters. It must always be possible to write out all the valid left hand sides that could occur in a filter, and this will in fact be done automatically when an OperatorSet is constructed.

Modules

Standard operators from Django for use with filtering.

Structs

A collection of filters for a particular type.

A collection of filters for a type that requires a context object.

Enums

Errors produced by filtering.

Traits

A wrapper for a field of any type.

Test whether an objects to see whether it is included in a given result set.

An object that can make a Filter.

Something which can produce a description of how to filter it.

Something that can describe how to filter itself if a context type is provided.

A wrapper for a field of Operable type.

Receive descriptions of the filters a Member supports.

A wrapper for a type that can be filtered.

Receive descriptions of the Members a type contains from its Meta.

A type that Django filters can work on.

Take a single value and produce a true/false result.

Something that can make an operator instance from a right-hand side.

Functions

Debug print of a Filterable type showing the supported queries.

Derive Macros

Derive the Filterable trait, creating suitable FilterClass types.

Derive the FilterableWithContext trait for persian-rug types.