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
Our application has three models, the ``StudentModel``, the
133
-
``UpdateStudentModel``, and the ``StudentCollection``.
134
149
135
150
Define the ``StudentModel`` class using the following code:
136
151
@@ -167,21 +182,13 @@ Define the ``StudentModel`` class using the following code:
167
182
},
168
183
)
169
184
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
+
````````````````````````
173
187
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``:
182
189
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
185
192
186
193
Define the ``UpdateStudentModel`` class using the following code:
187
194
@@ -209,12 +216,13 @@ Define the ``UpdateStudentModel`` class using the following code:
209
216
},
210
217
)
211
218
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
+
```````````````````````
216
221
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.
218
226
219
227
Define the ``StudentCollection`` class using the following code:
220
228
@@ -232,7 +240,7 @@ Define the ``StudentCollection`` class using the following code:
232
240
Create Your Application Routes
233
241
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
234
242
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>`__:
236
244
237
245
.. list-table::
238
246
:header-rows: 1
@@ -262,6 +270,21 @@ Our application has five routes:
262
270
263
271
.. step:: Create Your Student Route
264
272
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
+
265
288
.. code-block:: python
266
289
267
290
@app.post(
@@ -285,15 +308,12 @@ Our application has five routes:
285
308
)
286
309
return created_student
287
310
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
-
294
311
.. step:: Create Your Read Routes
295
312
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:
297
317
298
318
.. code-block:: python
299
319
@@ -311,10 +331,21 @@ Our application has five routes:
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:
318
349
319
350
.. code-block:: python
320
351
@@ -335,11 +366,23 @@ Our application has five routes:
335
366
336
367
raise HTTPException(status_code=404, detail="Student {id} not found")
337
368
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
339
370
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
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.
341
382
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:
343
386
344
387
.. code-block:: python
345
388
@@ -377,12 +420,6 @@ Our application has five routes:
377
420
378
421
raise HTTPException(status_code=404, detail=f"Student {id} not found")
379
422
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.
0 commit comments