You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: source/integrations/fastapi-integration.txt
+31-15Lines changed: 31 additions & 15 deletions
Original file line number
Diff line number
Diff line change
@@ -74,7 +74,7 @@ Set-up
74
74
75
75
.. tip:: Reset Environment Variables
76
76
77
-
Anytime you start a new terminal session, you will need to reset this
77
+
Anytime you start a new terminal session, you will must reset this
78
78
environment variable. You can use `direnv <https://direnv.net/>`__ to make
79
79
this process easier.
80
80
@@ -110,9 +110,9 @@ Define Your Database Models
110
110
111
111
.. note:: BSON to JSON Mapping
112
112
113
-
FastAPI encodes and decodes data as JSON strings, which do not support all of the
113
+
FastAPI encodes and decodes data as JSON strings, which do not support all the
114
114
data types that MongoDB's BSON data type can store. BSON has support for
115
-
additional non-JSON-native data types, including ``ObjectId`` which is used for
115
+
more non-JSON-native data types, including ``ObjectId`` which is used for
116
116
the default UUID attribute, ``_id``. Because of this, you must convert
117
117
``ObjectId`` objects to strings before storing them in the ``_id`` field.
118
118
@@ -156,9 +156,17 @@ Our application has three models, the ``StudentModel``, the ``UpdateStudentModel
156
156
157
157
This is the primary model we use as the `response model <https://fastapi.tiangolo.com/tutorial/response-model/>`__ for the majority of our endpoints.
158
158
159
-
I want to draw attention to the ``id`` field on this model. MongoDB uses ``_id``, but in Python, underscores at the start of attributes have special meaning. If you have an attribute on your model that starts with an underscore, `pydantic <https://pydantic-docs.helpmanual.io/>`__—the data validation framework used by FastAPI—will assume that it is a private variable, meaning you will not be able to assign it a value! To get around this, we name the field ``id`` but give it an alias of ``_id``. You also need to set ``populate_by_name`` to ``True`` in the model's ``model_config``
159
+
I want to draw attention to the ``id`` field on this model. MongoDB uses
160
+
``_id``, but in Python, underscores at the start of attributes have special
161
+
meaning. If you have an attribute on your model that starts with an underscore,
162
+
`pydantic <https://pydantic-docs.helpmanual.io/>`__—the data validation
163
+
framework used by FastAPI—will assume that it is a private variable, meaning you
164
+
cannot assign it a value. To get around this, we name the field
165
+
``id`` but give it an alias of ``_id``. You must also set
166
+
``populate_by_name`` to ``True`` in the model's ``model_config``.
160
167
161
-
We set this ``id`` value automatically to ``None``, so you do not need to supply it when creating a new student.
168
+
We set this ``id`` value automatically to ``None``, so that you don't need to
169
+
specify it when creating a new student.
162
170
163
171
.. code-block:: python
164
172
@@ -187,7 +195,7 @@ We set this ``id`` value automatically to ``None``, so you do not need to supply
187
195
The ``UpdateStudentModel`` has two key differences from the ``StudentModel``:
188
196
189
197
- It does not have an ``id`` attribute as this cannot be modified.
190
-
- All fields are optional, so you only need to supply the fields you wish to update.
198
+
- All fields are optional, so you only need to supply the fields you want to update.
191
199
192
200
Finally, ``StudentCollection`` is defined to encapsulate a list of ``StudentModel`` instances. In theory, the endpoint could return a top-level list of StudentModels, but there are some vulnerabilities associated with returning JSON responses with top-level lists.
193
201
@@ -258,7 +266,7 @@ Our application has five routes:
258
266
)
259
267
return created_student
260
268
261
-
The ``create_student`` route receives the new student data as a JSON string in a ``POST`` request. We have to decode this JSON request body into a Python dictionary before passing it to our MongoDB client.
269
+
The ``create_student`` route receives the new student data as a JSON string in a ``POST`` request. We must decode this JSON request body into a Python dictionary before passing it to our MongoDB client.
262
270
263
271
The ``insert_one`` method response includes the ``_id`` of the newly created student (provided as ``id`` because this endpoint specifies ``response_model_by_alias=False`` in the ``post`` decorator call. After we insert the student into our collection, we use the ``inserted_id`` to find the correct document and return this in our ``JSONResponse``.
264
272
@@ -278,13 +286,16 @@ Our application has five routes:
278
286
)
279
287
async def list_students():
280
288
"""
281
-
List all of the student data in the database.
289
+
List all the student data in the database.
282
290
283
291
The response is unpaginated and limited to 1000 results.
Motor's ``to_list`` method requires a max document count argument. For this example, I have hardcoded it to ``1000``; but in a real application, you would use the `skip and limit parameters <https://pymongo.readthedocs.io/en/3.11.0/api/pymongo/collection.html#pymongo.collection.Collection.find>`__ in ``find`` to paginate your results.
295
+
This example uses the ``to_list()`` method; but in a real application, we
@@ -341,17 +352,17 @@ Our application has five routes:
341
352
else:
342
353
raise HTTPException(status_code=404, detail=f"Student {id} not found")
343
354
344
-
# The update is empty, but we should still return the matching document:
355
+
# The update is empty, so return the matching document:
345
356
if (existing_student := await student_collection.find_one({"_id": id})) is not None:
346
357
return existing_student
347
358
348
359
raise HTTPException(status_code=404, detail=f"Student {id} not found")
349
360
350
-
The ``update_student`` route is like a combination of the ``create_student`` and the ``show_student`` routes. It receives the ``id`` of the document to update as well as the new data in the JSON body. We don't want to update any fields with empty values; so, first of all, we iterate over all the items in the received dictionary and only add the items that have a value to our new document.
361
+
The ``update_student`` route is like a combination of the ``create_student`` and the ``show_student`` routes. It receives the ``id`` of the document to update, and the new data in the JSON body. We don't want to update any fields with empty values, so we iterate over all the items in the received dictionary and only add the items that have a value to our new document.
351
362
352
-
If, after we remove the empty values, there are no fields left to update, we instead look for an existing record that matches the ``id`` and return that unaltered. However, if there are values to update, we use `find_one_and_update <https://motor.readthedocs.io/en/stable/api-asyncio/asyncio_motor_collection.html#motor.motor_asyncio.AsyncIOMotorCollection.find_one_and_update>`__ to `$set <https://docs.mongodb.com/manual/reference/operator/update/set/>`__ the new values, and then return the updated document.
363
+
Ifthere are no fields left to update, we look for an existing record that matches the ``id`` and return that unaltered. However, if there are values to update, we use `find_one_and_update <https://pymongo.readthedocs.io/en/stable/api/pymongo/asynchronous/collection.html#pymongo.asynchronous.collection.AsyncCollection.find_one_and_update>`__ to `$set <https://docs.mongodb.com/manual/reference/operator/update/set/>`__ the new values, and then return the updated document.
353
364
354
-
If we get to the end of the function and we have not been able to find a matching document to update or return, then we raise a ``404`` error again.
365
+
If we get to the end of the function and we have not been able to find a matching document to update or return, then we raise a ``404`` error.
355
366
356
367
.. step:: Create Your Delete Route
357
368
@@ -369,7 +380,12 @@ Our application has five routes:
369
380
370
381
raise HTTPException(status_code=404, detail=f"Student {id} not found")
371
382
372
-
Our final route is ``delete_student``. Again, because this is acting upon a single document, we have to supply an ``id`` in the URL. If we find a matching document and successfully delete it, then we return an HTTP status of ``204`` or "No Content." In this case, we do not return a document as we've already deleted it! However, if we cannot find a student with the specified ``id``, then instead we return a ``404``.
383
+
Our final route is ``delete_student``. Because this is acting on a single
384
+
document, we must supply an ``id`` in the URL. If we find a matching
385
+
document and successfully delete it, then we return an HTTP status of
386
+
``204`` or "No Content." In this case, we do not return a document since
387
+
we previously deleted it. However, if we cannot find a student with the specified ``id``, then
0 commit comments