NetBox includes a Python shell within which objects can be directly queried, created, modified, and deleted. To enter the shell, run the following command:
This will launch a customized version of [the built-in Django shell](https://docs.djangoproject.com/en/stable/ref/django-admin/#shell) with all relevant NetBox models pre-loaded. (If desired, the stock Django shell is also available by executing `./manage.py shell`.)
Objects are retrieved by forming a [Django queryset](https://docs.djangoproject.com/en/stable/topics/db/queries/#retrieving-objects). The base queryset for an object takes the form `<model>.objects.all()`, which will return a (truncated) list of all objects of that type.
<QuerySet[<Device:TestDevice1>, <Device:TestDevice2>, <Device:TestDevice3>, <Device:TestDevice4>, <Device:TestDevice5>, '...(remaining elements truncated)...']>
```
Use a `for` loop to cycle through all objects in the list:
```
>>> for device in Device.objects.all():
... print(device.name, device.device_type)
...
(u'TestDevice1', <DeviceType:PacketThingy9000>)
(u'TestDevice2', <DeviceType:PacketThingy9000>)
(u'TestDevice3', <DeviceType:PacketThingy9000>)
(u'TestDevice4', <DeviceType:PacketThingy9000>)
(u'TestDevice5', <DeviceType:PacketThingy9000>)
...
```
To count all objects matching the query, replace `all()` with `count()`:
```
>>> Device.objects.count()
1274
```
To retrieve a particular object (typically by its primary key or other unique field), use `get()`:
```
>>> Site.objects.get(pk=7)
<Site:TestLab>
```
### Filtering Querysets
In most cases, you want to retrieve only a specific subset of objects. To filter a queryset, replace `all()` with `filter()` and pass one or more keyword arguments. For example:
```
>>> Device.objects.filter(status=STATUS_ACTIVE)
<QuerySet[<Device:TestDevice1>, <Device:TestDevice2>, <Device:TestDevice3>, <Device:TestDevice8>, <Device:TestDevice9>, '...(remaining elements truncated)...']>
```
Querysets support slicing to return a specific range of objects.
Relationships with other models can be traversed by concatenating field names with a double-underscore. For example, the following will return all devices assigned to the tenant named "Pied Piper."
While the above query is functional, it is very inefficient. There are ways to optimize such requests, however they are out of the scope of this document. For more information, see the [Django queryset method reference](https://docs.djangoproject.com/en/stable/ref/models/querysets/) documentation.
The examples above are intended only to provide a cursory introduction to queryset filtering. For an exhaustive list of the available filters, please consult the [Django queryset API docs](https://docs.djangoproject.com/en/stable/ref/models/querysets/).
To modify an object, retrieve it, update the desired field(s), and call `save()` again.
```
>>> vlan = VLAN.objects.get(pk=1280)
>>> vlan.name
u'MyNewVLAN'
>>> vlan.name = 'BetterName'
>>> vlan.save()
>>> VLAN.objects.get(pk=1280).name
u'BetterName'
```
!!! warning
The Django ORM provides methods to create/edit many objects at once, namely `bulk_create()` and `update()`. These are best avoided in most cases as they bypass a model's built-in validation and can easily lead to database corruption if not used carefully.
## Deleting Objects
To delete an object, simply call `delete()` on its instance. This will return a dictionary of all objects (including related objects) which have been deleted as a result of this operation.
To delete multiple objects at once, call `delete()` on a filtered queryset. It's a good idea to always sanity-check the count of selected objects _before_ deleting them.