Skip to content

This issue was moved to a discussion.

You can continue the conversation there. Go to discussion →

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Optinal request parameters fields/models where at least ONE OF MANY is required #5731

Closed
9 tasks done
gprieto opened this issue Dec 4, 2022 · 3 comments
Closed
9 tasks done
Labels
question Question or problem question-migrate

Comments

@gprieto
Copy link

gprieto commented Dec 4, 2022

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

from fastapi import FastAPI

app = FastAPI()

@app.post("/path")
async def demo_post(this: str | None = None, or_this: str | None = None):

    return {
        "message": this or or_this
    }

Description

  • I would like to enforce that one of two optional parameters must be present in the request body
  • So that I get the correct validation errors if none of them are present

Operating System

Linux

Operating System Details

No response

FastAPI Version

0.88.0

Python Version

3.11.0

Additional Context

No response

@gprieto gprieto added the question Question or problem label Dec 4, 2022
@davismartens
Copy link

davismartens commented Dec 4, 2022

If you you only have 2 params you could use Union?

from fastapi import FastAPI
from typing import Union, Optional
from pydantic import BaseModel

app = FastAPI()

class param1(BaseModel):
    param1: str

class param2(BaseModel):
    param2: str


@app.post("/foo/")
async def foo(param: Union[param1, param2]):
    return param

If you user str | None = None it will simply say that one is not required but not guarantee that one or the other is required.

You might also find this helpful:
pydantic/pydantic#506
https://stackoverflow.com/questions/58958970/dataclasses-require-at-least-one-value-to-be-set-in-grouping-of-model-fields

@gprieto
Copy link
Author

gprieto commented Dec 4, 2022

Thank you @davismartens, your solution works for one field with different types/models.

My question was about different root fields - with different names - for which indeed the links you posted proved insightful. Nonetheless, the solution they propose which is to be using a validator works inside a pydantic model.

My original question is about making this work for FastAPI body parameters, is there a body-wide validator that one can define in FastAPI?

@davismartens
Copy link

@gprieto I might be misunderstand you here... but can't you just use the pydantic model + validator as your body param? or are you asking something else?

from fastapi import FastAPI
from typing import Optional
from pydantic import BaseModel, root_validator
from pydantic.dataclasses import dataclass

@dataclass
class params:
    field1: Optional[str] = None
    field2: Optional[str] = None
    field3: Optional[str] = None

    @root_validator
    def any_of(cls, v):
        if not any(v.values()):
            raise ValueError('one of field1, field2 or field3 must have a value')
        return v

@app.post("/foo/")
async def foo(param: params):
    return param

Repository owner locked and limited conversation to collaborators Feb 28, 2023
@tiangolo tiangolo converted this issue into discussion #8425 Feb 28, 2023

This issue was moved to a discussion.

You can continue the conversation there. Go to discussion →

Labels
question Question or problem question-migrate
Projects
None yet
Development

No branches or pull requests

3 participants