1

I have a big model which stores 10 text based values, and 10 numerical values. Something like this:

class Dataset(models.Model):
    text_field_1 = models.CharField(max_length=255)
    .
    .
    .
    text_field_10 = models.CharField(max_length=255)

    number_field_1 = models.IntegerField()
    .
    .
    .
    number_field_10 = models.IntegerField()

Now, what I want to do is give users to a way to filter, and order datasets using these fields, by passing in an object to a view. Hopefully, the example below shows what I want to do:

obj = {
    "filters" : [
        "text_field_1='vaccines'",
        "number_field_5__gte=1000",
    ],
    "order_by" : "text_field_3, -number_field_7",
    "excludes" : [],
}

generate_query(obj) # Dataset.objects.filter(text_field_1='vaccines', number_field_5__gte=1000).order_by('text_field_3', '-number_field_7')

So by calling the generate_query(obj), we get the queryset in the comment. Now, due to the nature of this model, its impossible for me to do this manually, by accounting for every possible combination of filters, orders, and excludes.

What is the best, and safest way to implement this? The only thing that comes to my mind is creating a big string, and then using exec or eval to execute the string.

1

2 Answers 2

7

Use dictionaries for filters and excludes and a list for order_by, and you can use argument unpacking with * or **.

obj = {
    "filters" : {
        "text_field_1": "vaccines",
        "number_field_5__gte": "1000",
    },
    "order_by" : ["text_field_3", "-number_field_7"],
    "excludes" : {},
}

Dataset.objects.filter(**obj['filters']).exclude(**obj['excludes']).order_by(*obj['order_by'])

It should be pretty safe, as long as you don't permit user to construct their own __ arguments. For example the filter event__owner__password='hunter2' could be used to indirectly query fields in related models.

Sign up to request clarification or add additional context in comments.

1 Comment

not allowing users to construct their own _ arguments will be done with form validators right?
0

There is quite a good package dedicated to filering based on user input:

https://django-filter.readthedocs.io/en/stable/

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.