Missing family property on aggregate creation via REST API #8037

Closed
opened 2025-12-29 20:31:35 +01:00 by adam · 4 comments
Owner

Originally created by @rodvand on GitHub (May 10, 2023).

Originally assigned to: @arthanson on GitHub.

NetBox version

v3.5.1

Python version

3.8

Steps to Reproduce

  1. Create an aggregate with the REST API
curl -X 'POST' \
  'https://demo.netbox.dev/api/ipam/aggregates/' \
  -H 'accept: application/json' \
  -H 'Content-Type: application/json' \
  -d '{
  "prefix": "34.0.0.0/8",
  "rir": 1,
  "date_added": "2023-05-10",
  "description": "string",
  "comments": "string"  
}'

Expected Behavior

The aggregate is created, but I expect the family value to be present with the server response.

Observed Behavior

This is the server response on creation:

{
  "id": 5,
  "url": "https://demo.netbox.dev/api/ipam/aggregates/5/",
  "display": "34.0.0.0/8",
  "prefix": "34.0.0.0/8",
  "rir": {
    "id": 1,
    "url": "https://demo.netbox.dev/api/ipam/rirs/1/",
    "display": "ARIN",
    "name": "ARIN",
    "slug": "arin"
  },
  "tenant": null,
  "date_added": "2023-05-10",
  "description": "string",
  "comments": "string",
  "tags": [],
  "custom_fields": {},
  "created": "2023-05-10T20:18:03.646781Z",
  "last_updated": "2023-05-10T20:18:03.646811Z"
}

If I go and check the aggregate through the API after it looks correct:

{
    "id": 5,
    "url": "https://demo.netbox.dev/api/ipam/aggregates/5/",
    "display": "34.0.0.0/8",
    "family": {
        "value": 4,
        "label": "IPv4"
    },
    "prefix": "34.0.0.0/8",
    "rir": {
        "id": 1,
        "url": "https://demo.netbox.dev/api/ipam/rirs/1/",
        "display": "ARIN",
        "name": "ARIN",
        "slug": "arin"
    },
    "tenant": null,
    "date_added": "2023-05-10",
    "description": "string",
    "comments": "string",
    "tags": [],
    "custom_fields": {},
    "created": "2023-05-10T20:18:03.646781Z",
    "last_updated": "2023-05-10T20:18:03.646811Z"
}
Originally created by @rodvand on GitHub (May 10, 2023). Originally assigned to: @arthanson on GitHub. ### NetBox version v3.5.1 ### Python version 3.8 ### Steps to Reproduce 1. Create an aggregate with the REST API ``` curl -X 'POST' \ 'https://demo.netbox.dev/api/ipam/aggregates/' \ -H 'accept: application/json' \ -H 'Content-Type: application/json' \ -d '{ "prefix": "34.0.0.0/8", "rir": 1, "date_added": "2023-05-10", "description": "string", "comments": "string" }' ``` ### Expected Behavior The aggregate is created, but I expect the family value to be present with the server response. ### Observed Behavior This is the server response on creation: ``` { "id": 5, "url": "https://demo.netbox.dev/api/ipam/aggregates/5/", "display": "34.0.0.0/8", "prefix": "34.0.0.0/8", "rir": { "id": 1, "url": "https://demo.netbox.dev/api/ipam/rirs/1/", "display": "ARIN", "name": "ARIN", "slug": "arin" }, "tenant": null, "date_added": "2023-05-10", "description": "string", "comments": "string", "tags": [], "custom_fields": {}, "created": "2023-05-10T20:18:03.646781Z", "last_updated": "2023-05-10T20:18:03.646811Z" } ``` If I go and check the aggregate through the API after it looks correct: ``` { "id": 5, "url": "https://demo.netbox.dev/api/ipam/aggregates/5/", "display": "34.0.0.0/8", "family": { "value": 4, "label": "IPv4" }, "prefix": "34.0.0.0/8", "rir": { "id": 1, "url": "https://demo.netbox.dev/api/ipam/rirs/1/", "display": "ARIN", "name": "ARIN", "slug": "arin" }, "tenant": null, "date_added": "2023-05-10", "description": "string", "comments": "string", "tags": [], "custom_fields": {}, "created": "2023-05-10T20:18:03.646781Z", "last_updated": "2023-05-10T20:18:03.646811Z" } ```
adam added the type: bugstatus: acceptedseverity: medium labels 2025-12-29 20:31:35 +01:00
adam closed this issue 2025-12-29 20:31:35 +01:00
Author
Owner

@jeremystretch commented on GitHub (May 12, 2023):

It seems the family field is being omitted because the serializer field has read_only=True.

@jeremystretch commented on GitHub (May 12, 2023): It seems the `family` field is being omitted because the serializer field has `read_only=True`.
Author
Owner

@tobiasge commented on GitHub (Jun 13, 2023):

The same problem exists on a POST to /api/ipam/prefixes/.

@tobiasge commented on GitHub (Jun 13, 2023): The same problem exists on a `POST` to `/api/ipam/prefixes/`.
Author
Owner

@tobiasge commented on GitHub (Jun 20, 2023):

I did some debugging (with /api/ipam/prefixes/) and noticed that the instance variable in netbox/netbox/api/viewsets/__init__.py (line 122) is of the type Prefix but the field prefix in the instance is a str and not (as I would expect) an IPNetworkField. That's why the family is missing, because the property field fails.
To test this I added an instance.refresh_from_db() after the .save(). This helped and now I get the family in the API repsonse.

I'm not sure if this is the correct solution, as this change affects all models and adds one (or more) queries to every create.
Perhaps a list of models where the reload is needed would be possible, but I'm not that familiar with the code, to decide if this could and should be done.

@tobiasge commented on GitHub (Jun 20, 2023): I did some debugging (with `/api/ipam/prefixes/`) and noticed that the `instance` variable in `netbox/netbox/api/viewsets/__init__.py` (line 122) is of the type `Prefix` but the field `prefix` in the instance is a `str` and not (as I would expect) an `IPNetworkField`. That's why the family is missing, because the property field fails. To test this I added an `instance.refresh_from_db()` after the `.save()`. This helped and now I get the family in the API repsonse. I'm not sure if this is the correct solution, as this change affects all models and adds one (or more) queries to every create. Perhaps a list of models where the reload is needed would be possible, but I'm not that familiar with the code, to decide if this could and should be done.
Author
Owner

@kkthxbye-code commented on GitHub (Jul 24, 2023):

Casting to IPNetwork in the family property method for Aggregate and Prefix fixes it, but it's kinda hacky.

Another solution is to add the following method to AggregateSerializer and PrefixSerializer:

def validate_prefix(self, value):
    if value:
        try:
            return netaddr.IPNetwork(value)
        except:
            raise serializers.ValidationError("Invalid prefix.")
    return value

This will cast the prefix string to a IPNetwork and solve the issue in my testing. Not really confident enough in DRF to figure out if this is the correct solution though.

@kkthxbye-code commented on GitHub (Jul 24, 2023): Casting to IPNetwork in the `family` property method for Aggregate and Prefix fixes it, but it's kinda hacky. Another solution is to add the following method to `AggregateSerializer` and `PrefixSerializer`: ```python def validate_prefix(self, value): if value: try: return netaddr.IPNetwork(value) except: raise serializers.ValidationError("Invalid prefix.") return value ``` This will cast the prefix string to a IPNetwork and solve the issue in my testing. Not really confident enough in DRF to figure out if this is the correct solution though.
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: starred/netbox#8037