Skip to content

Commit 6e29536

Browse files
committed
restructure
1 parent b634694 commit 6e29536

File tree

1 file changed

+79
-42
lines changed

1 file changed

+79
-42
lines changed

source/integrations/fastapi-integration.txt

Lines changed: 79 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,24 @@ method and the ``MONGODB_URL`` environment variable, then specify the database n
117117

118118
Define Your Database Models
119119
~~~~~~~~~~~~~~~~~~~~~~~~~~~
120+
121+
Our application has three models, the ``StudentModel``, the
122+
``UpdateStudentModel``, and the ``StudentCollection``.
123+
124+
StudentModel Class
125+
``````````````````
126+
127+
This is the primary model we use as the `response model
128+
<https://fastapi.tiangolo.com/tutorial/response-model/>`__ for the majority of
129+
our endpoints.
130+
131+
MongoDB uses ``_id`` as the default UUID on its documents. However, `pydantic
132+
<https://pydantic-docs.helpmanual.io/>`__, the data validation
133+
framework used by FastAPI, leading underscores indicate that a variable is private, meaning you
134+
cannot assign it a value. Therefore, we name the field ``id`` but give it an
135+
alias of ``_id`` and set ``populate_by_name`` to ``True`` in the model's
136+
``model_config``. We also set this ``id`` value automatically to ``None``, so
137+
that can create a new student with out specifying it.
120138

121139
.. note:: BSON to JSON Mapping
122140

@@ -128,9 +146,6 @@ Define Your Database Models
128146

129147
For more information about how BSON compares to JSON, see this `JSON and BSON
130148
<https://www.mongodb.com/json-and-bson>`__ MongoDB article.
131-
132-
Our application has three models, the ``StudentModel``, the
133-
``UpdateStudentModel``, and the ``StudentCollection``.
134149

135150
Define the ``StudentModel`` class using the following code:
136151

@@ -167,21 +182,13 @@ Define the ``StudentModel`` class using the following code:
167182
},
168183
)
169184

170-
This is the primary model we use as the `response model
171-
<https://fastapi.tiangolo.com/tutorial/response-model/>`__ for the majority of
172-
our endpoints.
185+
UpdateStudentModel Class
186+
````````````````````````
173187

174-
I want to draw attention to the ``id`` field on this model. MongoDB uses
175-
``_id``, but in Python, underscores at the start of attributes have special
176-
meaning. If you have an attribute on your model that starts with an underscore,
177-
`pydantic <https://pydantic-docs.helpmanual.io/>`__—the data validation
178-
framework used by FastAPI—will assume that it is a private variable, meaning you
179-
cannot assign it a value. To get around this, we name the field
180-
``id`` but give it an alias of ``_id``. You must also set
181-
``populate_by_name`` to ``True`` in the model's ``model_config``.
188+
The ``UpdateStudentModel`` has two key differences from the ``StudentModel``:
182189

183-
We set this ``id`` value automatically to ``None``, so that can create a new
184-
student with out specifying it.
190+
- It does not have an ``id`` attribute, as this cannot be modified
191+
- All fields are optional, so you can supply only the fields you want to update
185192

186193
Define the ``UpdateStudentModel`` class using the following code:
187194

@@ -209,12 +216,13 @@ Define the ``UpdateStudentModel`` class using the following code:
209216
},
210217
)
211218

212-
The ``UpdateStudentModel`` has two key differences from the ``StudentModel``:
213-
214-
- It does not have an ``id`` attribute as this cannot be modified.
215-
- All fields are optional, so can supply only the fields you want to update.
219+
StudentCollection Class
220+
```````````````````````
216221

217-
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.
222+
The ``StudentCollection`` class is defined to encapsulate a list of
223+
``StudentModel`` instances. In theory, the endpoint could return a top-level
224+
list of ``StudentModel`` objects, but there are some vulnerabilities associated with
225+
returning JSON responses with top-level lists.
218226

219227
Define the ``StudentCollection`` class using the following code:
220228

@@ -232,7 +240,7 @@ Define the ``StudentCollection`` class using the following code:
232240
Create Your Application Routes
233241
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
234242

235-
Our application has five routes:
243+
Our application has five routes, as shown in the `running application homepage <http://127.0.0.1:8000/docs>`__:
236244

237245
.. list-table::
238246
:header-rows: 1
@@ -262,6 +270,21 @@ Our application has five routes:
262270

263271
.. step:: Create Your Student Route
264272

273+
The ``create_student`` route receives the new student data as a JSON string
274+
in a ``POST`` request. We must decode this JSON request body into a Python
275+
dictionary before passing it to our MongoDB client.
276+
277+
The ``insert_one`` method response includes the ``_id`` of the newly created
278+
student (provided as ``id`` because this endpoint specifies
279+
``response_model_by_alias=False`` in the ``post`` decorator call. After we
280+
insert the student into our collection, we use the ``inserted_id`` to find
281+
the correct document and return this in our ``JSONResponse``.
282+
283+
FastAPI returns an HTTP ``200`` status code by default; but in this
284+
instance, a ``201`` created is more appropriate.
285+
286+
Define the ``create_student`` route using the following code:
287+
265288
.. code-block:: python
266289

267290
@app.post(
@@ -285,15 +308,12 @@ Our application has five routes:
285308
)
286309
return created_student
287310

288-
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.
289-
290-
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``.
291-
292-
FastAPI returns an HTTP ``200`` status code by default; but in this instance, a ``201`` created is more appropriate.
293-
294311
.. step:: Create Your Read Routes
295312

296-
The application has two read routes: one for viewing all students, and one for viewing an individual student.
313+
The application has two read routes: one for viewing all students, and one
314+
for viewing an individual student specified by their ``id``.
315+
316+
Define the ``list_students`` route to view all students using the following code:
297317

298318
.. code-block:: python
299319

@@ -311,10 +331,21 @@ Our application has five routes:
311331
"""
312332
return StudentCollection(students=await student_collection.find().to_list())
313333

314-
This example uses the ``to_list()`` method; but in a real application, we
315-
recommend using the `skip and limit parameters
316-
<https://pymongo.readthedocs.io/en/stable/api/pymongo/asynchronous/collection.html#pymongo.asynchronous.collection.AsyncCollection.find>`__
317-
in ``find`` to paginate your results.
334+
.. note:: Results Pagination
335+
336+
This example uses the ``to_list()`` method; but in a real application, we
337+
recommend using the `skip and limit parameters
338+
<https://pymongo.readthedocs.io/en/stable/api/pymongo/asynchronous/collection.html#pymongo.asynchronous.collection.AsyncCollection.find>`__
339+
in ``find`` to paginate your results.
340+
341+
The student detail route has a path parameter of ``id``, which FastAPI
342+
passes as an argument to the ``show_student`` function. We use the ``id`` to
343+
attempt to find the corresponding student in the database.
344+
345+
If a document with the specified ``id`` does not exist, we raise an
346+
``HTTPException`` with a status of ``404``.
347+
348+
Define the ``show_students`` route to view an individual using the following code:
318349

319350
.. code-block:: python
320351

@@ -335,11 +366,23 @@ Our application has five routes:
335366

336367
raise HTTPException(status_code=404, detail="Student {id} not found")
337368

338-
The student detail route has a path parameter of ``id``, which FastAPI passes as an argument to the ``show_student`` function. We use the ``id`` to attempt to find the corresponding student in the database. The conditional in this section is using an `assignment expression <https://www.python.org/dev/peps/pep-0572/>`__, an addition to Python 3.8 and often referred to by the cute sobriquet "walrus operator."
369+
.. step:: Create Your Update Route
339370

340-
If a document with the specified ``_id`` does not exist, we raise an ``HTTPException`` with a status of ``404``.
371+
The ``update_student`` route is like a combination of the ``create_student``
372+
and the ``show_student`` routes. It receives the ``id`` of the student to
373+
update, and the new data in the JSON body.
374+
375+
We don't want to update any fields with empty values, so we iterate over all the parameters in the received
376+
data and only modify the defined parameters. We use `find_one_and_update
377+
<https://pymongo.readthedocs.io/en/stable/api/pymongo/asynchronous/collection.html#pymongo.asynchronous.collection.AsyncCollection.find_one_and_update>`__
378+
to `$set <https://docs.mongodb.com/manual/reference/operator/update/set/>`__
379+
the new values, and then return the updated document.
380+
381+
If there are no fields to update, then we return the original ``StudentModel`` document.
341382

342-
.. step:: Create Your Update Route
383+
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.
384+
385+
Define the ``update_student`` route to view an individual using the following code:
343386

344387
.. code-block:: python
345388

@@ -377,12 +420,6 @@ Our application has five routes:
377420

378421
raise HTTPException(status_code=404, detail=f"Student {id} not found")
379422

380-
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.
381-
382-
If there 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.
383-
384-
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.
385-
386423
.. step:: Create Your Delete Route
387424

388425
.. code-block:: python

0 commit comments

Comments
 (0)