#!/usr/bin/python3
# -*- coding:utf-8 -*-
# __author__ = '__Jack__'

from typing import Optional, List

from fastapi import APIRouter, status, Form, File, UploadFile, HTTPException

from pydantic import BaseModel, EmailStr

app04 = APIRouter()

"""Response Model 响应模型"""


class UserIn(BaseModel):
    """请求体"""
    username: str
    password: str
    email: EmailStr
    mobile: str = "10086"
    address: str = None
    full_name: Optional[str] = None


class UserOut(BaseModel):
    """响应体"""
    username: str
    email: EmailStr  # 用 EmailStr 需要 pip install pydantic[email]
    mobile: str = "10086"
    address: str = None
    full_name: Optional[str] = None


users = {
    "user01": {"username": "user01", "password": "<PASSWORD>", "email": "<EMAIL>"},
    "user02": {"username": "user02", "password": "<PASSWORD>", "email": "<EMAIL>", "mobile": "110"}
}


@app04.post("/response_model/", response_model=UserOut, response_model_exclude_unset=True)
async def response_model(user: UserIn):
    """response_model_exclude_unset=True表示默认值不包含在响应中，仅包含实际给的值，如果实际给的值与默认值相同也会包含在响应中"""
    print(user.password)  # password不会被返回
    # return user
    return users["user01"]


@app04.post(
    "/response_model/attributes",
    response_model=UserOut,
    # response_model=Union[UserIn, UserOut], # 取并集
    # response_model=List[UserOut],
    response_model_include=["username", "email", "mobile"],
    response_model_exclude=["mobile"]
)
async def response_model_attributes(user: UserIn):
    """response_model_include列出需要在返回结果中包含的字段；response_model_exclude列出需要在返回结果中排除的字段"""
    # del user.password  # Union[UserIn, UserOut]后，删除password属性也能返回成功
    return user
    # return [user, user]


"""Response Status Code 响应状态码"""


@app04.post("/status_code", status_code=200)
async def status_code():
    return {"status_code": 200}


@app04.post("/status_attribute", status_code=status.HTTP_200_OK)
async def status_attribute():
    print(type(status.HTTP_200_OK))
    return {"status_code": status.HTTP_200_OK}


"""Form Data 表单数据处理"""


@app04.post("/login/")
async def login(username: str = Form(...), password: str = Form(...)):  # 定义表单参数
    """用Form类需要pip install python-multipart; Form类的元数据和校验方法类似Body/Query/Path/Cookie"""
    return {"username": username}


"""Request Files 单文件、多文件上传及参数详解"""


@app04.post("/file")
# 如果要上传多个文件 files: List[bytes] = File(...)
async def file_(file: bytes = File(...)):
    """使用File类 文件内容会以bytes的形式读入内存 适合于上传小文件"""
    return {"file_size": len(file)}


@app04.post("/upload_files")
# 如果要上传单个文件 file: UploadFile = File(...)
async def upload_files(files: List[UploadFile] = File(...)):
    """
    使用UploadFile类的优势:
    1.文件存储在内存中，使用的内存达到阈值后，将被保存在磁盘中
    2.适合于图片、视频大文件
    3.可以获取上传的文件的元数据，如文件名，创建时间等
    4.有文件对象的异步接口
    5.上传的文件是Python文件对象，可以使用write(), read(), seek(), close()操作
    """
    for file in files:
        contents = await file.read()
        print(contents)
    return {"filename": files[0].filename, "content_type": files[0].content_type}


"""【见run.py】FastAPI项目的静态文件配置"""

"""Path Operation Configuration 路径操作配置"""


@app04.post(
    "/path_operation_configuration",
    response_model=UserOut,
    # tags=["Path", "Operation", "Configuration"],
    summary="This is summary",
    description="This is description",  # 若为None,则显示请求函数的doc
    response_description="This is response description",
    deprecated=True,  # 接口已废弃
    status_code=status.HTTP_200_OK
)
async def path_operation_configuration(user: UserIn):
    """
    Path Operation Configuration 路径操作配置
    :param user: 用户信息
    :return: 返回结果
    """
    return user.dict()


"""【见run.py】FastAPI 应用的常见配置项"""

"""Handling Errors 错误处理"""


@app04.get("/http_exception")
async def http_exception(city: str):
    if city != "Beijing":
        raise HTTPException(status_code=404, detail="City not found!", headers={
                            "X-Error": "Error"})  # 添加headers={"X-Error": "Error"}是在开发中常用方案
    return {"city": city}


@app04.get("/http_exception/{city_id}")
# 如果要重写HTTPException异常类，需要在主应用中重写
async def override_http_exception(city_id: int):
    if city_id == 1:
        raise HTTPException(status_code=418, detail="Nope! I don't like 1.")
    return {"city_id": city_id}

#!/usr/bin/python3
# -*- coding:utf-8 -*-
# __author__ = '__Jack__'

from typing import Optional, List

from fastapi import APIRouter, status, Form, File, UploadFile, HTTPException

from pydantic import BaseModel, EmailStr

app04 = APIRouter()

"""Response Model 响应模型"""


class UserIn(BaseModel):
    """请求体"""
    username: str
    password: str
    email: EmailStr
    mobile: str = "10086"
    address: str = None
    full_name: Optional[str] = None


class UserOut(BaseModel):
    """响应体"""
    username: str
    email: EmailStr  # 用 EmailStr 需要 pip install pydantic[email]
    mobile: str = "10086"
    address: str = None
    full_name: Optional[str] = None


users = {
    "user01": {"username": "user01", "password": "<PASSWORD>", "email": "<EMAIL>"},
    "user02": {"username": "user02", "password": "<PASSWORD>", "email": "<EMAIL>", "mobile": "110"}
}


