Repository: netbox-community/netbox

Issue:
Unable to add images to a Device Type using a PATCH request
### Deployment Type

Self-hosted

### NetBox Version

v3.7.3

### Python Version

3.8

### Steps to Reproduce

1. Clone or download https://github.com/netbox-community/Device-Type-Library-Import/
2. Run the importer `NETBOX_URL=<your netbox instance> REPO_URL=https://github.com/netbox-community/devicetype-library/ NETBOX_TOKEN=<your netbox token> python3 nb-dt-import.py`


This used to work, I believe this issue related to the change in this commit: https://github.com/netbox-community/netbox/commit/839609d101aeb44d94f464813e87c6eb1374afd0.

It works in v3.7.2. 

### Expected Behavior

Images should be successfully uploaded and added to the Device Type. 

### Observed Behavior

Device-Type-Library-Import will get HTTP 400 error from the API when trying to upload images.

Example log message
```Images {'front_image': '/Users/username/tmp/Device-Type-Library-Import/repo/elevation-images/Dell/dell-powervault-nx3240.front.png', 'rear_image': '/Users/username/tmp/Device-Type-Library-Import/repo/elevation-images/Dell/dell-powervault-nx3240.rear.png'} updated at https://localhost/api/dcim/device-types/393/: <Response [400]>``` 

Further inspection of the response body shows:
```{"front_image":["Enter a valid URL."],"rear_image":["Enter a valid URL."]}```


Discussion:
+1 just hitting this very same issue today
+1, same same
Bug reports which reference code outside NetBox core are not actionable. If you believe there is a bug in the REST API, please provide suitable reproduction steps **that do not rely on third party code**, which someone else can follow to reproduce the suspect behavior. (This may be as simple as posting an example API request.)
See https://github.com/netbox-community/netbox/compare/develop...jbemmel:netbox:develop#diff-5497394955b13b98e5274b262322f5a175a9b2c1016ffd173f556696933ef2eaR329

The issue is in netbox/dcim/api/serializers.py, as referenced in the commit mentioned in the bug report. Removing these 2 lines fixes the issue

![image](https://github.com/netbox-community/netbox/assets/2031627/189fb4c1-58b3-471d-a635-b222c9c47abd)

Again, no action will be taken without sufficient reproduction details.
```
docker run -e "NETBOX_URL=http://172.17.0.1:8000/" -e "NETBOX_TOKEN=0123456789abcdef0123456789abcdef01234567" -e "VENDORS=Nokia" ghcr.io/minitriga/netbox-device-type-library-import
```

adjust the IP address and Netbox token to your setup

Yes, that depends on third party code, but it's a single line command that anyone can easily execute. Kindly stop citing unreasonable policies
Per the bug report template:

> Describe in detail the exact steps that someone else can take to reproduce this bug using the current stable release of NetBox. Begin with the creation of any necessary database objects and call out every operation being performed explicitly. **If reporting a bug in the REST API, be sure to reconstruct the raw HTTP request(s) being made**: Don't rely on a client library such as pynetbox.

If you're unwilling to provide the information needed, I'll proceed with closing out this issue.
> 
> If you're unwilling to provide the information needed, I'll proceed with closing out this issue.

I am trying to be helpful here, but these kinds of comments are discouraging. I did not open this bug report, I am merely affected by the same issue and I know where the problem is and how to fix it.

I am not "unwilling", but I do get irritated by all this and I wish you all the best with resolving your issues
> I am trying to be helpful here

You're claiming that there's a bug with a certain API request, yet you won't share the actual request you're making. You expect someone else to figure that out for you. This is unreasonable, and it is why our reporting policies clearly define the information we require to investigate a bug report. If you're unwilling to abide by these policies, please refrain from engaging with the project as it's not a productive use of time.
* Create a device type (id 8 in this case)
* Get an image, test.png in this case
* Run the following command to upload image: `curl -X PATCH -F 'front_image=@test.png' http://127.0.0.1:8000/api/dcim/device-types/8/ -H "Authorization: Token TOKENHERE"`

Returns: `{"front_image":["Enter a valid URL."]}`

Reverting https://github.com/netbox-community/netbox/commit/839609d101aeb44d94f464813e87c6eb1374afd0 makes the above curl command succede. The rest API also returns the wrong string in front_image/rear_image when the commit is not reverted:

Without the bad commit:
`"front_image": "http://127.0.0.1:8000/media/devicetype-images/test.png",`

With the bad commit:
`"front_image": "devicetype-images/test.png",`

Lastly it's immediately obvious from looking at the commit that it's wrong. The two model fields are ImageFields, obviously not URLFields. Not sure how this was not caught by the submitter nor the reviewer, and it seems like the unit tests doesn't catch this either.
@kkthxbye-code thanks for documenting those very simple reproduction steps. Given that you've already looked into the underlying issue, would you like to submit a PR for this?
Guess I'll take this one.

Resolving patch:
diff --git a/netbox/dcim/api/serializers.py b/netbox/dcim/api/serializers.py
--- a/netbox/dcim/api/serializers.py
+++ b/netbox/dcim/api/serializers.py
@@ -326,8 +326,8 @@ class DeviceTypeSerializer(NetBoxModelSerializer):
     airflow = ChoiceField(choices=DeviceAirflowChoices, allow_blank=True, required=False, allow_null=True)
     weight_unit = ChoiceField(choices=WeightUnitChoices, allow_blank=True, required=False, allow_null=True)
     device_count = serializers.IntegerField(read_only=True)
-    front_image = serializers.URLField(allow_null=True, required=False)
-    rear_image = serializers.URLField(allow_null=True, required=False)
+    front_image = serializers.ImageField(required=False, allow_null=True)
+    rear_image = serializers.ImageField(required=False, allow_null=True)
 
     # Counter fields
     console_port_template_count = serializers.IntegerField(read_only=True)


Test patch: