Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Calculated Jinja2 based CustomFields #11704

Closed
PieterL75 opened this issue Feb 8, 2023 · 6 comments
Closed

Calculated Jinja2 based CustomFields #11704

PieterL75 opened this issue Feb 8, 2023 · 6 comments
Labels
status: under review Further discussion is needed to determine this issue's scope and/or implementation type: feature Introduction of new functionality to the application

Comments

@PieterL75
Copy link
Contributor

PieterL75 commented Feb 8, 2023

NetBox version

v3.4.4

Feature type

New functionality

Proposed functionality

Create a custom field of the type 'Calculated'
This custom field is composed of a Jinja2 template that gives the ability to format the data of the object to an custom presentation.
It should provide the ability to represent create a string, a badge, a %graph, markdown, ...

Use case

There is a lot of a data in one model (device), and most of can be shown in a table column.
This custom field will create a way to merge multiple columns into one, or create a column with data that is not visible in the GUI (ex: number of interfaces)
#6347 will give even more fields to merge into a custom view

It will create the ability to provide fully customizable view, with the need to update the core of the code.

Database changes

No response

External dependencies

No response

@PieterL75 PieterL75 added the type: feature Introduction of new functionality to the application label Feb 8, 2023
@jeremystretch
Copy link
Member

jeremystretch commented Feb 8, 2023

IMO this wouldn't be an appropriate use of custom fields, as it's a pretty stark violation of the separation between data and presentation. Custom fields exist specifically to hold additional data about an object, not to to display existing data in an alternative format. I can appreciate the underlying use case, but I don't think custom fields are the right solution for it.

Edit to add: It seems like your focus is primarily on table columns. Maybe what you're really after is a way to inject custom columns?

@PieterL75
Copy link
Contributor Author

My proposal is mainly for columns, but I can imagine that it is also useful in the Deviceview or even in API results (not the badges, but the numbers)

I suppose you can see better solution than a custom field (your (net)box is bigger than my (net)box), but in my little box, that seemed a good idea :-)

@ryanmerolle
Copy link
Contributor

Relates to #8217

Other DCIM tools offer jinja custom_fields, and so this will likely come up from time to time.

If you are using custom fields for links to other tools like I was, I migrated to custom_links which allow for Jinja logic in the link text and url. It solved most of my use case.

My only other use case was for generating interface descriptions since I throw in circuit info and peer device/interface info into descriptions. I just achieve that by including the jinja logic in my config templates.

@jeremystretch jeremystretch added the status: under review Further discussion is needed to determine this issue's scope and/or implementation label Feb 10, 2023
@jeremystretch
Copy link
Member

I'll elaborate on my explanation above.

This custom field is composed of a Jinja2 template that gives the ability to format the data of the object to an custom presentation.

My understanding of the intent here is to expose as an object attribute some value that is rendered (or "computed") from one or more other attributes of that object. As a very contrived example, let's say we want to include a field in the REST API representation of a site that concatenates the name of its region with its own name. Suppose we want to do this using a simple Jinja2 filter:

{{ site.name }}, {{ site.region.name }}

So for example, a site named "Raleigh" in a region named "North Carolina" would look like this:

{
    "name": "Raleigh",
    "region": {
        "name": "North Carolina"
    },
    "custom-attributes": {
        "region-and-name": "Raleigh, North Carolina"
    }
}

There are two reasons we wouldn't want to use a custom field for this:

  1. The value of the custom attribute is dictated by some external piece of logic, outside the control the consumer.
  2. The custom attribute itself cannot be directly modified.

For example, there should never be an instance where an API consumer would need to set the value of the region-and-name attribute` directly: Instead, it's influenced by the values of the fields it references. Custom field values by contrast are mutable and can be set directly by an API consumer.

One key implication of this distinction is that computed attributes do not need to be stored per instance; we only need to define a per-model definition, which can be replicated for each instance. In this example, we just create a single attribute object tying our Jinja2 code to the site model. This allows us to render the attribute for every site.

The only reason I can see to store the computed value for each instance would be as a performance optimization (essentially caching the rendered output). But considering the overhead associated with keeping these values up to date combined with the additional complexity of supporting read-only custom fields, this seems unlikely to be worthwhile except in very complex scenarios.

Beyond the technical implementation, we must also consider the practical use case for such attributes: Given that APIs are intended to be consumed programmatically, what practical use cases can we identify that cannot be satisfied with the data already being provided. (As in the above example, the region and site names are already provided, and the client could render the custom attribute value independently.) Further, we would generally want to stop short of rendering any particular markup (e.g. HTML) as it could severely limit the practical application of the data being provided.

There is a lot of a data in one model (device), and most of can be shown in a table column.

Again, it feels like the intended use case here is specifically for the user interface, which is a valid consideration as it cannot be consumed programmatically. If anything, I would propose that the preferred implementation would be some mechanism by which custom attributes can be registered at the model level, and potentially conveyed as table columns and other elements in the user interface.

@PieterL75
Copy link
Contributor Author

I understand your point on the API part. CustomFields are not the right place to store this kind of formatting, as they are intended to store data related to the instance of the model. Each object of that model should be able to store different values in the CustomField.
My proposal does indeed require a different approach.

You're more in favor of a 'CustomColumn' or 'CustomAttribute' that links to a model. That attribute can be made available in the 'Configure Table' list, and it can also be returned as an attribute to a model in the API.
There could be different types of these (Text, Integer, URL, Badge, ProgressBar, ...)

@jeremystretch
Copy link
Member

I'm going to close this out as the specific proposal herein is untenable, but I encourage anyone interested to submit a new FR proposing a feasible implementation of the desired functionality. This will likely require the introduction of a new model, which should be detailed accordingly.

@github-actions github-actions bot locked as resolved and limited conversation to collaborators Jun 15, 2023
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
status: under review Further discussion is needed to determine this issue's scope and/or implementation type: feature Introduction of new functionality to the application
Projects
None yet
Development

No branches or pull requests

3 participants