Me gustaría crear un punto final que se parezca a /cities?population__gt=100000 para obtener todas las ciudades con una población superior a 100 000.
¿Cuál es la mejor manera de hacer esto en FastAPI? Preferiría no tener que enumerar todos los operadores posibles para un campo determinado, así:
@app.get("/cities") def get_city( population: int = None, population_gt: int = None, population_gte: int = None, population_lt: int = None, population_lte: int = None): return ...Una forma de implementar esto es pasar el operator (es decir, gt , lt , etc.) y tener una función separada para cada operación, a la que puede llamar si se recibe un operador. Ejemplo a continuación. Puede ajustar/agregar funciones según sea necesario.
def gt(population): return f"operator: gt, population: {population}" def gte(population): return f"operator: gte, population: {population}" def lt(population): return f"operator: lt, population: {population}" def lte(population): return f"operator: lte, population: {population}" operators = {"gt": gt, "gte": gte, "lt": lt, "lte": lte} @app.get("/cities") def get_city(population: int = None, operator: str = None): if operator in operators: result = operators[operator](population) return result else: return "Operator Not Found!" Dado que, como acaba de decir, esto es necesario para más de un parámetro, sugeriría usar un enfoque similar a este , donde podría pasar el operador dentro del valor de cada clave y extraerlo más tarde en el lado del servidor, por ejemplo, /cities?population=~gt~100000&population=~lt~500000&size=~eq~100000 . Puede tener operadores similares al enlace anterior, es decir, "Iguales": ~eq~ , "Mayor que": ~gt~ , "Mayor que iguales": ~gteq~ , y así sucesivamente.
Para recibir múltiples valores para un parámetro de consulta, como para la population en la URL de ejemplo anterior, para realizar operaciones como where population is greater than <number> and less than <number> , puede declarar un parámetro de consulta con un tipo de List y use Query explícitamente, como se describe aquí y se explica en la documentación .
El siguiente ejemplo le da una idea de la lógica detrás de este enfoque utilizando el parámetro de population , y también muestra cómo extraer el operador y el valor real en el lado del servidor. Luego, depende de usted definir el resto de los parámetros que necesita, así como también cómo manejar estos datos; por ejemplo, usar un enfoque similar al anterior (tener una función para cada operación) o construir la consulta que está a punto de pasar a su base de datos a medida que recorre los datos.
import re pattern = "~(.*?)~" @app.get("/cities") def get_city(population: List[str] = Query(None)): pop_qs = {} for p in population: try: pop_opr = re.search(pattern, p).group(1) pop_no_str = re.sub(r"^~.*?~", "", p) except: return "Invalid data received" try: pop_no = int(pop_no_str) pop_qs.update({pop_opr : pop_no}) except ValueError: return f"Cannot convert '{pop_no_str}' to Integer." return pop_qs