The Updating Records
section shows how to use the :py~pynautobot.core.response.Record.update
method to update fields <Terminology>
. Another way to accomplish update operations is to update the :py~pynautobot.core.response.Record
object's attributes, and call the :py~pynautobot.core.response.Record.save
method. The main difference with this approach is that changes are not synced to Nautobot until the :py~pynautobot.core.response.Record.save
method is called.
The below example will:
- make updates to a Device
- show that updates haven't synced to Nautobot before saving.
- show that updates are synced after calling the save method.
>>> device = nautobot.dcim.devices.get(name="hq-access-03")
>>> # Show that device is active
>>> device.status
Active
>>> # Update status and name fields
>>> device.comments = "removed from service"
>>> device.status = "decommissioned"
>>> # Show that changes haven't been synced
>>> tmp_device = nautobot.dcim.devices.get(name="hq-access-03")
>>> tmp_device.status
Active
>>> # Save updates and show that changes have been synced
>>> device.save()
>>> updated_device = nautobot.dcim.devices.get(name="hq-access-03")
>>> updated_device.comments
'removed from service'
>>> updated_device.status
Decommissioned
Since the Update operation behaves similarly to the Create operation, performing an update can have the some of the same errors. The two examples below are the same issues outlined in The Data Sent Does Not Adhere to the Database Schema
.
The first example uses the :py~pynautobot.core.response.Record.update
method and returns an exception immediately. The second example modifies the objects position
attribute, and the exception is not raised until the :py~pynautobot.core.response.Record.save
method is called.
>>> # Get a device record
>>> hq_access_5 = devices.get(name="hq-access-05")
>>> # Attempt to update position with an invalid type
>>> hq_access_5.update({"postition": "high"})
Traceback (most recent call last):
...
pynautobot.core.query.RequestError:
The request failed with code 400 Bad Request:
{
'position': ['A valid integer is required.']
}
>>> # Get a device record
>>> hq_access_5 = devices.get(name="hq-access-05")
>>> # Attempt to provide invalid rack unit for position
>>> hq_access_5.position = 100
>>> # The exception is only raised when save() is called
>>> hq_access_5.save()
Traceback (most recent call last):
...
pynautobot.core.query.RequestError:
The request failed with code 400 Bad Request:
{
'position': [
'U100 is already occupied or does not have sufficient space' \
'to accommodate this device type: c9300-48 (1U)'
]
}
One important feature of the Nautobot API is that updates are Atomic. If any of the fields being updated causes an error, then all updates are aborted. The following example updates the face
and position
fields. An error is raised for the position
field, and fetching the object from Nautobot shows that face
has also been left unchanged.
>>> # Get a device record
>>> hq_access_5 = devices.get(name="hq-access-05")
>>> # Set the face attribute
>>> hq_access_5.face = "front"
>>> # Attempt to provide invalid rack unit for position
>>> hq_access_5.position = 100
>>> # An exception is raised
>>> hq_access_5.save()
Traceback (most recent call last):
...
pynautobot.core.query.RequestError:
The request failed with code 400 Bad Request:
{
'position': [
'U100 is already occupied or does not have sufficient space' \
'to accommodate this device type: c9300-48 (1U)'
]
}
>>> # Show that the object's face field has not changed
>>> tmp_hq_access_5 = devices.get(name="hq-access-05")
>>> tmp_hq_access_5.face is None
True
>>> # Fix the position field and retrigger update
>>> hq_access_5.position = 42
>>> hq_access_5.save()
True
>>> # Show that updates have taken affect
>>> tmp_hq_access_5 = devices.get(name="hq-access-05")
>>> tmp_hq_access_5.face
Front
>>> tmp_hq_access_5.position
42
In some cases it may not be necessary to load an object to update it, for example if the ID and updated fields are known, the call HTTP PATCH may be made without performing an :py~pynautobot.core.endpoint.Endpoint.get
first.
In this case, the :py~pynautobot.core.endpoint.Endpoint.update
method may be used to directly submit a PATCH to the Nautobot REST API. Using this reduces the number of API calls. It can be particularly useful as a way to update data fetched from the GraphQL API.
The examples updates a Device record, however this can apply to other API :py~pynautobot.core.endpoint.Endpoint
types.
import os
from pynautobot import api
url = os.environ["NAUTOBOT_URL"]
token = os.environ["NAUTOBOT_TOKEN"]
nautobot = api(url=url, token=token)
# Update status and name fields
result = nautobot.dcim.devices.update(
id="491d799a-2b4d-41fc-80e1-7c5cbb5b71b6",
data={
"comments": "removed from service",
"status": "decommissioned",
},
)
print(result) # will output True if successful
References:
Gathering Data from GraphQL Endpoint