2
0
mirror of https://github.com/inventree/InvenTree.git synced 2025-04-28 11:36:44 +00:00

Add new report filters for accessing database tables (#8560)

* Add new report filters for accessing database tables

* Simplify

* Handle exception

* Add docs

* Update docstrings
This commit is contained in:
Oliver 2024-11-27 07:51:27 +11:00 committed by GitHub
parent 368f3b7bd4
commit 20fb1250f8
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 118 additions and 0 deletions

View File

@ -78,6 +78,78 @@ To return an element corresponding to a certain key in a container which support
{% endraw %} {% endraw %}
``` ```
## Database Helpers
A number of helper functions are available for accessing database objects:
### filter_queryset
The `filter_queryset` function allows for arbitrary filtering of the provided querysert. It takes a queryset and a list of filter arguments, and returns a filtered queryset.
::: report.templatetags.report.filter_queryset
options:
show_docstring_description: false
show_source: False
!!! info "Provided QuerySet"
The provided queryset must be a valid Django queryset object, which is already available in the template context.
!!! warning "Advanced Users"
The `filter_queryset` function is a powerful tool, but it is also easy to misuse. It assumes that the user has a good understanding of Django querysets and the underlying database structure.
#### Example
In a report template which has a `PurchaseOrder` object available in its context, fetch any line items which have a received quantity greater than zero:
```html
{% raw %}
{% load report %}
{% filter_queryset order.lines.all received__gt=0 as received_lines %}
<ul>
{% for line in received_lines %}
<li>{{ line.part.part.full_name }} - {{ line.received }} / {{ line.quantity }}</li>
{% endfor %}
</ul>
{% endraw %}
```
### filter_db_model
The `filter_db_model` function allows for filtering of a database model based on a set of filter arguments. It takes a model class and a list of filter arguments, and returns a filtered queryset.
::: report.templatetags.report.filter_db_model
options:
show_docstring_description: false
show_source: False
#### Example
Generate a list of all active customers:
```html
{% raw %}
{% load report %}
{% filter_db_model company.company is_customer=True active=True as active_customers %}
<ul>
{% for customer in active_customers %}
<li>{{ customer.name }}</li>
{% endfor %}
</ul>
{% endraw %}
```
### Advanced Database Queries
More advanced database filtering should be achieved using a [report plugin](../extend/plugins/report.md), and adding custom context data to the report template.
## Number Formatting ## Number Formatting
### format_number ### format_number

View File

@ -8,8 +8,10 @@ from decimal import Decimal
from typing import Any, Optional from typing import Any, Optional
from django import template from django import template
from django.apps.registry import apps
from django.conf import settings from django.conf import settings
from django.core.exceptions import ValidationError from django.core.exceptions import ValidationError
from django.db.models.query import QuerySet
from django.utils.safestring import SafeString, mark_safe from django.utils.safestring import SafeString, mark_safe
from django.utils.translation import gettext_lazy as _ from django.utils.translation import gettext_lazy as _
@ -29,6 +31,50 @@ register = template.Library()
logger = logging.getLogger('inventree') logger = logging.getLogger('inventree')
@register.simple_tag()
def filter_queryset(queryset: QuerySet, **kwargs) -> QuerySet:
"""Filter a database queryset based on the provided keyword arguments.
Arguments:
queryset: The queryset to filter
Keyword Arguments:
field (any): Filter the queryset based on the provided field
Example:
{% filter_queryset companies is_supplier=True as suppliers %}
"""
return queryset.filter(**kwargs)
@register.simple_tag()
def filter_db_model(model_name: str, **kwargs) -> QuerySet:
"""Filter a database model based on the provided keyword arguments.
Arguments:
model_name: The name of the Django model - including app name (e.g. 'part.partcategory')
Keyword Arguments:
field (any): Filter the queryset based on the provided field
Example:
{% filter_db_model 'part.partcategory' is_template=True as template_parts %}
"""
app_name, model_name = model_name.split('.')
try:
model = apps.get_model(app_name, model_name)
except Exception:
return None
if model is None:
return None
queryset = model.objects.all()
return filter_queryset(queryset, **kwargs)
@register.simple_tag() @register.simple_tag()
def getindex(container: list, index: int) -> Any: def getindex(container: list, index: int) -> Any:
"""Return the value contained at the specified index of the list. """Return the value contained at the specified index of the list.