FastAPI+React全栈开发15 让我们构建一个展示API

news/2024/4/15 7:37:03

Chapter03 Getting Started with FastAPI

15 Let’s Build a showcase API

FastAPI+React全栈开发15 让我们构建一个展示API

REST APIs are all about cycles of HTTP requests and responses, it is the engine that powers the web and is implemented in every web framework, speaking the language of the web, the HTTP protocol. I feel that the best way to showcase FastAPI’s capabilities is to dive right in and create simple endpoints and focus on specific parts of code that achieve the desired functionalities. Rather than the usual CRUD operations that we will implement in the forthcoming chapters, I want to focus on the process of retrieving and setting request and response elements.

REST api都是关于HTTP请求和响应的循环,它是为web提供动力的引擎,并且在每个web框架中实现,使用web的语言,HTTP协议。我觉得展示FastAPI功能的最好方法是直接进入并创建简单的端点,并专注于实现所需功能的代码的特定部分。与我们将在接下来的章节中实现的常规CRUD操作不同,我想重点关注检索和设置请求和响应元素的过程。

Retrieving path and query parameters

The first endpoint will be for retrieving a car by its unique ID:


from fastapi import FastAPIapp = FastAPI()@app.get("/car/{id}")
async def get_car(id: str):return {"id": id}if __name__ == '__main__':import

The first line of the preceding snippet defines a dynamic path, the static part is defined with car/, while {id} is a standard Python string formatted dynamic parameter in the sense that it can be anything, a string or a number.


Let’s try it out and test the endpoint with an ID equal to 1:


