Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/ertgl/django-xformula
Django query evaluator, built on top of XFormula language front-end.
https://github.com/ertgl/django-xformula
django domain-specific-language dynamic-filtering python query
Last synced: 15 days ago
JSON representation
Django query evaluator, built on top of XFormula language front-end.
- Host: GitHub
- URL: https://github.com/ertgl/django-xformula
- Owner: ertgl
- License: mit
- Created: 2022-11-12T20:34:37.000Z (about 2 years ago)
- Default Branch: main
- Last Pushed: 2024-12-24T00:17:36.000Z (30 days ago)
- Last Synced: 2025-01-01T12:11:27.786Z (21 days ago)
- Topics: django, domain-specific-language, dynamic-filtering, python, query
- Language: Python
- Homepage:
- Size: 195 KB
- Stars: 2
- Watchers: 2
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# django-xformula
Django query evaluator, built on top of
[XFormula](https://github.com/ertgl/xformula) language front-end.## Use Cases
This library can be used to develop various types of features, such as:
* **Open APIs**: Allow users and integrated services to filter data using formulas
* **Flexible Security**: Implement query-based authorization checks, stored in the database
* **Conditional Webhooks**: Trigger webhooks based on preferred conditions, likely provided by the user
* **Personalized Experience**: Allow users to customize their interactions with the appThese are just a few examples of what you can do with `django-xformula`.
## Features
* **Bidirectional operators**
* Same syntax for both Python and Django query evaluation
* Operations containing at least one `QuerySet` will be evaluated as `QuerySet`
* Operations containing at least one `Q` will be evaluated as `Q`
* Operations containing at least one `Combinable` will be evaluated as `Combinable`
* Operations containing at least one `Field` will be evaluated as `Combinable`
* Operations containing at least one `Model` instance will be evaluated as `Value` containing the model instance's primary key
* Other operations work like Python* **Zero built-in variables by default**
* When a variable name is used but does not exist in the specified built-ins, it will be evaluated as an `F` object* **Customizable attribute getter**
* Manage which attributes can be used in formulas (Getting an attribute of an object is forbidden by default and raises a `ForbiddenAttribute` error which inherits Django's `PermissionDenied` class)* **Customizable caller**
* Manage which functions can be called in formulas (Calling a callable is forbidden by default and raises a `ForbiddenCall` error which inherits Django's `PermissionDenied` class)## Installation
To install `django-xformula`, use the following command:
```sh
pip install django-xformula
```## Usage
Here's a basic, unsafe, pseudo example of how to use `django-xformula`.
This code snippet demonstrates how to filter a Django queryset using a
formula provided by the user:```py
from operator import callfrom django.db.models import Q, QuerySet
from django.db.models.functions import Length
from django_xformula import QueryEvaluator# Import your models here
from myapp.models import MyModeldef resource_view(request):
evaluator = QueryEvaluator()
query = request.GET.get("q", "")
context = QueryEvaluator.Context(
# Pass Python objects to the formula context.
builtins={
"Length": Length,
"me": request.user,
},
# Very dangerous! Do not use in production!
# Better to write your own function caller
# based on the conditions you want to allow or disallow.
call=call,
# Very dangerous! Do not use in production!
# Better to write your own attribute getter
# based on the conditions you want to allow or disallow.
getattr=getattr,
)
q_or_result = evaluator.evaluate(q, context)
if isinstance(q_or_result, QuerySet):
return render_table(q_or_result)
if isinstance(q_or_result, Q):
queryset = MyModel.objects.filter(q_or_result)
return render_table(queryset)
# Probably, the formula was not a database query.
# The evaluator has returned the result of the formula.
# E.g.: Expressions like `1 + 1`, etc...
return render_result(q_or_result)
```This endpoint would allow users to filter `MyModel` instances using formulas
containing the `me` variable, which is the current user.For example, the following query would return all `MyModel` instances where the
`owner_id` field is equal to the current user's ID:```python
owner_id == me.id
```Another example would be to return all `MyModel` instances where the `name`
field is longer than 5 characters:```python
Length(name) > 5
```Even more complex queries can be written, such as the following example.
This query would return all `MyModel` instances where the `name` field is longer
than field `age`, only if the remote data is fetched successfully:```python
fetch_remote_data(me).status_code == 200 and Length(name) > age
```### Operators
XFormula supports a wide range of operators by default, Python operators are
included as well. See the
[default operator precedences](https://github.com/ertgl/xformula/blob/main/src/xformula/syntax/core/operations/default_operator_precedences.py#L16)
for more information.### Query Validity
Django ORM's rules still apply. Do not allow users to execute database
functions that are not supported by your database backend.## License
This project is licensed under the
[MIT License](https://opensource.org/license/mit).See the [LICENSE](LICENSE) file for more information.