Skip to content

Commit aac1def

Browse files
committed
steps
1 parent 0022b1c commit aac1def

File tree

1 file changed

+105
-102
lines changed

1 file changed

+105
-102
lines changed

source/integrations/fastapi-integration.txt

Lines changed: 105 additions & 102 deletions
Original file line numberDiff line numberDiff line change
@@ -56,95 +56,128 @@ Prerequisites
5656
<https://docs.atlas.mongodb.com/getting-started/>`__ guide to create your
5757
account and MongoDB cluster.
5858

59-
.. step:: Set-up
59+
.. procedure::
60+
:style: connected
6061

61-
.. step:: Clone the example code from the `mongodb-with-fastapi repository <https://github.com/mongodb-developer/mongodb-with-fastapi>`__:
62+
.. step:: Set-up
6263

63-
.. code-block:: shell
64+
.. step:: Clone the example code from the `mongodb-with-fastapi repository <https://github.com/mongodb-developer/mongodb-with-fastapi>`__:
6465

65-
git clone [email protected]:mongodb-developer/mongodb-with-fastapi.git
66+
.. code-block:: shell
6667

67-
.. step:: Install the required dependencies listed in the ``requirements.txt`` file:
68+
git clone [email protected]:mongodb-developer/mongodb-with-fastapi.git
6869

69-
.. tip:: Use a Virtual environment
70+
.. step:: Install the required dependencies listed in the ``requirements.txt`` file:
7071

71-
Installing your Python dependencies in a `virtualenv
72-
<https://docs.python.org/3/tutorial/venv.html>`__ with allow for versions
73-
of the libraries to be install for individual projects. Before running
74-
pip, ensure your ``virtualenv`` is active.
72+
.. tip:: Use a Virtual environment
7573

76-
.. code-block:: shell
74+
Installing your Python dependencies in a `virtualenv
75+
<https://docs.python.org/3/tutorial/venv.html>`__ with allow for versions
76+
of the libraries to be install for individual projects. Before running
77+
pip, ensure your ``virtualenv`` is active.
7778

78-
cd mongodb-with-fastapi
79-
pip install -r requirements.txt
79+
.. code-block:: shell
8080

81-
It may take a few moments to download and install your dependencies.
81+
cd mongodb-with-fastapi
82+
pip install -r requirements.txt
8283

83-
.. step:: Create an environment variable for your MongoDB connection string:
84+
It may take a few moments to download and install your dependencies.
8485

85-
.. code-block:: shell
86+
.. step:: Create an environment variable for your MongoDB connection string:
8687

87-
export MONGODB_URL="mongodb+srv://<username>:<password>@<url>/<db>?retryWrites=true&w=majority"
88+
.. code-block:: shell
8889

89-
.. tip:: Reset Environment Variables
90+
export MONGODB_URL="mongodb+srv://<username>:<password>@<url>/<db>?retryWrites=true&w=majority"
9091

91-
Anytime you start a new terminal session, you will need to reset this
92-
environment variable. You can use `direnv <https://direnv.net/>`__ to make
93-
this process easier.
92+
.. tip:: Reset Environment Variables
9493

95-
.. step:: Start your FastAPI server:
94+
Anytime you start a new terminal session, you will need to reset this
95+
environment variable. You can use `direnv <https://direnv.net/>`__ to make
96+
this process easier.
9697

97-
.. code-block:: shell
98+
.. step:: Start your FastAPI server:
9899

99-
uvicorn app:app --reload
100+
.. code-block:: shell
100101

101-
.. image:: /includes/integrations/fastapi-terminal.png
102-
:alt: Screenshot of terminal running FastAPI
102+
uvicorn app:app --reload
103103

104-
Once the application has started, you can view it in your browser at http://127.0.0.1:8000/docs.
104+
.. image:: /includes/integrations/fastapi-terminal.png
105+
:alt: Screenshot of terminal running FastAPI
105106

106-
.. image:: /includes/integrations/fastapi-browser.png
107-
:alt: Screenshot of browser and swagger UI
107+
Once the application has started, you can view it in your browser at http://127.0.0.1:8000/docs.
108108

109-
.. step:: Create Your Application
109+
.. image:: /includes/integrations/fastapi-browser.png
110+
:alt: Screenshot of browser and swagger UI
110111

111-
All the code for the example application is stored in ``app.py``.
112+
.. step:: Create Your Application
112113

113-
Connect to your MongoDB Atlas cluster using the asynchronous `Pymongo Driver <https://www.mongodb.com/docs/languages/python/pymongo-driver/current>`__, then specify the database named ``college``:
114+
All the code for the example application is stored in ``app.py``.
114115

115-
.. code-block:: python
116+
Connect to your MongoDB Atlas cluster using the asynchronous `Pymongo Driver <https://www.mongodb.com/docs/languages/python/pymongo-driver/current>`__, then specify the database named ``college``:
116117

117-
client = AsyncMongoClient(MONGODB_URL, server_api=pymongo.server_api.ServerApi(version="1", strict=True, deprecation_errors=True))
118-
db = client.get_database("college")
119-
student_collection = db.get_collection("students")
118+
.. code-block:: python
120119

