Skip to main content

Django-Filter extension to support filtering by Properties

Project description

Django Property Filter

Django-property-filter is an extension to django-filter and provides functionality to filter querysets by class properties.

It does so by providing sub-classes for Filters and Filtersets to keep existing django-filter functionality.

License Version
Github Action Coverage
Wheel Implementation
Status Downloads
Supported versions

For more details and examples check the documentation.

Requirements

  • Python: 3.8, 3.9, 3.10, 3.11, 3.12, 3.13
  • Django: 4.2, 5.0, 5.1
  • Django-filter: 23.5+

Limitations

Performance

Because this app preserved Django Filtersets and filters them agains fields that are not Database fields all filtering happens in memory. Compared with direct sql optimized queries that might be slower and more memory intensive.

Limit on returned results

In theory there is no limit for most databases how many results can be returned from a filter query unless the database implements a limit which will impact how many results django-property-filter can return. Sqlite3 defines different limits depending on the version used. For further details see the documentation for limitations

Installation

Install using pip:

pip install django-property-filter

Then add 'django_property_filter' to your INSTALLED_APPS.

INSTALLED_APPS = [
    ...
    'django_property_filter',
]

Usage

Example Model

Our Model

from django.db import models

class BookSeries(models.Model):
    name = models.CharField(max_length=255)

    @property
    def book_count(self):
      return Book.objects.filter(series=self).count()

class Book(models.Model):
    title = models.CharField(max_length=255)
    price = models.DecimalField()
    discount_percentage = models.IntegerField()
    author = models.TextField()
    series = models.ForeignKey(BookSeries)

    @property
    def discounted_price(self):
      return self.price * self.discount_percentage \ 100

Implicit Filter Creation

If we want to filter by discounted price as well as number of books in a series, which both are properties and not fields in the database, we would do the following.::

from django_property_filter import PropertyFilterSet, PropertyNumberFilter

class BookFilterSet(PropertyFilterSet):

  class Meta:
      model = Book
      exclude = ['price']
      property_fields = [
        ('discounted_price', PropertyNumberFilter, ['lt', 'exact']),
        ('series.book_count.', PropertyNumberFilter, ['gt', 'exact']),
      ]

This will create 4 Filters

1.) A "less than" and an "exact" filter for the "discounted_price" property
    of the Book Model
2.) A "greater than" and an "exact" filter for the "book_count" property
    of the related Model "series".

The order in which the property filters are applied are in the same order as they are defined. In the above filter will be in order of

1.) discounted_price: lt
2.) discounted_price: exact
3.) series.book_count: gt
4.) series.book_count: exact

This can be usefull to speed up the filtering by property filters if filters are defined first that are likely to filter a large number of values. E.g. a boolean field might be filtering an average of half the values, while a field representing a name will likely filter fewer.

Since PropertyFilterSet is and extension to django-filter's Filterset which requires either the Meta attribute "fields" or "exclude" to be set we excluded the "price" field. If we had instead used:: fields = ['price']

It would also have created an "exact" filter for the book price.

The only difference to using a normal FilterSet from django-filter is the "property_fields" field.

The "property_fields" is a list of tuples with 3 values.

1.) The property name. 
    If the property is on a related Model it should be separated by "__",
    and can span multiple levels e.g. fk__fk__fk__property
2.) The specific Property Filter to use.
    This is necessary since it can't be determined what the return type
    of the property will be in all cases
3.) The list of lookup expressions.

Explicit Filter Creation

It is also possible to create Filters explicitely.

from django_property_filter import PropertyNumberFilter, PropertyFilterSet

class BookFilterSet(PropertyFilterSet):
    prop_number_gte = PropertyNumberFilter(field_name='discounted_price', lookup_expr='gte')
    prop_number_lt = PropertyNumberFilter(field_name='discounted_price', lookup_expr='lt')

    class Meta:
        model = NumberClass
        fields = ['prop_number_gte', 'prop_number_lt']

This creates a "greater than or equel" and a "less than" filter for the discounted_price property.

The order in which the property filters are applied are in the same order as they are defined. In the above filter will be in order of

1.) prop_number_gte
2.) prop_number_lt

This can be usefull to speed up the filtering by property filters if filters are defined first that are likely to filter a large number of values. E.g. a boolean field might be filtering an average of half the values, while a field representing a name will likely filter fewer.

Development

Run the Django Test Project to see the filters in action

  • go to "tests\django_test_proj"
  • run "python manage.py makemigrations"
  • run "python manage.py migrate"
  • run "python manage.py setup_data"
  • run "python manage.py runserver"

Issue Raising

Raising bugs, feature requests and questions is possible via the public repository django-property-filter-issue-reporting

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

django_property_filter-1.3.0.tar.gz (15.7 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

django_property_filter-1.3.0-py3-none-any.whl (14.7 kB view details)

Uploaded Python 3

File details

Details for the file django_property_filter-1.3.0.tar.gz.

File metadata

  • Download URL: django_property_filter-1.3.0.tar.gz
  • Upload date:
  • Size: 15.7 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.12.8

File hashes

Hashes for django_property_filter-1.3.0.tar.gz
Algorithm Hash digest
SHA256 769b05e219b44b8950ead2112746d780f8d64ebd5fab53520993f433a2f811f9
MD5 1d3c28aa30f3541b25ef004b9cfc1fa4
BLAKE2b-256 b983606918f6d03c927b4cccbbd56208dc29bc714f94563b529a9868e432ce72

See more details on using hashes here.

File details

Details for the file django_property_filter-1.3.0-py3-none-any.whl.

File metadata

File hashes

Hashes for django_property_filter-1.3.0-py3-none-any.whl
Algorithm Hash digest
SHA256 156dc32200e5b054b13cca9261db5ca92de6d92f7a01691621ef6aaadc6ef874
MD5 6f0259fae84310a00ee6a9c7f1ac4665
BLAKE2b-256 8523c12d83a4171f123c9b4f374d0b5e76ec1b3ae696f5750ce5f14538d503a3

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page