Is there a way to check if a string is a valid filter for a django queryset?
<p>I'm trying to add some functionality to give a user the ability to filter a paginated queryset in Django via URL get parameters, and have got this successfully working:</p>

<pre><code>for f in self.request.GET.getlist('f'):
    try:
        k,v = f.split(':', 1)
        queryset = queryset.filter(**{k:v})
    except:
        pass
</code></pre>

<p>However, I am hoping to do so in a way that doesn't use <code>try/except</code> blocks. Is there a standard way in django to check if a string is a valid filter parameter?</p>

<p>For example something like:</p>

<pre><code>my_str = "bad_string_not_in_database"
if some_queryset.is_valid_filter_string(my_str):
   some_queryset.filter(**{my_str:100}) 
</code></pre>

<p>The short answer is no, but there are other options.</p>

<p>Django does not provide, nor make it easy to create, the kind of validation function you're asking about.  There are not just fields and forward relationships that you can filter on, but also reverse relationships, for which a <code>related_name</code> or a <code>related_query_name</code> on a field in a completely different model might be the <a href="https://docs.djangoproject.com/en/1.10/ref/models/fields/#django.db.models.ForeignKey.related_name" rel="nofollow">valid way</a> to filter your querysets.  And there are various filtering mechanisms, like <code>iexact</code>, <code>startswith</code>, <code>regex</code>, etc., that are valid as postfixes to those relationship names.  So, to validate everything correctly, you would need to replicate a lot of Django's internal parsing code and that would be a big mistake.</p>

<p>If you just want to filter by this model's fields and forward relationships, you can use <code>hasattr(SomeModel, my_str)</code>, but that won't always work correctly (your model has other attributes besides fields, such as methods and properties).</p>

<p>Instead of doing a blanket <code>except: pass</code>, you can at least catch the specific error that will be thrown when an invalid string is used in the filtering kwargs (<a href="https://docs.djangoproject.com/en/1.10/topics/db/queries/#field-lookups" rel="nofollow">it's <code>TypeError</code></a>).  You can also return a 400 error to let the client know that their request was not valid, instead of silently continuing with the un-filtered queryset.</p>

<p>My preferred solution would be to outsource this kind of boilerplate, generalizable logic to a library, such as <a href="https://github.com/AltSchool/dynamic-rest#field-based-filtering" rel="nofollow">dynamic-rest</a>.</p>

python django django-queryset django-orm