question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. ItĀ collects links to all the places you might be looking at while hunting down a tough bug.

And, if youā€™re still stuck at the end, weā€™re happy to hop on a call to see how we can help out.

How to pass and validate dynamic number of filter groups via query parameters?

See original GitHub issue

First Check

  • I added a very descriptive title to this issue.
  • I used the GitHub search to find a similar issue and didnā€™t find it.
  • I searched the FastAPI documentation, with the integrated search.
  • I already searched in Google ā€œHow to X in FastAPIā€ and didnā€™t find any information.
  • I already read and followed all the tutorial in the docs and didnā€™t find an answer.
  • I already checked if it is not related to FastAPI but to Pydantic.
  • I already checked if it is not related to FastAPI but to Swagger UI.
  • I already checked if it is not related to FastAPI but to ReDoc.

Commit to Help

  • I commit to help with one of those options šŸ‘†

Example Code

There is no need for code in this example.

Description

Iā€™ve searched for a solution for this seemingly common problem in APIs and have not found an answer. Please point me to the right direction. Iā€™m trying to add dynamic filtering to my api endpoint by passing groups of filters via query parameters:

Say we have a table Person:

id
name: str
age: int
height: int
born: date

I want to create an API endpoint to get list of Persons using dynamic amount of filters

Letā€™s say we define each filter by having three properties:

field
operator
value

depending on type of field we are filtering, weā€™d have different operators:

str: begins, contains, ends
int, date: <, <=, =, >=, >

For example:

filters = {
    {field: "name", operator: "contains", value: "test"},
    {field: "age", operator: ">", value: 18},
    {field: "age", operator: "<=", value: 31},
    {field: "height", operator: ">", value: 150},
    {field: "height", operator: ">", value: 170},
}

OR

filters = {
    {field: "name", operator: "contains", value: "test"},
    {field: "age", operator: ">", value: 18},
}

As you can see number of filters is dynamic and can include same field several times.

I need to come up with a way to convert these filters into query parameters and pass it to FastAPI

I would like to have pydantic check that ā€œfieldā€ value of each filter group is one of those allowed

Also need to make sure that based on type of field, only appropriate operators will be used

Then I could loop through each filter and apply them to query.

How can I achieve this with FastAPI?

How would filters be represented in URI? (I would like to avoid sending them via GET request body)

Is there an alternative way to achieve this?

Operating System

Linux, Windows, macOS

Operating System Details

No response

FastAPI Version

0.70.1

Python Version

3.9.9

Additional Context

No response

Issue Analytics

  • State:closed
  • Created 2 years ago
  • Comments:7 (1 by maintainers)

github_iconTop GitHub Comments

4reactions
dstlnycommented, Dec 28, 2021

@dstlny your suggestion does not work, the api expects the query filters list in the Body of the request and not Query params

Changing

filters: typing.List[QueryFilter] 

to

filters: typing.List[QueryFilter] = Depends(typing.List[QueryFilter])

should do the trick iirc

Iā€™ve been thinking, and youā€™re probably better off stringifying the list on the frontend, and then parsing it after you recieve the stringified object, rather than letting FastAPI do it. Something like"

from fastapi import Depends
from pydantic import BaseModel, root_validator, parse_obj_as
import typing
import datetime
import json
from dateutil import parser

class QueryFilter(BaseModel):
	field: str
	operator: typing.Literal["includes", "contains", "<", "<=", ">=", ">"]
	value: typing.Union[str, int, datetime.date]

	@root_validator
	def validate_value(cls, values):
		
		operator, value = values.get("operator"), values.get("value")

		## is int
		if value.isdigit():
			if operator in {"<=", "<", ">", ">="}: ## etc
				pass
		else:
                       ## can't be any of these
			if operator in {"<=", "<", ">", ">="}: ## etc
				raise ValueError("Some error")

		return values

@router.get("/thing/")
async def thing(
	request: Request,
	filters: str = Query(...) ## pass as stringifed list of objects
):
	newFilter = json.loads(filters) ## load the stringified list

	all_filters = parse_obj_as(typing.List[QueryFilter], newFilter) ## let pydantic parse the JSON we just loaded... it''ll throw the same errors tha FastAPPI is expecting if it meets any errors

	print(all_filters) ## prints a list of QueryFilter

	return {}

Just tested this locally, stringifying from the frontend as such, and it works as it should. FastAPI get params really arenā€™t made for this kinda thingā€¦ šŸ˜ƒ image image

0reactions
tiangolocommented, Nov 12, 2022

Thanks for the help here everyone! šŸ‘ šŸ™‡

Thanks for reporting back and closing the issue @jimbotrue šŸ‘

Read more comments on GitHub >

github_iconTop Results From Across the Web

Dynamically add/remove query parameters in Postman request
A common issue that you may face when using Postman is adding or removing query parameters dynamically. Ā· Information about the Object. Ā·...
Read more >
Filter by Parameter and Dynamic Drop-Downs with Power Query
Power Query is Excel's new ETL (Extract, Transform, and Load) tool. It's used to pull data in from many different sources, then 'transform'Ā ......
Read more >
Using the Excel FILTER Function to Create Dynamic Filters
Learn how to use the new FILTER function in Excel to create dynamic filters. These dynamic filters will update filter results immediatelyĀ ...
Read more >
Adding search parameters dynamically - Algolia
Click the Add consequence button and select Add Query Parameter. Ā· In the input field that appears, add the JSON parameters you want...
Read more >
Using query parameters Ā· Tinybird Docs
Query parameters are great for any value of the query that you might want control dynamically from your applications.
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found