121-
.. step:: Define Your Database Models
122-
123-
Our application has three models, the ``StudentModel``, the ``UpdateStudentModel``, and the ``StudentCollection``.
120+
client = AsyncMongoClient(MONGODB_URL, server_api=pymongo.server_api.ServerApi(version="1", strict=True, deprecation_errors=True))
121+
db = client.get_database("college")
122+
student_collection = db.get_collection("students")
123+
124+
.. step:: Define Your Database Models
125+
126+
Our application has three models, the ``StudentModel``, the ``UpdateStudentModel``, and the ``StudentCollection``.
127+
128+
.. code-block:: python
129+
130+
# Represents an ObjectId field in the database.
131+
# It will be represented as a `str` on the model so that it can be
132+
serialized to JSON.
133+
PyObjectId = Annotated[str, BeforeValidator(str)]
134+
135+
class StudentModel(BaseModel):
136+
"""
137+
Container for a single student record.
138+
"""
139+
140+
# The primary key for the StudentModel, stored as a `str` on the instance.
141+
# This will be aliased to ``_id`` when sent to MongoDB,
142+
# but provided as ``id`` in the API requests and responses.
143+
id: Optional[PyObjectId] = Field(alias="_id", default=None)
144+
name: str = Field(...)
145+
email: EmailStr = Field(...)
146+
course: str = Field(...)
147+
gpa: float = Field(..., le=4.0)
148+
model_config = ConfigDict(
149+
populate_by_name=True,
150+
arbitrary_types_allowed=True,
151+
json_schema_extra={
152+
"example": {
153+
"name": "Jane Doe",
154+
"email": "[email protected]",
155+
"course": "Experiments, Science, and Fashion in Nanophotonics",
156+
"gpa": 3.0,
157+
}
158+
},
159+
)
160+
161+
This is the primary model we use as the `response model <https://fastapi.tiangolo.com/tutorial/response-model/>`__ for the majority of our endpoints.
162+
163+
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``
124164

125-
.. code-block:: python
165+
We set this ``id`` value automatically to ``None``, so you do not need to supply it when creating a new student.
126166

127-
# Represents an ObjectId field in the database.
128-
# It will be represented as a `str` on the model so that it can be
129-
serialized to JSON.
130-
PyObjectId = Annotated[str, BeforeValidator(str)]
167+
.. code-block:: python
131168

132-
class StudentModel(BaseModel):
169+
class UpdateStudentModel(BaseModel):
133170
"""
134-
Container for a single student record.
171+
A set of optional updates to be made to a document in the database.
135172
"""
136173

137-
# The primary key for the StudentModel, stored as a `str` on the instance.
138-
# This will be aliased to ``_id`` when sent to MongoDB,
139-
# but provided as ``id`` in the API requests and responses.
140-
id: Optional[PyObjectId] = Field(alias="_id", default=None)
141-
name: str = Field(...)
142-
email: EmailStr = Field(...)
143-
course: str = Field(...)
144-
gpa: float = Field(..., le=4.0)
174+
name: Optional[str] = None
175+
email: Optional[EmailStr] = None
176+
course: Optional[str] = None
177+
gpa: Optional[float] = None
145178
model_config = ConfigDict(
146-
populate_by_name=True,
147179
arbitrary_types_allowed=True,
180+
json_encoders={ObjectId: str},
148181
json_schema_extra={
149182
"example": {
150183
"name": "Jane Doe",
@@ -155,53 +188,23 @@ Prerequisites
155188
},
156189
)
157190

158-
This is the primary model we use as the `response model <https://fastapi.tiangolo.com/tutorial/response-model/>`__ for the majority of our endpoints.
159-
160-
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``
161-
162-
We set this ``id`` value automatically to ``None``, so you do not need to supply it when creating a new student.
163-
164-
.. code-block:: python
165-
166-
class UpdateStudentModel(BaseModel):
167-
"""
168-
A set of optional updates to be made to a document in the database.
169-
"""
170-
171-
name: Optional[str] = None
172-
email: Optional[EmailStr] = None
173-
course: Optional[str] = None
174-
gpa: Optional[float] = None
175-
model_config = ConfigDict(
176-
arbitrary_types_allowed=True,
177-
json_encoders={ObjectId: str},
178-
json_schema_extra={
179-
"example": {
180-
"name": "Jane Doe",
181-
"email": "[email protected]",
182-
"course": "Experiments, Science, and Fashion in Nanophotonics",
183-
"gpa": 3.0,
184-
}
185-
},
186-
)
187-
188-
The ``UpdateStudentModel`` has two key differences from the ``StudentModel``:
189-
190-
- It does not have an ``id`` attribute as this cannot be modified.
191-
- All fields are optional, so you only need to supply the fields you wish to update.
192-
193-
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.
194-
195-
.. code-block:: python
196-
197-
class StudentCollection(BaseModel):
198-
"""
199-
A container holding a list of `StudentModel` instances.
200-
201-
This exists because providing a top-level array in a JSON response can be a `vulnerability <https://haacked.com/archive/2009/06/25/json-hijacking.aspx/>`__
202-
"""
203-
204-
students: List[StudentModel]
191+
The ``UpdateStudentModel`` has two key differences from the ``StudentModel``:
192+
193+
- It does not have an ``id`` attribute as this cannot be modified.
194+
- All fields are optional, so you only need to supply the fields you wish to update.
195+
196+
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.
197+
198+
.. code-block:: python
199+
200+
class StudentCollection(BaseModel):
201+
"""
202+
A container holding a list of `StudentModel` instances.
203+
204+
This exists because providing a top-level array in a JSON response can be a `vulnerability <https://haacked.com/archive/2009/06/25/json-hijacking.aspx/>`__
205+
"""
206+
207+
students: List[StudentModel]
205208

206209
Application Routes
207210
~~~~~~~~~~~~~~~~~~

0 commit comments

Comments
 (0)