Repository: netbox-community/netbox

Issue:
Unable to reference object id in site using REST API 
### Deployment Type

Self-hosted

### NetBox Version

v4.0.0

### Python Version

3.10

### Steps to Reproduce

1. Create a tenant named "Test Tenant". Make a note of the tenant's id (in my case it's 7)
2. Create a site using REST API
```
curl -s -X POST \
-H "Authorization: Token 0123456789abcdef0123456789abcdef01234567" \
-H "Content-Type: application/json" \
http://localhost:32768/api/dcim/sites/ \
--data '{"name": "Test site 1", "slug": "test-site-1", "tenant": 7}' | jq '.'
```

### Expected Behavior

The site is created in and tenant is set to Test tenant.

### Observed Behavior

```
{
  "tenant": {
    "non_field_errors": [
      "Invalid data. Expected a dictionary, but got int."
    ]
  }
}
```

The same API calls work as expected in NetBox 3.7.


Discussion:
I see the issue with SiteSerializer; we're not passing `nested=True` to TenantSerializer. Easy fix.

@rodvand have you come across this issue for any other models? A quick check suggests it affects only the site model, but I'll do a more thorough audit.
> @rodvand have you come across this issue for any other models? A quick check suggests it affects only the site model, but I'll do a more thorough audit.

I'll update if I come by any more of this issue. 

Resolving patch:
diff --git a/netbox/dcim/api/serializers_/sites.py b/netbox/dcim/api/serializers_/sites.py
--- a/netbox/dcim/api/serializers_/sites.py
+++ b/netbox/dcim/api/serializers_/sites.py
@@ -51,7 +51,7 @@ class SiteSerializer(NetBoxModelSerializer):
     status = ChoiceField(choices=SiteStatusChoices, required=False)
     region = RegionSerializer(nested=True, required=False, allow_null=True)
     group = SiteGroupSerializer(nested=True, required=False, allow_null=True)
-    tenant = TenantSerializer(required=False, allow_null=True)
+    tenant = TenantSerializer(nested=True, required=False, allow_null=True)
     time_zone = TimeZoneSerializerField(required=False, allow_null=True)
     asns = SerializedPKRelatedField(
         queryset=ASN.objects.all(),


Test patch:
diff --git a/netbox/dcim/tests/test_api.py b/netbox/dcim/tests/test_api.py
--- a/netbox/dcim/tests/test_api.py
+++ b/netbox/dcim/tests/test_api.py
@@ -10,6 +10,7 @@
 from extras.models import ConfigTemplate
 from ipam.models import ASN, RIR, VLAN, VRF
 from netbox.api.serializers import GenericObjectSerializer
+from tenancy.models import Tenant
 from utilities.testing import APITestCase, APIViewTestCases, create_test_device
 from virtualization.models import Cluster, ClusterType
 from wireless.choices import WirelessChannelChoices
@@ -152,6 +153,7 @@ def setUpTestData(cls):
         Site.objects.bulk_create(sites)
 
         rir = RIR.objects.create(name='RFC 6996', is_private=True)
+        tenant = Tenant.objects.create(name='Tenant 1', slug='tenant-1')
 
         asns = [
             ASN(asn=65000 + i, rir=rir) for i in range(8)
@@ -166,6 +168,7 @@ def setUpTestData(cls):
                 'group': groups[1].pk,
                 'status': SiteStatusChoices.STATUS_ACTIVE,
                 'asns': [asns[0].pk, asns[1].pk],
+                'tenant': tenant.pk,
             },
             {
                 'name': 'Site 5',