http localhost:8000/car/1
HTTP/1.1 200 OK
content-length: 10
content-type: application/json
date: Wed, 27 Mar 2024 09:48:46 GMT
server: uvicorn{"id": "1"

We got our JSON response back, but here, 1 in the response is a string. You can try this same route with an ID equal to a string.


http localhost:8000/car/abc
HTTP/1.1 200 OK
content-length: 12
content-type: application/json
date: Wed, 27 Mar 2024 09:50:34 GMT
server: uvicorn{"id": "abc"

FastAPI doesn’t complain and returns our string, which was provided as part of the dynamic parameter, but this is where Python’s newer features come into play. Enter type hinting.


Returning to our FastAPI route (or endpoint), to make the car ID become an integer, it is enough to hint at the type of the variable parameter. The endpoint will look like this.


from fastapi import FastAPIapp = FastAPI()@app.get("/car/{id}")
async def get_car(id: int):return {"id": id}if __name__ == '__main__':import

I have given it a new path: /car/{id} . Apart from the name of the function, the only difference is in the argument, the semicolon followed by int means that we expect aninteger, but FastAPI takes this very seriously.


If we take a look at the interactive documention at http://llocalhost:8000/docs, and try to insert a string in the id field for the /car endpoint, we will get an error and will not be able to proceed.


http localhost:8000/car/abc
HTTP/1.1 422 Unprocessable Entity
content-length: 201
content-type: application/json
date: Wed, 27 Mar 2024 09:58:10 GMT
server: uvicorn{"detail": [{"input": "abc","loc": ["path","id"],"msg": "Input should be a valid integer, unable to parse string as an integer","type": "int_parsing","url": ""}]

If we try it out in our REST client and test the /car route by passing it a string, we will see that FastAPI is yelling at us, but this is for our own good! We got several useful messages. First, FastAPI set the status code for us correctly, that is 422 Unprocessable Entity, and in the body of the response, it pointed out what the problem was, the value is not valid integer. It also gives us the location where the error occurred, in the path, that is, the id part. This is a trivial example, but imagine that you are sending a complex request with a complicated path, several query strings, and maybe additional information in the header. Using type hinting quickly solves these problems.

如果我们在REST客户端中尝试它,并通过传递一个字符串来测试/car路由,我们将看到FastAPI对我们大喊大叫,但这是为了我们自己好!我们收到了几条有用的信息。首先,FastAPI为我们正确地设置了状态码,即422 Unprocessable Entity,并且在响应的主体中指出了问题所在,值不是有效的整数。它还为我们提供了错误发生的位置,在路径中,即id部分。这是一个简单的例子,但是想象一下,您正在发送一个复杂的请求,该请求具有复杂的路径、几个查询字符串,并且头中可能还有其他信息。使用类型提示可以快速解决这些问题。

If you try to access the endpoint without specifying any ID, you will get yet another error.


http get localhost:8000/car
HTTP/1.1 404 Not Found
content-length: 22
content-type: application/json
date: Wed, 27 Mar 2024 11:42:03 GMT
server: uvicorn{"detail": "Not Found"

FastAPI has, again, correctly set the status code giving us a nice 404 Not Found error, and repeated this message in the body. The endpoint that we hit does not exist, we need to pecify a value after the slash.

FastAPI再次正确地设置了状态码,给我们一个很好的404 Not Found错误,并在body中重复此消息。我们命中的端点不存在,我们需要在斜杠后面指定一个值。

Situations may arise where you have similar paths, but one of them is dynamic, while the other one is static. A typical case could be an application that has numerous users, hitting the API at the URL defined by /users/id would give you some information about the user with the selected ID, while /users/me would typically be an endpoint that displays your information and allows you to modify it in some way.


In these situations, it is important to remember that, like in other web frameworks, order matters.


The following piece of code will not yield the desired results.


from fastapi import FastAPIapp = FastAPI()@app.get("/car/{id}")
async def get_car(id: str):return {"id": id}@app.get("/car/yellow")
async def get_car():return {"abc": "yellow"}if __name__ == '__main__':import
http get localhost:8000/car/333
HTTP/1.1 200 OK
content-length: 12
content-type: application/json
date: Wed, 27 Mar 2024 11:48:27 GMT
server: uvicorn{"id": "333"
http get localhost:8000/car/yellow

这里的路由被 /car/{id} 捕获了,没有走 /car/yellow 的逻辑。

HTTP/1.1 200 OK
content-length: 15
content-type: application/json
date: Wed, 27 Mar 2024 11:48:52 GMT
server: uvicorn{"id": "yellow"

FastAPI allows us to solve this at the path level by letting us create a class based on Enum for the account type. This class defines all the possible values for the account variable. In our case, there are just two, free and pro.


from fastapi import FastAPI
from enum import Enumapp = FastAPI()class AccountEnum(str, Enum):FREE = "free"PRO = "pro"

Finally, in the actual endpoint, we combine this class with the utilities from the Path function (do not forget to import it along with FastAPI from fastapi!).


from fastapi import FastAPI, Path
from enum import Enumapp = FastAPI()class AccountEnum(str, Enum):FREE = "free"PRO = "pro"@app.get("/account/{acc_type}/{months}")
async def get_account_enum(acc_type: AccountEnum, months: int = Path(..., ge=3, le=12)):return {"message": "Account Enum","acc_type": acc_type,"months": months,}if __name__ == '__main__':import

FastAPI was able to pack a lot of punch in the preceding code: by setting the type of the acc_type part of the path to our previously defined class, we ensured that only the free or pro value can be passed. The months variable, however, is handled by the Path utility function.


As for other topics in this part, I strongly advise you to head over to the excellent documentation site and see what other options are avvailable, in this case, the Path function received three parameters. The three dots mean that the value is required and that no default value has been provided, get=3 means that the value can be greater or equal to 3, while le=12 means that it can be smaller or equal to 12.


With that, we’ve learned how to validate, restrict, and order our path parameters. Now, let’s look at the query parameters. Query parameters are added at the end of the URL by using the ?min_price=2000&max_price=4000 format.


The question mark in the previous expression is a separator that tells us where the query string begins, while the ampersands, &, allow us to add more than one assignment (the equals signs, =).


Query parameters are usually used to apply filters, sort, order, or limit query sets, apply paginations to a long list of results, and similar tasks. FastAPI treats them similarly to path parameters. They will be, so to say, automatically picked up by FastAPI and available for processing in our endpoint functions.


Let’s create a simple endpoint that accepts two query parameters for the minimum and the maximum prices of the car.


from fastapi import FastAPIapp = FastAPI()@app.get("/cars/price")
async def get_cars(min_price: int = 0, max_price: int = 100000):return {"message": "get_cars","min_price": min_price,"max_price": max_price,}if __name__ == '__main__':import

Let’s test this endpoint with HTTPie.


http "localhost:8000/cars/price?min_price=2000&max_price=4000"
HTTP/1.1 200 OK
content-length: 56
content-type: application/json
date: Wed, 27 Mar 2024 15:06:12 GMT
server: uvicorn{"max_price": 4000,"message": "get_cars","min_price": 2000

Of course, this particular solution is not very good, we do not ensure the basic condition that the minimum price should be lower than the maximum price, but that can easily be handled by Pydantic object-level validation.


FastAPI picked up our query parameters and performed the same parsing and validation checks it did previously. It is worth mentioning that FastAPI provides the Query function, which is very similar to the Path function that we used previously, we can use the greater than, less than, or equal conditions, as well as set default values.


With that, we’ve seen how FastAPI enables us to work with data that is passed through the path and query parameters, as well as the tools it uses under the hood to perform parsing and validation as soon as possible. Now, let’s examine the main data vehicle of REST APIs: the request body.

至此,我们已经看到了FastAPI如何使我们能够处理通过路径和查询参数传递的数据,以及它在底层使用的工具,以便尽快执行解析和验证。现在,让我们检查一下REST api的主要数据载体:请求体。

The request body - the bulk of the data

REST APIs enable two-way communicaton between a client, usually a web browser or similar device and an API server. The bulk of this data is carried over in the request and response body. A request body consists of the data that’s sent from the client to our API, if there is such data, while the response body is the data sent from the API server to our client(s). This data can be encoded in various ways (XML was quite popular 15 years ago, for example) but in this book, we will consider exclusively JavaScript Object Notation (JSON) since it is used everywhere and it plays exceptionlly nicely with our database solution of choice, MongoDB.

REST API支持客户端(通常是web浏览器或类似设备)与API服务器之间的双向通信。这些数据的大部分在请求和响应体中传递。请求体包含从客户端发送到我们的API的数据(如果有这样的数据),而响应体是从API服务器发送到我们的客户端的数据。这些数据可以以各种方式编码(例如,XML在15年前非常流行),但在本书中,我们将只考虑JavaScript对象表示法(JSON),因为它无处不在,而且它与我们选择的数据库解决方案MongoDB配合得非常好。

When sending data, we should always use POST requests to create new resources, PUT and PATCH to update resources, and the DELETE method to delete. Since the body of a request can and will contain raw data, in our case, MongoDB documents or arrays of documents, we will see how we can leverage the power of Pydantic models to our benefit. But first, let’s see how the mechanism works, without any validation or modeling.


In the following snippet for a hypothetical endpoint that would be used to insert new cars in our future database, we pass just the generic request body as the data. We expect it to be a dictionary.


from typing import Dictfrom fastapi import FastAPI, Bodyapp = FastAPI()"/cars")
async def new_car(data: Dict = Body(...)):return dataif __name__ == '__main__':import

Intuitively, you may have guessed that the Body function is somewhat similar to the previously introduced Path and Query functions, yet there is a difference, when working with the request body, this function is mandatory.


The three dots indicate that the body is required (you must send something), but this is the only requirement. Let’s try to insert a car (a Fiat 500, made in 2015).


http POST "localhost:8000/cars" brand="FIAT" model="500" year=2015
HTTP/1.1 200 OK
content-length: 44
content-type: application/json
date: Wed, 27 Mar 2024 15:22:26 GMT
server: uvicorn{"brand": "FIAT","model": "500","year": "2015"

Again, FastAPI functions do the heavy lifting for us, we were able to retrieve all the data that was passed to the request body and make it available to our function for further processing, database insertion, optional preprocessing, and so on. On the other hand, we could have passed just about any key-value pairs to the body. For example, we could set the number of legs to 4(cars do not have legs, yet), and it would make its way into the request body, disregarding modern car engineering.


Keen observers may have notice that while all went well, FastAPI sent us a 200 response status again, even through a 201 Resource Created error may have been more appropriate and, well, exact. We could have had some MongoDB insertion at the end of the function, after all. Do not worry, we will see how easy it is to modify the response body as well, but for now, let’s see why Pydantic shines when it comes to request bodies.


Let’s say that we wawnt to enforce a certain structure for our request body. After all, we cannot allow users to send arbitrary fields and data and bomb our precious POST endpoint. To create new car entries, we only want the brand, model, and production year fields.


We will create a simple Pydantic model with the desired types.


from fastapi import FastAPI, Body
from pydantic import BaseModelclass InsertCar(BaseModel):brand: strmodel: stryear: intapp = FastAPI()"/cars")
async def new_car(data: InsertCar = Body(...)):return dataif __name__ == '__main__':import

By now, you already know that the first two parameters are expected to be strings, while the year must be an integer, all of them are required.


Now, if we try to post the same data that we did previously but with additional fields, we will only get these three fields back. Also, these fields will go through Pydantic parsing and validation and throw meaningful error messages if something does not conform to the data specification.


I encourage you to play with this endpoint and try different post data combinations. The following is an example.


http POST "localhost:8000/cars" brand="FIAT" model="500" year=2015
HTTP/1.1 200 OK
content-length: 42
content-type: application/json
date: Wed, 27 Mar 2024 15:34:34 GMT
server: uvicorn{"brand": "FIAT","model": "500","year": 2015

This combination of Pydantic model validation and the Body function provides all the necessary flexibility when working with request data. This is because you can combine them and pass different pieces of information using the same request bus ride, so to speak.


If we wanted to pass a user with a promo code along with the new car data, we could try to define a Pydantic model for the user and extract the promo code with the Body function. First, let’s define a minimal user model.


class InsertUser(BaseModel):username: strname: str

Now, we can create a more complex function that will process two Pydantic models and an optional user promo code, we have set the default value to None.


from fastapi import FastAPI, Body
from pydantic import BaseModelclass InsertCar(BaseModel):brand: strmodel: stryear: intclass InsertUser(BaseModel):username: strname: strapp = FastAPI()"/cars")
async def new_car(user: InsertUser,car: InsertCar,code: int = Body(None)
):return {"user": user,"car": car,"code": code,}if __name__ == '__main__':import

For this request, which contains a full fledged JSON object with two nested objects and some code, I opted to use Insomnia since I find it easier than typing JSON in the command propt or resorting to piping. I guess it is a matter of preference, but I believe that when developing and testing REST APIs, it is useful to have a GUI tool such as Insomnia or Postman and a command-line client (such as cURL or httpie). This is what Insomnia looks like when testing this particular endpoint.

对于这个包含两个嵌套对象和一些代码的完整JSON对象的请求,我选择使用Insomnia,因为我发现它比在命令提示符中输入JSON或使用管道更容易。我想这是一个偏好问题,但我相信,在开发和测试REST api时,有一个GUI工具(如Insomnia或Postman)和一个命令行客户端(如cURL或httpie)是很有用的。这就是Insomnia 在测试这个特定端点时的样子。

POST: http://localhost:8000/cars
{"car":{"brand": "Renault","model": "Twingo","year": 2017},"user": {"username": "zhangdapeng","name": "dapeng"},"code": 10000

After playing around with the combination of request bodies and Pydantic models, we have seen that we can control the inflow of the data and be confident that the data that’s available to our API endpoint will be what we want it and expect it to be. Sometimes, however, we may want to go to the bare metal and work with the raw request object. FastAPI covers that case too.


The request object

I have mentioned several times that FastAPI is built on the Starlette web framework and that it uses numberous Starlette features. The raw request object in FastAPI is Starlette’s request object and it can be accessed in our functions once it’s been imported from FastAPI directly. Bear in mind that by using the request object directly, you are missing out on FastAPI’s most important features, Pydantic parsing and validation, as well as self documentation! However, there might be situations in which you need to have the raw requests.

我已经多次提到FastAPI是建立在Starlette web框架上的,它使用了许多Starlette的特性。FastAPI中的原始请求对象是Starlette的请求对象,一旦从FastAPI直接导入,就可以在我们的函数中访问它。请记住,通过直接使用请求对象,您将错过FastAPI最重要的特性,Pydantic解析和验证,以及自我文档!但是,在某些情况下,您可能需要原始请求。

from fastapi import FastAPI, Requestapp = FastAPI()"/cars")
async def new_car(req: Request):return {"base_url": req.base_url,}if __name__ == '__main__':import

In the preceding code, we created a minimal FastAPI app, imported the Request class, and used it in the only endpoint. If you test this endpoint with your REST client, you will only get the base URL as the message, while the all part lists all the methods and properties of the Request object so that you have an idea of what is available.


All of these methods and properties are available for you to use in your application.


With that, we’ve seen how FastAPI facilitates our work with the main HTTP transport mechanisms request bodies, query strings, and paths. Now, we will cover other, equally important aspects of any web framework solution.


Cookies and headers, form data, and files

When speaking of the ways our web framework ingests data, any discussion would be incomplete without including topics such as handling form data, handling files, and manipulating cookies and headers. This section will provide simple examples of how FastAPI handles these tasks.



Header parameters are handled in a similar way to query and path parameters and, as we will see later, cookies. We can collect them, so to speak, using the Header function. Headers are essential in topics such as authentication and authorization as they often carry JSON Web Tokens (JWTs), which are used for identifying users and their permissions.

处理报头参数的方式与处理查询和路径参数以及cookie的方式类似。可以这么说,我们可以使用Header函数收集它们。标头在身份验证和授权等主题中是必不可少的,因为它们通常携带JSON Web令牌(jwt),用于标识用户及其权限。

Let’s try to read the user agent by using the Header function.


from fastapi import FastAPI, Headerapp = FastAPI()"/cars")
async def new_car(user_agent: str | None = Header(None)):return {"User-Agent": user_agent}if __name__ == '__main__':import


http POST localhost:8000/cars


HTTP/1.1 200 OK
content-length: 29
content-type: application/json
date: Wed, 27 Mar 2024 23:27:57 GMT
server: uvicorn{"User-Agent": "HTTPie/3.2.2"

You can extract all the headers in this way and FastAPI is nice enough to provide further assistance: it will convert names into lowercase, convert the keys into snake case, and so on.



Cookies work in a very similar way and although they can be extracted manually from the Cookies header, the framework offers a utility function, conveniently named Cookie, that does all the work in a way similar to Query, Path, and Header.


Forms (and files)

So far, we have only dealt with JSON data and that is alright, after all, it is the ubiquitous language of the web and our main vehicle for moving data back and forth. There are cases, however, that require a different data encoding, forms might be processed directly by your API, with data encoded as multipart/form-data or form-urlencoded.


Important Node: Notice that although we can have multiple Form parameters in a path operation, we cannot declare Body fields that we expect to be in JSON. The HTTP request will have the body encoded using only application/x-www-for,-urlencoded instead of application/json. This limitation is part of the HTTP protocol and has nothing todo with FastAPI itself.


The simplest way to cover both form cases, with and without including files for upload, is to start by installing python-multipart, a streaming multipart parser for Python. Stop your server and use pip to install it.

覆盖这两种表单情况(包括或不包括用于上传的文件)的最简单方法是从安装Python -multipart开始,这是一个用于Python的流多部分解析器。停止服务器并使用pip安装它。

pip install python-multipart

The Form function works similarly to the previously examined utility functions, but with the difference that it looks for form-encoded parameters. Let’s look at a simple example in which we wish to upload a car image and a couple of form fields, such as the brand and the model. I will use a photo that I found on Pexels (photo by Yogesh Yadav:

Form函数的工作方式类似于前面讨论的实用程序函数,但不同之处在于它查找表单编码的参数。让我们看一个简单的示例,在这个示例中,我们希望上传一个汽车图像和两个表单字段,比如品牌和型号。我将使用我在pixel上找到的一张照片(照片由Yogesh Yadav提供:。

from fastapi import FastAPI, Form, File, UploadFileapp = FastAPI()"/upload")
async def upload(file: UploadFile = File(...),brand: str = Form(...),model: str = Form(...),
):return {"brand": brand,"model": model,"file": file.filename,}if __name__ == '__main__':import

The preceding code handles the form parameters via the Form function and the uploaded file by using the UploadFile utility class.


The preceding code handles the form parameters via the Form function and the uploaded file by using the UploadFile utility class.


To save the image to a disk, we need to copy the buffer to an actual file on the disk. The following code achieves this.


import shutil
from fastapi import FastAPI, Form, File, UploadFileapp = FastAPI()"/upload")
async def upload(file: UploadFile = File(...),brand: str = Form(...),model: str = Form(...),
):# 保存图片with open("test.jpg", "wb") as f:shutil.copyfileobj(file.file, f)return {"brand": brand,"model": model,"file": file.filename,}if __name__ == '__main__':import

The open block opens a file on the disk using a specified filename and copies the FastAPI file that’s sent through the form. I have hardcoded the filename, do any new upload will simply overwirte the existing file, but you could use some randomly generated filename while using the UUID library, for example.


File uploading is an operation that you probably won’t be doing this way, file uploads can be handled by the Python async file library known as aifiles or as a background task, which is another feature of FastAPI. However, I wanted to provide a rather complete picture of how you can handle everyday web tasks with the framework.


FastAPI response customization

In the previous sections, we looked at numberous small examples of FastAPI requests, saw how we can reach every corner of the request, the path, the query string, the request body, headers, and cookies, and saw how to work with form encoded requests. Now, let’s take a closer look at FastAPI’s response objects. In all the cases that we have seen so far, we returned a Python dictionary that was then serialized into JSON correctly by FastAPI. The framework enables use, the developers, to customize the response in a very granular way, as we will see in the next few sections.


The first thing that you may want to change in an HTTP response is going to be the status code. You may also want to provide some meaningful errors when things do not go as planned. FastAPI conveniently raises classic Python exceptions when HTTP errors are present. FastAPI puts a lot of emphasis on using standar, compliant meaningful response codes that minimize the need to create custom payload messages. For instance, you don’t want to send a 200 OK status code for everything and then notify users of errors by using the payload, FastAPI encourages good practices.

您可能希望在HTTP响应中更改的第一件事是状态码。当事情没有按计划进行时,您可能还希望提供一些有意义的错误。当存在HTTP错误时,FastAPI可以方便地引发经典的Python异常。FastAPI非常强调使用标准的、兼容的、有意义的响应代码,从而最大限度地减少了创建自定义有效负载消息的需要。例如,您不希望为所有内容发送200 OK状态码,然后通过使用有效负载通知用户错误,FastAPI鼓励良好的实践。

Setting status codes

HTTP status codes indicate if an operation was successful or if there was an error. These codes also provide information about the type of operation, and they can be divided into several groups: infomational, successful, client errors, server errors, and so on. It isn’t necessary to memorize the status codes, although you probably know what a 404 or a 500 code is, unfortunately.


FastAPI makes it incredibly easy to set a status code, it is enough to just pass the desired status_code variable to the decorator. Here, we are using the 208 status code for a simple endpoint.


from fastapi import FastAPI, statusapp = FastAPI()@app.get("/", status_code=status.HTTP_208_ALREADY_REPORTED)
async def hello():return {"message": "Hello World"}if __name__ == '__main__':import

Testing the root route in httpie yields the following output.


http localhost:8000
HTTP/1.1 208 Already Reported
content-length: 25
content-type: application/json
date: Thu, 28 Mar 2024 01:14:43 GMT
server: uvicorn{"message": "Hello World"

Similarly, we can set status codes for the delete, update, or create operations.


FastAPI sets the 200 status by default if it doesn’t encounter exceptions, so it is up to us to set the correct codes for the various API operations, such as 204 No Content for deleteing, 201 for creating, and so on. It is a good practice that is particularly encouraged.

如果没有遇到异常,FastAPI默认设置200状态,因此由我们来为各种API操作设置正确的代码,例如用于删除的204 No Content,用于创建的201,等等。这是一种特别鼓励的良好做法。

Pydantic can be used for response modeling as well, we can limit or otherwise modify the fields that should appear in the response and perform similar checks that it ddoes for the request body by using the response_model argument.


HTTP errors

Errors are bound to happen, no matter how meticulously you design your backend, for example, users somehow find a way to send the wrong parameters to a query, the frontend sends the wrong request body, or the database goes offline (although that shouldn’t happen since we will be using MongoDB!), anything can happen. It is of paramount importance to detect these errors as soon as possible (this is a leitmotiv in FastAPI) and send clear and complete messages to the frontend, as well as the user. We can do this by raising exceptions.


FastAPI heavily relies on web standards and tries to enforce good practices in every facet of the development process, so it puts a lot of emphasis on using HTTP status codes. These codes provide a clear indication of the type of problem that has arisen, while the payload can be used to further clarify the cause of the problem.


FastAPI uses a Python exception, aptly called HTTPException, to raise HTTP errors. This class allows us to set a status code and set an error message.


Returning to our example of inserting new cars into the database, we could set a custom exception like this.


from fastapi import FastAPI, HTTPException, status
from pydantic import BaseModelclass InsertCar(BaseModel):brand: strmodel: stryear: intapp = FastAPI()"/cars")
async def insert_car(car: InsertCar):if car.year > 2022:raise HTTPException(status_code=status.HTTP_406_NOT_ACCEPTABLE,detail="The car doesn't exist yet!",)return {"message": car}if __name__ == '__main__':import

When trying to insert a car that hasn’t been built yet, the response is as follows.


http POST localhost:8000/cars brand="fiat" model="500L" year=2023
HTTP/1.1 406 Not Acceptable
content-length: 39
content-type: application/json
date: Thu, 28 Mar 2024 01:29:35 GMT
server: uvicorn{"detail": "The car doesn't exist yet!"

This is a pretty contrived example as I do not expect you to make custom exceptions for any possible problem that might arise, but I believe that this gives a goo idea of what is possible and the flexibility that FastAPI gives you.


We just had a pretty fast ride through the main features of FastAPI, with particular emphasis on ways to get data out of the request and how to set the response according to our needs. Now, let’s summarize this chapter.



TCP Socket通信CAPL代码演示

TCP通信过程分为三个部分: 建立连接:三次握手数据传输关闭连接:四次挥手这些都可以通过socket套接字接口来实现。 Client: variables {const dword INVALID_SOCKET = 0xFFFFFFFF;dword clientSocket = INVALID_SOCKET;char …


一.引言 某些CentOS安装后默认是没有部分Linux命令的,比如netstat和lsof: 一般情况下我们可以通过yum install安装这些命令。但是在CentOS无法访问公网的时候(比如CentOS服务器部署在学校、军工等无法访问外网的环境)&#xff0c…


答案:更多答案,请关注【电大搜题】微信公众号 答案:更多答案,请关注【电大搜题】微信公众号 答案:更多答案,请关注【电大搜题】微信公众号 互联网金融的本质是 A. 双边市场经济 B. 平台经济 C. 多边…


目录 前言 我所理解的服务器架构 什么是否部署架构 部署架构的职责 进程业务职责 网络链接及通讯方式 与客户端的连接方式 服务器之间连接关系 数据落地以及一致性 数据库的选择 数据访问三级缓存 数据分片 读写分离 分布式数据处理 负载均衡 热更新 配置更新 …

hadoop 高可用(HA)、HDFS HA、Yarn HA

目录 hadoop 高可用(HA) HDFS高可用 HDFS高可用架构 QJM 主备切换: Yarn高可用 hadoop 高可用(HA) HDFS高可用 HDFS高可用架构 QJM 主备切换: Yarn高可用

1,static 关键字.Java

目录 1.概述 2.定义格式和使用 2.1 静态变量及其访问 2.2 实例变量及其访问 2.3 静态方法及其访问 2.4 实例方法及其访问 3.小结 1.概述 static表示静态,是Java中的一个修饰符,可以修饰成员方法,成员变量。被static修饰后的&#xff…


一、LC介绍 土地覆盖(Land Cover,LC)是自然营造物和人工建筑物所覆盖的地表诸多要素的综合体。土地覆盖指地表所属的植被覆盖物(森林、草原、耕作植被等)或非植被覆盖物(冰雪、建筑物等)的具体类型,侧重描述地球表面的自然属性&a…


主动发现 结果 主动注册 结果 分布式监控 服务机:132 代理机:133 客户端:135 代理机 数据库赋权: 代理机配置 网页上配置代理 客户端配置 网页上配置主机 重启代理机服务 网页效果

【机器学习】数据探索(Data Exploration)---数据质量和数据特征分析

一、引言 在机器学习项目中,数据探索是至关重要的一步。它不仅是模型构建的基础,还是确保模型性能稳定、预测准确的关键。数据探索的过程中,数据质量和数据特征分析占据了核心地位。数据质量直接关系到模型能否从数据中提取有效信息&#xff…


C#多页面共用一个实例 案例&#xff1a; C#与硬件设备交互&#xff0c;交互类里面有打开设备、数据接发等1操作&#xff0c;在其他许多地方需要调用该设备兼顾各代码的耦合度 采用单例模式&#xff0c;eg.CAN设备&#xff1a; private CANClass(){}/// <summary>/// 获…

Apache ECharts-数据统计(详解、入门案例)

简介&#xff1a;Apache ECharts 是一款基于 Javascript 的数据可视化图表库&#xff0c;提供直观&#xff0c;生动&#xff0c;可交互&#xff0c;可个性化定制的数据可视化图表。 1、介绍 图 1.1 Apache ECharts 功能、运行环境 功能&#xff1a; ECharts&#xff…


&#x1f308;个人主页&#xff1a;会编程的果子君 &#x1f4ab;个人格言:“成为自己未来的主人~” 电流及参考方向 电流&#xff1a;带电粒子有规则的定向移动 电流强度&#xff1a;单位时间内通过导体横截面的电荷量&#xff0c;即&#xff1a;idq/dt 单位&#xff1a…


2013年认证杯SPSSPRO杯数学建模 C题 公路运输业对于国内生产总值的影响分析 原题再现&#xff1a; 交通运输作为国民经济的载体&#xff0c;沟通生产和消费&#xff0c;在经济发展中扮演着极其重要的角色。纵观几百年来交通运输与经济发展的相互关系&#xff0c;生产水平越高…


前言 今天是贪心算法的第一天&#xff0c;算法之路重新开始&#xff01; 内容 之前没了解过贪心算法。 什么是贪心 贪心的本质是选择每一阶段的局部最优&#xff0c;从而达到全局最优。难点就是如何通过局部最优&#xff0c;推出整体最优。 一、455.分发饼干 假设你是一…


参展企业介绍 温州源浩流体设备科技有限公司是一家集设计、开发、制造、销售、服务于一体的高科技企业&#xff0c;公司主要生产各种不锈钢阀门、管件、卫生级流体设备(卫生级换向阀,卫生级减压阀,卫生级罐底阀)等。现为温州市泵阀协会会员&#xff0c;ISO9000 2008版质量质量…


#define _CRT_SECURE_NO_WARNINGS #include<stdio.h> #include<stdlib.h> typedef int ElemType; typedef struct LinkNode {ElemType data;LinkNode* next; }LinkNode, * LinkList; //尾插法建立单链表 void creatLinkList(LinkList& L) {L (LinkNode*)mallo…

QT - 日志:qDebug/qInfo/qWarning/qCritical

篇一、日志打印函数 头文件&#xff1a; #include <QDebug> 代码&#xff1a;qDebug()<<"hello world!"; 其他打印级别&#xff1a; qInfo(): 普通信息 qDebug(): 调试信息 qWarning(): 警告信息 qCritical(): 严重错误 qFatal(): 致命错误 1. qDebug…


目录 用户定义原语 UDP定义 UDP状态表 状态表符号 组合UDP 电平敏感UDP 沿敏感时序UDP 参考《Verilog 编程艺术》魏家明著 用户定义原语 用户定义原语&#xff08;User-defined primitive&#xff0c;UDP&#xff09;是一种模拟硬件技术&#xff0c;可以通过设计新的原…


论文 Extended Feature Pyramid Network for Small Object Detection python3 D:/Project/EFPN-detectron2-master/tools/ --config-file configs/InstanceSegmentation/pointrend_rcnn_R_50_FPN_1x_coco.yaml --num-gpus 1 训练脚本 cfg 中的配置 先获取配置…


字典在转化为其他类型时&#xff0c;会出现是否舍弃value的操作&#xff0c;只有在转化为字符串的时候才不会舍弃value 注释的快捷键是ctrl/ 字符串无法与整数&#xff0c;浮点数&#xff0c;等用加号完成拼接 5不入&#xff1f;&#xff1f;&#xff1f; 还有一种格式化的方法…