Updating a cable via PUT without specifying length_unit returns an error that the field cannot be null however the field isn't required on POST.
PUT and POST behavior should be the same.
PUT requires a field have a value that POST doesn't.
Ok, here's bit more detail. POST lets you create a cable without the length_unit field:
{
"termination_a_type": "dcim.interface",
"termination_a_id": 2349,
"termination_a": 2349,
"termination_b_type": "dcim.interface",
"termination_b_id": 2382,
"termination_b": 2382
}
If you do include it and set to null then you get the same error as PUT on POST
POSTing the json above results in this response:
$ curl -X POST -H "Authorization: Token abc123" -H "Content-Type: application/json" -H "Accept: application/json; indent=4" http://localhost:8000/api/dcim/cables/ --data @cable.json
{
"id": 1,
"termination_a_type": "dcim.interface",
"termination_a_id": 1,
"termination_a": {
"id": 1,
"url": "http://localhost:8000/api/dcim/interfaces/1/",
"device": {
"id": 1,
"url": "http://localhost:8000/api/dcim/devices/1/",
"name": "test",
"display_name": "test"
},
"name": "et-0/1/0",
"cable": 1
},
"termination_b_type": "dcim.interface",
"termination_b_id": 2,
"termination_b": {
"id": 2,
"url": "http://localhost:8000/api/dcim/interfaces/2/",
"device": {
"id": 2,
"url": "http://localhost:8000/api/dcim/devices/2/",
"name": "test1",
"display_name": "test1"
},
"name": "et-0/1/0",
"cable": 1
},
"type": null,
"status": {
"value": true,
"label": "Connected"
},
"label": "",
"color": "",
"length": null,
"length_unit": null
}
Which if you modify and repackaged into a PUT trips the error.
It seems this is happening because we're using a CharField for length_unit rather than an IntegerField. The notable distinction is that an IntegerField can be null whereas a CharField cannot (it can be _blank_, but not null).
We can change this to our custom NullableCharField, which stores empty values as null rather than "", but in the interest of maintaining consistency with other choice fields it might be preferable to switch to an IntegerField. This just means we would change from storing m, ft etc. to hard-coded integer values like we do for other fields.
I'm open to feedback.
I vote for consistency here. We have a well-defined method for choice fields in that they use integer based fields with constants in the code base. This ensures consistency through the code base, but also in the way API clients interact with choice fields.
One additional thought: Sticking with integer values in the database makes future localization work a bit cleaner. For example, a Spanish speaker won't wonder why "pie" ("foot") is stored as "ft".
This also affects Rack.outer_unit. I'm changing that field to an IntegerField as well.