@app04.post("/response_model/", response_model=UserOut, response_model_exclude_unset=True)
async def response_model(user: UserIn):
    """response_model_exclude_unset=True表示默认值不包含在响应中，仅包含实际给的值，如果实际给的值与默认值相同也会包含在响应中"""
    print(user.password)  # password不会被返回
    # return user
    return users["user01"]


@app04.post(
    "/response_model/attributes",
    response_model=UserOut,
    # response_model=Union[UserIn, UserOut], # 取并集
    # response_model=List[UserOut],
    response_model_include=["username", "email", "mobile"],
    response_model_exclude=["mobile"]
)
async def response_model_attributes(user: UserIn):
    """response_model_include列出需要在返回结果中包含的字段；response_model_exclude列出需要在返回结果中排除的字段"""
    # del user.password  # Union[UserIn, UserOut]后，删除password属性也能返回成功
    return user
    # return [user, user]


"""Response Status Code 响应状态码"""


@app04.post("/status_code", status_code=200)
async def status_code():
    return {"status_code": 200}


@app04.post("/status_attribute", status_code=status.HTTP_200_OK)
async def status_attribute():
    print(type(status.HTTP_200_OK))
    return {"status_code": status.HTTP_200_OK}


"""Form Data 表单数据处理"""


@app04.post("/login/")
async def login(username: str = Form(...), password: str = Form(...)):  # 定义表单参数
    """用Form类需要pip install python-multipart; Form类的元数据和校验方法类似Body/Query/Path/Cookie"""
    return {"username": username}


"""Request Files 单文件、多文件上传及参数详解"""


@app04.post("/file")
# 如果要上传多个文件 files: List[bytes] = File(...)
async def file_(file: bytes = File(...)):
    """使用File类 文件内容会以bytes的形式读入内存 适合于上传小文件"""
    return {"file_size": len(file)}


@app04.post("/upload_files")
# 如果要上传单个文件 file: UploadFile = File(...)
async def upload_files(files: List[UploadFile] = File(...)):
    """
    使用UploadFile类的优势:
    1.文件存储在内存中，使用的内存达到阈值后，将被保存在磁盘中
    2.适合于图片、视频大文件
    3.可以获取上传的文件的元数据，如文件名，创建时间等
    4.有文件对象的异步接口
    5.上传的文件是Python文件对象，可以使用write(), read(), seek(), close()操作
    """
    for file in files:
        contents = await file.read()
        print(contents)
    return {"filename": files[0].filename, "content_type": files[0].content_type}


"""【见run.py】FastAPI项目的静态文件配置"""

"""Path Operation Configuration 路径操作配置"""


@app04.post(
    "/path_operation_configuration",
    response_model=UserOut,
    # tags=["Path", "Operation", "Configuration"],
    summary="This is summary",
    description="This is description",  # 若为None,则显示请求函数的doc
    response_description="This is response description",
    deprecated=True,  # 接口已废弃
    status_code=status.HTTP_200_OK
)
async def path_operation_configuration(user: UserIn):
    """
    Path Operation Configuration 路径操作配置
    :param user: 用户信息
    :return: 返回结果
    """
    return user.dict()


"""【见run.py】FastAPI 应用的常见配置项"""

"""Handling Errors 错误处理"""


@app04.get("/http_exception")
async def http_exception(city: str):
    if city != "Beijing":
        raise HTTPException(status_code=404, detail="City not found!", headers={
                            "X-Error": "Error"})  # 添加headers={"X-Error": "Error"}是在开发中常用方案
    return {"city": city}


@app04.get("/http_exception/{city_id}")
# 如果要重写HTTPException异常类，需要在主应用中重写
async def override_http_exception(city_id: int):
    if city_id == 1:
        raise HTTPException(status_code=418, detail="Nope! I don't like 1.")
    return {"city_id": city_id}

#!/usr/bin/python3 # -*- coding:utf-8 -*- # __author__ = '__Jack__' Response Model 响应模型 请求体 响应体 # 用 EmailStr 需要 pip install pydantic[email] response_model_exclude_unset=True表示默认值不包含在响应中，仅包含实际给的值，如果实际给的值与默认值相同也会包含在响应中 # password不会被返回 # return user # response_model=Union[UserIn, UserOut], # 取并集 # response_model=List[UserOut], response_model_include列出需要在返回结果中包含的字段；response_model_exclude列出需要在返回结果中排除的字段 # del user.password  # Union[UserIn, UserOut]后，删除password属性也能返回成功 # return [user, user] Response Status Code 响应状态码 Form Data 表单数据处理 # 定义表单参数 用Form类需要pip install python-multipart; Form类的元数据和校验方法类似Body/Query/Path/Cookie Request Files 单文件、多文件上传及参数详解 # 如果要上传多个文件 files: List[bytes] = File(...) 使用File类 文件内容会以bytes的形式读入内存 适合于上传小文件 # 如果要上传单个文件 file: UploadFile = File(...) 使用UploadFile类的优势:     1.文件存储在内存中，使用的内存达到阈值后，将被保存在磁盘中     2.适合于图片、视频大文件     3.可以获取上传的文件的元数据，如文件名，创建时间等     4.有文件对象的异步接口     5.上传的文件是Python文件对象，可以使用write(), read(), seek(), close()操作 【见run.py】FastAPI项目的静态文件配置 Path Operation Configuration 路径操作配置 # tags=["Path", "Operation", "Configuration"], # 若为None,则显示请求函数的doc # 接口已废弃 Path Operation Configuration 路径操作配置     :param user: 用户信息     :return: 返回结果 【见run.py】FastAPI 应用的常见配置项 Handling Errors 错误处理 # 添加headers={"X-Error": "Error"}是在开发中常用方案 # 如果要重写HTTPException异常类，需要在主应用中重写