What is Body? `from fastapi import Body` - python

In the documentation and elsewhere I have seen Body used but don't know what it is.
Can someone explain what these three options mean?
from fastapi import Body
from pydantic import BaseModel
class MyModel(BaseModel):
body1: None
body2: Body(None)
body3: Body(...)

When you use a Pydantic model you don't need to use Body.
You could write:
from pydantic import BaseModel, Schema
class MyModel(BaseModel):
body1: None
body2: Schema(None)
body3: Schema(...)
Body is used only in path operation parameters when you need to force FastAPI to understand that the parameter is received in as part of the body (e.g. instead of a query parameter). You only need to use Body explicitly when using parameters of "singular" types (of a single value, like int, str). If you use a Pydantic model, a list or something similar as a type, you don't need to use Body explicitly.
You can also use Body to add extra metadata if you need to. Like a title, examples, etc.
Read more about it here in the docs: https://fastapi.tiangolo.com/tutorial/body/

Related

Trying to set a superclass field in a subclass using validator

I am trying to set a super-class field in a subclass using validator as follows:
Approach 1
from typing import List
from pydantic import BaseModel, validator, root_validator
class ClassSuper(BaseModel):
field1: int = 0
class ClassSub(ClassSuper):
field2: List[int]
#validator('field1')
def validate_field1(cls, v, values):
return len(values["field2"])
sub = ClassSub(field2=[1, 2, 3])
print(sub.field1) # It prints 0, but expected it to print 3
If I run the code above it prints 0, but I expected it to print 3 (which is basically len(field2)). However, if I use #root_validator() instead, I get the expected result.
Approach 2
from typing import List
from pydantic import BaseModel, validator, root_validator
class ClassSuper(BaseModel):
field1: int = 0
class ClassSub(ClassSuper):
field2: List[int]
#root_validator()
def validate_field1(cls, values):
values["field1"] = len(values["field2"])
return values
sub = ClassSub(field2=[1, 2, 3])
print(sub.field1) # This prints 3, as expected
New to using pydantic and I am bit puzzled what I am doing wrong with the Approach 1. Thank you for your help.
The reason your Approach 1 does not work is because by default, validators for a field are not called, when the value for that field is not supplied (see docs).
Your validate_field1 is never even called. If you add always=True to your #validator, the method is called, even if you don't provide a value for field1.
However, if you try that, you'll see that it will still not work, but instead throw an error about the key "field2" not being present in values.
This in turn is due to the fact that validators are called in the order they were defined. In this case, field1 is defined before field2, which means that field2 is not yet validated by the time validate_field1 is called. And values only contains previously-validated fields (see docs). Thus, at the time validate_field1 is called, values is simply an empty dictionary.
Using the #root_validator is the correct approach here because it receives the entire model's data, regardless of whether or not field values were supplied explicitly or by default.
And just as a side note: If you don't need to specify any parameters for it, you can use #root_validator without the parantheses.
And as another side note: If you are using Python 3.9+, you can use the regular list class as the type annotation. (See standard generic alias types) That means field2: list[int] without the need for typing.List.
Hope this helps.

Pydantic schema logic

So, I'm building an API to interact with my personal wine labels collections database.
For what I understand, a pydantic model purpose is to serve as a "verifier" of the schema that is sent to the API. So, my pydantic schema for adding a label is the following:
from pydantic import BaseModel
from typing import Optional
class WineLabels(BaseModel):
name: Optional[str]
type: Optional[str]
year = Optional[int]
grapes = Optional[str]
country = Optional[str]
region = Optional[str]
price = Optional[float]
id = Optional[str]
None of the fields is to be updated automatically. This is equal to the sqlalchemy model since I want to add all the fields manually.
So my question is, let's say I want to create a call to search by ID and another one to search by name. I do not believe these schema should be applied. Should I create another schema ? Should I create one like this?:
class SearchWineLabel(WineLabels):
id: str
Should a schema be created for each purpose that cannot be fulfilled by an already existing schema?
Sorry, but I can't understand the logic behind it.
Thanks!!
If you want to search by id or name, I'm not sure if you even need a schema - one or more get parameters would usually be enough in those cases (and is usually better semantically).
In any case, the schema would be written for what the endpoint is expected to receive, not by using a general schema that contains the field in some other way. Think of the schemas as the input/output definitions for given resources and endpoints.
You usually want to have different schemas for adding and updating (since adding will require certain fields to be present, while updating may allow null or a missing field in any location).
The Pydantic schemas will allow you to express these differences without writing code, and it will be reflected in your generated api docs under /docs

What's the diference between 'normal' Python Classes and Pydantic Classes?

I would like to know the difference between classes built normally in python and those built with the Pydantic lib, for example:
eg normal;
class Node:
def __init__(self, chave=None, esquerda=None, direita=None):
self.chave = chave
self.esquerda = esquerda
self.direita = direita
eg pydantic;
from datetime import datetime
from typing import List, Optional
from pydantic import BaseModel
class User(BaseModel):
id: int
name = 'John Doe'
signup_ts: Optional[datetime] = None
friends: List[int] = []
There are a few main differences.
Firstly, purpose. Pydantic models are designed to:
Data validation and settings management using python type annotations.
pydantic enforces type hints at runtime, and provides user friendly errors when data is invalid.
When you use type annotations you receive a lot of validators and some useful methods out of the box.
As Ahmed and John says, in your example you can't assign “hello” to id in BaseModel (pydantic) because you type id as an int. But you can pass a string “1” (must be a numerical, not float) and it will be mapped to int. In this case:
pydantic uses int(v) to coerce types to an int; see this warning on loss of information during data conversion
Also Pydantic models allows you to use many more types than standard python types, like urls and much more. It means that you can easily validate more data types.
You can easily create complex models using composition.
Pydantic has some kind of integration with orms: docs
There are a lot of other features, much more than I can describe in a single answer. I strongly recommend reading the documentation, it is very clear and useful.
The pydantic models are very useful for example in building microservices where you can share your interfaces as pydantic models. Also all models can easily generate the json schema. See: Schema, exporting models.
Pydantic is also a big part of a growing in popularity python web framework fastapi.

"str" is not a dataclass error with marshmallow and marshmallow-dataclass

Using python, I am trying to create data schema for my dataclasses using marshmallow and marshmallow-dataclass. I believe I have followed the docs, adding the decorator to my relevant dataclasses and NewTypes to my fields that are not standard python objects. However, I am getting an error before the program even loads.
The error relates to a str not being a dataclass and I have no idea how the decorator is processing a string instead of a dataclass.
I am sure I have missed something simple, so apologies in advance if that is the case.
A summarised version of the code is:
from marshmallow_dataclass import dataclass as m_dataclass, NewType
ProjectileDataType = NewType("ProjectileDataType", Any)
#m_dataclass
class ProjectileData:
Schema: ClassVar[Type[Schema]] = Schema
# what created it?
skill_name: str = field(default="None")
# what does it look like?
sprite: str = field(default="None")
defintions.py : https://pastebin.com/tHnVE2Gc
Error traceback: https://pastebin.com/htuqhKSU
Docs: https://github.com/lovasoa/marshmallow_dataclass , https://marshmallow.readthedocs.io/en/stable/quickstart.html

Extending protorpc StringField

I would like to write custom validation for some fields in ProtoRPC messages.
The documentation says, that protorpc.messages.Field class cannot be extended by developers.
Does it mean I should not extend StringField?
E.g. StringField does not ensure that string is non-empty.
I've checked, and my custom string class with my validate_element method works as expected.
Is there any reason, I should not do that?
You can subclass protorpc.messages.MessageField to create a custom Field. See the DataTimeField source code for an example of this.

Categories