-
-
Notifications
You must be signed in to change notification settings - Fork 429
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
using patch with None, and optional fields #1045
Comments
Better late than never you could use it like this:
|
Thanks @Qadosch, I worked around it by getting at the request itself. My question wasn't so much that I was blocked, as whether I understood correctly, warranting opening an issue and/or a PR. |
As far as I understand, the concept of Schemas is to deal with unset values, is by setting them to None. Pydantic deals with this this way and by extension FastAPI and DjangoNinja. It feels like the PATCH method is not welcome lol |
Might be able to be handled with a function instead. A helper method that takes the Schema specifying the possible fields/validation, and the request, and once the data has been verified normalizes it for changed fields only. Essentially, doing the Schema work first, then removing fields that weren't in the request body. Could also be a method on the class, in addition to Another way to deal with it is to add |
I have a similar problem.
Can we have If a field is optional we can have it as such: class TheSchema(Schema):
the_field_1: Optional[str]
the_field_2: Optional[str] Here class TheSchema(Schema):
the_field_1: str = None
the_field_2: str = None Here the |
Hi @mshemuni yeah it make some sense... but unfortunately this |
I was thinking about PATCH - and it looks like what people have issues with and most common use is that schema is created with all fields option and then it is used with so maybe the most elegant solution would be to have some special type marker that will simply turn any schema to schema with optional fields and return a dict (with excluded unset) class SomeSchema(Schema):
foo: str
bar: int
@api.post("/create")
def create(request, payload: SomeSchema):
...
@api.patch("/patch")
def patch(request, payload: PatchDict[SomeSchema]): # <----
print(payload) # will print like {"bar": 1}
so payload inside patch function will actually be a validated dict with excluded fields that were not passed |
This is more elegant than what I was thinking about! A convenience method on
A similar convenience method on ModelSchemas for PUTs would also save some code. Every time I write a PUT I have to write the same iteration loop setting all the attrs. I'm happy to take a crack at PR for all this if you're interested (although it would be weeks from now, my schedule is a bit full at the moment) |
as long its still possible to call |
I spent a bit of time on this, and well, I believe I'm in over my head. I don't really use type hinting much in Python. I thought the answer was the use of a Generic, but those don't appear to actually inherit the class they're wrapping. I can get at the ModelSchema's methods, but the payload is expected to be a Pydantic model and it isn't clear to me how to make the Generic behave as the model itself. I thought about an inheritance approach, but that ran into its own problems because of how the metaclass works. I then tried dynamically copying the class itself, and making modifications to it, but that falls down because Pydantic mucks with the fields at instantiation and changes afterwards don't effect the behaviour. Separately, I think there is value in ModelSchema having methods that apply the "put" and "patch" operations on a passed in Django model, that way the view can be pretty much a one-liner, similar to how POST and create works using **payload.dict(). Although PatchDict might be useful in its own right, if "apply_put" and "apply_patch" existed (up for feedback on the names), you wouldn't need PatchDict. What approach would you suggest I take? I can implement "apply_put" and "apply_patch" as a PR. And/or, if someone can point me at where to learn more about using typing as an adapting class I'm willing to take another stab at it. That could be its own PR or the sole approach. Thoughts? |
Guys, the option class ContractSchemaInput(ModelSchema):
sender_id: int
client_id: int
type_id: int
price_frequency: Literal["minute", "hourly", "daily", "weekly", "monthly"]
care_type: Literal["ambulante", "accommodation"]
attachment_ids: list[str] = []
class Meta:
model = Contract
exclude = ("id", "type", "sender", "client", "updated", "created")
@router.patch("/contracts/{int:id}/update", response=ContractSchema)
def update_client_contract(request: HttpRequest, id: int, contract: ContractSchemaInput):
print("Payload:", contract.dict(exclude_unset=True))
Contract.objects.filter(id=id).update(**contract.dict(exclude_unset=True))
return get_object_or_404(Contract, id=id) Output error: {
"detail": [
{
"type": "missing",
"loc": [
"body",
"contract",
"sender_id"
],
"msg": "Field required"
},
{
"type": "missing",
"loc": [
"body",
"contract",
"client_id"
],
"msg": "Field required"
},
{
"type": "missing",
"loc": [
"body",
"contract",
"type_id"
],
"msg": "Field required"
},
{
"type": "missing",
"loc": [
"body",
"contract",
"care_type"
],
"msg": "Field required"
},
{
"type": "missing",
"loc": [
"body",
"contract",
"start_date"
],
"msg": "Field required"
},
{
"type": "missing",
"loc": [
"body",
"contract",
"end_date"
],
"msg": "Field required"
},
{
"type": "missing",
"loc": [
"body",
"contract",
"care_name"
],
"msg": "Field required"
}
]
} Please any suggestions? |
@medram
and your Models have to support that schema |
Hello there,
I don't normally bother with a PATCH operation, but need to this time and so am running into something I haven't before. I've built a ModelSchema using the Meta attribute
fields_optional="__all__"
, but the associated payload includes all keys, even if they're aren't sent in the request. Keys that aren't sent are set to None. This is problematic, as there is no way to differentiate a client wanting to set a value to None from a value not being sent.Am I doing it wrong?
While on the topic, it'd be great to have a shortcut for creating a schema based on another one, but with a change to its attributes. For example, having a Car model, I would have a CarInSchema for the PUT, and a CarPatchSchema for the PATCH. Rather than copy-paste the class, it'd be great to have a way to create CarPatchSchema based on CarInSchema, but with the
fields_optional
attribute set. I attempted to use inheritance to accomplish this, but it didn't seem to work. Probably something to do with the inner class and how the metaclass is creating the class.(Actually, on that topic, it'd be great to be able to just add a field as well. 90% of the time my "In" and "Out" Schemas only differ by the ID field, so having a base "In" Schema, and an inheriting Out and Patch Schema where only the changes were needed would be ideal)
The text was updated successfully, but these errors were encountered: