Add Configuration Template Variable Table #8843

Closed
opened 2025-12-29 20:41:57 +01:00 by adam · 6 comments
Owner

Originally created by @MCDELTAT on GitHub (Nov 16, 2023).

Change Type

Addition

Area

Features

Proposed Changes

Should we add an exhaustive list of variables that can be used in Jinja Configuration Templates? At the moment, it does not appear any reference exists at all.

I found this tutorial from Netbox Labs here. I also found the short snippet that exists in the Configuration Rendering page of the official docs here.

I noticed that many of the items are simply the JSON path of the Device API Response such as device.device_type.manufacturer.slug. However, on testing some like device.device_type.display did not render, telling me there are exceptions to the API response. In the first example, it also calls things like device.interfaces.all(), when there is no direct device.interfaces object on the API response. Are there additional functions? What are they? I think the doc would be helpful in referencing all of this.

This seems like a good first ticket and I wouldn't mind picking it up if it isn't a quick write up for a current maintainer.

Thanks.

Originally created by @MCDELTAT on GitHub (Nov 16, 2023). ### Change Type Addition ### Area Features ### Proposed Changes Should we add an exhaustive list of variables that can be used in Jinja Configuration Templates? At the moment, it does not appear any reference exists at all. I found this tutorial from Netbox Labs [here][1]. I also found the short snippet that exists in the `Configuration Rendering` page of the official docs [here][2]. I noticed that many of the items are simply the JSON path of the Device API Response such as `device.device_type.manufacturer.slug`. However, on testing some like `device.device_type.display` did not render, telling me there are exceptions to the API response. In the first example, it also calls things like `device.interfaces.all()`, when there is no direct `device.interfaces` object on the API response. Are there additional functions? What are they? I think the doc would be helpful in referencing all of this. This seems like a good first ticket and I wouldn't mind picking it up if it isn't a quick write up for a current maintainer. Thanks. [1]: https://netboxlabs.com/blog/how-to-generate-device-configurations-with-netbox/ [2]: https://docs.netbox.dev/en/stable/features/configuration-rendering/
adam added the type: documentationpending closure labels 2025-12-29 20:41:57 +01:00
adam closed this issue 2025-12-29 20:41:57 +01:00
Author
Owner

@YooBZH commented on GitHub (Nov 27, 2023):

Hi,

I second this demand, I am struggling with Netbox templating because of that.
I managed to find a few examples on the web but that is about it.

A documentation could solve this problem, or maybe there is a way to "explore" by ourselves ?
Like creating a dummy template and trying things like (this does not work, dont bother trying) :

{% for x in device | items() %}
{{ x }}
{% endfor %}

Or something equivalent, so we can discover by ourselves all the capabilities of an object.

I tried a lot of things, like accessing device.__dict__() or device.__dir__() but this does not work because of security reason.

jinja2.exceptions.SecurityError: access to attribute '__dir__' of 'Device' object is unsafe.

If anyone has any hint I think a lot of use would appreciate that :)

Bonus note:
while writing this comment I experimented a bit and found out that you can list ipam capabilities with :

{% for x in ipam | items() %}
{{ x }}
{% endfor %}

Which render to :

('IPAddress', <class 'ipam.models.ip.IPAddress'>)

('RIR', <class 'ipam.models.ip.RIR'>)

('ASN', <class 'ipam.models.asns.ASN'>)

('VRF', <class 'ipam.models.vrfs.VRF'>)

('FHRPGroup', <class 'ipam.models.fhrp.FHRPGroup'>)

('Aggregate', <class 'ipam.models.ip.Aggregate'>)

('Prefix', <class 'ipam.models.ip.Prefix'>)

('IPRange', <class 'ipam.models.ip.IPRange'>)

('Role', <class 'ipam.models.ip.Role'>)

('ASNRange', <class 'ipam.models.asns.ASNRange'>)

('VLANGroup', <class 'ipam.models.vlans.VLANGroup'>)

('ServiceTemplate', <class 'ipam.models.services.ServiceTemplate'>)

('L2VPN', <class 'ipam.models.l2vpn.L2VPN'>)

('Service', <class 'ipam.models.services.Service'>)

('RouteTarget', <class 'ipam.models.vrfs.RouteTarget'>)

('VLAN', <class 'ipam.models.vlans.VLAN'>)

('L2VPNTermination', <class 'ipam.models.l2vpn.L2VPNTermination'>)

I dont know how to dig further.

Edit : I mainly discussed about exploring Netbox models, but having also a bit of documentation about what Jinja method is available (and how it is available) would be nice too , right now I only know about .filter(name=....) ; that is a bit limiting.

@YooBZH commented on GitHub (Nov 27, 2023): Hi, I second this demand, I am struggling with Netbox templating because of that. I managed to find a few examples on the web but that is about it. A documentation could solve this problem, or maybe there is a way to "explore" by ourselves ? Like creating a dummy template and trying things like (this does not work, dont bother trying) : ```jinja2 {% for x in device | items() %} {{ x }} {% endfor %} ``` Or something equivalent, so we can discover by ourselves all the capabilities of an object. I tried a lot of things, like accessing `device.__dict__()` or `device.__dir__()` but this does not work because of security reason. ```python jinja2.exceptions.SecurityError: access to attribute '__dir__' of 'Device' object is unsafe. ``` If anyone has any hint I think a lot of use would appreciate that :) Bonus note: while writing this comment I experimented a bit and found out that you can list ipam capabilities with : ```jinja2 {% for x in ipam | items() %} {{ x }} {% endfor %} ``` Which render to : ```python ('IPAddress', <class 'ipam.models.ip.IPAddress'>) ('RIR', <class 'ipam.models.ip.RIR'>) ('ASN', <class 'ipam.models.asns.ASN'>) ('VRF', <class 'ipam.models.vrfs.VRF'>) ('FHRPGroup', <class 'ipam.models.fhrp.FHRPGroup'>) ('Aggregate', <class 'ipam.models.ip.Aggregate'>) ('Prefix', <class 'ipam.models.ip.Prefix'>) ('IPRange', <class 'ipam.models.ip.IPRange'>) ('Role', <class 'ipam.models.ip.Role'>) ('ASNRange', <class 'ipam.models.asns.ASNRange'>) ('VLANGroup', <class 'ipam.models.vlans.VLANGroup'>) ('ServiceTemplate', <class 'ipam.models.services.ServiceTemplate'>) ('L2VPN', <class 'ipam.models.l2vpn.L2VPN'>) ('Service', <class 'ipam.models.services.Service'>) ('RouteTarget', <class 'ipam.models.vrfs.RouteTarget'>) ('VLAN', <class 'ipam.models.vlans.VLAN'>) ('L2VPNTermination', <class 'ipam.models.l2vpn.L2VPNTermination'>) ``` I dont know how to dig further. Edit : I mainly discussed about exploring Netbox models, but having also a bit of documentation about what Jinja method is available (and how it is available) would be nice too , right now I only know about `.filter(name=....)` ; that is a bit limiting.
Author
Owner

@MCDELTAT commented on GitHub (Dec 2, 2023):

Two weeks later and I haven't been able to figure out what the available items by looping over things either. I tried reading the code but honestly there's a lot of Django magic going on.

Files of interest:

  1. netbox/templates/dcim/device/render_config.html -> Where the rendered config shows up on the device.
  2. netbox/dcim/views.py -> class DeviceRenderConfigView
  3. netbox/dcim/api/views.py -> class DeviceViewSet

So I forged on without docs and have several questions. Is there a way to get all IPs on the interface? I.E. interface.ip. Would this be an array for interfaces with multiple IPs?

Here's what I gathered don't return anything (assuming interface used as loop iterator):

  1. interface.ip
  2. interface.ips
  3. interface.ips[0]
  4. interface.ip_address

So at the moment I don't know how to get the second ip address on an interface in these templates.

@MCDELTAT commented on GitHub (Dec 2, 2023): Two weeks later and I haven't been able to figure out what the available items by looping over things either. I tried reading the code but honestly there's a lot of Django magic going on. Files of interest: 1. `netbox/templates/dcim/device/render_config.html` -> Where the rendered config shows up on the device. 2. `netbox/dcim/views.py` -> `class DeviceRenderConfigView` 3. `netbox/dcim/api/views.py` -> `class DeviceViewSet` So I forged on without docs and have several questions. Is there a way to get all IPs on the interface? I.E. `interface.ip`. Would this be an array for interfaces with multiple IPs? Here's what I gathered don't return anything (assuming interface used as loop iterator): 1. `interface.ip` 2. `interface.ips` 3. `interface.ips[0]` 4. `interface.ip_address` So at the moment I don't know how to get the second ip address on an interface in these templates.
Author
Owner

@YooBZH commented on GitHub (Dec 3, 2023):

@MCDELTAT here are some ways to work with device interfaces and their IP addresses.

Print all interfaces and their first assigned IP address :

{% for intf in device.interfaces.all() %}
{{ intf }} ip address : {{ intf.ip_addresses.first() }}
{% endfor %}

To access the IP address of a specific interface you can filter the interface by name, something like :

{{ device.interfaces.filter(name="GigabitEthernet0/0/0").0.ip_addresses.first() }}

If the interface has more than one IP address, you can loop over all of them :

{% for ip_address in device.interfaces.filter(name="GigabitEthernet0/0/0").0.ip_addresses.all() %}
{{ ip_address }}
{% endfor %}

I hope this will help you and others, it will certainly help me when I will have forgotten about all of that :)

@YooBZH commented on GitHub (Dec 3, 2023): @MCDELTAT here are some ways to work with device interfaces and their IP addresses. Print all interfaces and their first assigned IP address : ```jinja2 {% for intf in device.interfaces.all() %} {{ intf }} ip address : {{ intf.ip_addresses.first() }} {% endfor %} ``` To access the IP address of a specific interface you can filter the interface by name, something like : ```jinja2 {{ device.interfaces.filter(name="GigabitEthernet0/0/0").0.ip_addresses.first() }} ``` If the interface has more than one IP address, you can loop over all of them : ```jinja2 {% for ip_address in device.interfaces.filter(name="GigabitEthernet0/0/0").0.ip_addresses.all() %} {{ ip_address }} {% endfor %} ``` I hope this will help you and others, it will certainly help me when I will have forgotten about all of that :)
Author
Owner

@jacobw commented on GitHub (Dec 20, 2023):

@MCDELTAT I've been using ./manage.py nbshell to explore the data models when working up a template. I find it quite easy to figure out what's available once you get the hang of it. The main thing that helps is tab completion, and instant results.

@jacobw commented on GitHub (Dec 20, 2023): @MCDELTAT I've been using ./manage.py nbshell to explore the data models when working up a template. I find it quite easy to figure out what's available once you get the hang of it. The main thing that helps is tab completion, and instant results.
Author
Owner

@github-actions[bot] commented on GitHub (Mar 20, 2024):

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. NetBox is governed by a small group of core maintainers which means not all opened issues may receive direct feedback. Do not attempt to circumvent this process by "bumping" the issue; doing so will result in its immediate closure and you may be barred from participating in any future discussions. Please see our contributing guide.

@github-actions[bot] commented on GitHub (Mar 20, 2024): This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. NetBox is governed by a small group of core maintainers which means not all opened issues may receive direct feedback. **Do not** attempt to circumvent this process by "bumping" the issue; doing so will result in its immediate closure and you may be barred from participating in any future discussions. Please see our [contributing guide](https://github.com/netbox-community/netbox/blob/develop/CONTRIBUTING.md).
Author
Owner

@github-actions[bot] commented on GitHub (May 15, 2024):

This issue has been automatically closed due to lack of activity. In an effort to reduce noise, please do not comment any further. Note that the core maintainers may elect to reopen this issue at a later date if deemed necessary.

@github-actions[bot] commented on GitHub (May 15, 2024): This issue has been automatically closed due to lack of activity. In an effort to reduce noise, please do not comment any further. Note that the core maintainers may elect to reopen this issue at a later date if deemed necessary.
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: starred/netbox#8843