drf/django滤波器以编程方式调用过滤器类,而无需使用视图集/请求

发布于 2025-02-01 04:31:11 字数 1449 浏览 2 评论 0原文

我正在构建功能,以允许用户从Angular Frontend上的查询构建器组件中节省一组过滤器。我还使用Django-Filter软件包来为我的应用程序中的大多数搜索能力提供动力。

说我有一个名为mymodel(带有fk字段'类别'的模型)和一个视图集,其中我指定了filterset_class = mymodefilter,

from django_filters import rest_framework as filters

class MyModelFilter(filters.Filterset):

    category_in = filters.BaseCSVFilter(field_name='category', method='filter_category_in')
    
    def filter_category_in(self, qs, name, value):
        # filters happen
        return qs

当我的前端访问https:// api-url/mymodel/?category_in = 1,2 ,3

我现在要做的是从Django应用程序内部编程调用此过滤器。

用例:我需要对CRON作业进行编程,以构建和通过基于可以匹配?category_in = 1,2,3 param Filter。使用DRF请求时,对于视图集来说,这是非常简单的,但是我不知道在哪里可以看他在哪里使用此过滤器而无需进行请求路由。

该过滤器被保存在称为Savedquery的型号中的JSONFIELD(SAVED_QUERY_STATEMENT)中。它看起来像这样:

sqs = {
    'name': 'category',
    'lookup_expr': 'in',
    'value': '1,2,3'
}

因此,cron作业函数(执行执行)将执行savedquery.objects.get()调用并获取与之相关的查询,然后需要获取myModel querySet where(category__in = [[ 1,2,3])) 我如何在不做类似这样的事情的情况下使用该过滤器的JSON/String表示(我有50多件可能的过滤器,还有更多的过滤器

qs = MyModel.objects.all()
if 'category' in sqs.get('name'):
    if 'in' in sqs.get('lookup_expr'):
        ids = [int(v) for v in sqs.get('value').split(',')]
        qs.filter(category__in=ids)

...

...通过视图集...有什么想法吗?

I am building functionality to allow users to save a set of filters from a query-builder component on my Angular frontend. I am also using the django-filter package to power most of the search ability in my app.

Say I have a model named MyModel (with a FK field 'category') and a ViewsSet wherein I've specified filterset_class = MyModeFilter

from django_filters import rest_framework as filters

class MyModelFilter(filters.Filterset):

    category_in = filters.BaseCSVFilter(field_name='category', method='filter_category_in')
    
    def filter_category_in(self, qs, name, value):
        # filters happen
        return qs

This works well when my frontend calls https://api-url/mymodel/?category_in=1,2,3

What I want to do now is programmatically call this filter from inside the django app.

Use case: I need to program a CRON job to build and email an excel report based on a queryset that would match the ?category_in=1,2,3 param filter. This is very straightforward with the ViewSets when using DRF requests, but I don't know where to start looking at his to use this filter without going the requests route.

The the filter is saved in a JSONField (saved_query_statement) in a model called SavedQuery. It will look something like this:

sqs = {
    'name': 'category',
    'lookup_expr': 'in',
    'value': '1,2,3'
}

So the CRON job function, when executed, will do a SavedQuery.objects.get() call and get the query which is relevant to it, then it needs to get the MyModel queryset where (category__in=[1,2,3])
How can I take the JSON/string representation of this filter without doing a lot of something like this (I have over 50 possible filters with more to come...)

qs = MyModel.objects.all()
if 'category' in sqs.get('name'):
    if 'in' in sqs.get('lookup_expr'):
        ids = [int(v) for v in sqs.get('value').split(',')]
        qs.filter(category__in=ids)

...

TLDR, I'd like to use the django-filter Filterset class without going through the Viewset... any ideas?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

洋洋洒洒 2025-02-08 04:31:11

您可以使用**拆卸过滤器键/值args并使其有些通用:

qs.filter(**kv)

在您的情况下,它会像这样:

qs = MyModel.objects.all()

# Somehow create kwargs from your JSON
filter_key = sqs.get('name')
lookup_expr = sqs.get('lookup_expr')
if lookup_expr:
    filter_key += '__{}'.format(lookup_expr)
filter_value = parse_filter_value(sqs.get('value'))  # This is a bit tricky
kwargs = {filter_key: filter_value}

# Now filter
qs.filter(**kwargs)

您必须弄清楚如何实现parse_filter_value,但这不是这里的核心问题,通常这种方法可能非常方便。

You can use ** to unpack filter key/value args and make it somewhat generic:

qs.filter(**kv)

In your case, it would go something like this:

qs = MyModel.objects.all()

# Somehow create kwargs from your JSON
filter_key = sqs.get('name')
lookup_expr = sqs.get('lookup_expr')
if lookup_expr:
    filter_key += '__{}'.format(lookup_expr)
filter_value = parse_filter_value(sqs.get('value'))  # This is a bit tricky
kwargs = {filter_key: filter_value}

# Now filter
qs.filter(**kwargs)

You'll have to figure out how to implement parse_filter_value, but that's not the core problem here, and in general this approach can be very handy.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文