Repository: netbox-community/netbox

Issue:
can't clear selection custom field
### Issue type
[ ] Feature request <!-- An enhancement of existing functionality -->
[x] Bug report      <!-- Unexpected or erroneous behavior -->
[ ] Documentation   <!-- A modification to the documentation -->

<!--
    Please describe the environment in which you are running NetBox. (Be sure
    to verify that you are running the latest stable release of NetBox before
    submitting a bug report.) If you are submitting a bug report and have made
    any changes to the code base, please first validate that your bug can be
    recreated while running an official release.
-->
### Environment
* Python version:  2.7.5
* NetBox version:  2.3.1

<!--
    BUG REPORTS must include:
        * A list of the steps needed for someone else to reproduce the bug
        * A description of the expected and observed behavior
        * Any relevant error messages (screenshots may also help)

    FEATURE REQUESTS must include:
        * A detailed description of the proposed functionality
        * A use case for the new feature
        * A rough description of any necessary changes to the database schema
        * Any relevant third-party libraries which would be needed
-->
### Description

Assuming there is a basic setup of manufacturer, sites, a device and so on.

1. create a custom selection field with a couple of options
2. edit an device and set the field, save
3. edit the same device and try to clear the field (select `------`), save
4. receive an error 500 page :(

Sadly I can't reproduce this in the docker-compose setup.

```
Traceback (most recent call last):
  File "/usr/lib/python2.7/site-packages/django/core/handlers/exception.py", line 41, in inner
    response = get_response(request)
  File "/usr/lib/python2.7/site-packages/django/core/handlers/base.py", line 187, in _get_response
    response = self.process_exception_by_middleware(e, request)
  File "/usr/lib/python2.7/site-packages/django/core/handlers/base.py", line 185, in _get_response
    response = wrapped_callback(request, *callback_args, **callback_kwargs)
  File "/usr/lib/python2.7/site-packages/django/views/generic/base.py", line 68, in view
    return self.dispatch(request, *args, **kwargs)
  File "/usr/lib/python2.7/site-packages/django/contrib/auth/mixins.py", line 92, in dispatch
    return super(PermissionRequiredMixin, self).dispatch(request, *args, **kwargs)
  File "/usr/lib/python2.7/site-packages/django/views/generic/base.py", line 88, in dispatch
    return handler(request, *args, **kwargs)
  File "/opt/netbox/netbox/utilities/views.py", line 196, in post
    obj = form.save()
  File "/opt/netbox/netbox/extras/forms.py", line 123, in save
    self._save_custom_fields()
  File "/opt/netbox/netbox/extras/forms.py", line 116, in _save_custom_fields
    cfv.save()
  File "/opt/netbox/netbox/extras/models.py", line 169, in save
    if self.pk and self.value is None:
  File "/opt/netbox/netbox/extras/models.py", line 161, in value
    return self.field.deserialize_value(self.serialized_value)
  File "/opt/netbox/netbox/extras/models.py", line 140, in deserialize_value
    return self.choices.get(pk=int(serialized_value))
ValueError: invalid literal for int() with base 10: ''
```

but funnily enough there is [a check for exactly this case](https://github.com/digitalocean/netbox/blob/develop/netbox/extras/models.py#L130-L131) a few lines about the crash site:

```python
if serialized_value is '':
    return None
```


Discussion:

Resolving patch:
diff --git a/netbox/extras/models.py b/netbox/extras/models.py
--- a/netbox/extras/models.py
+++ b/netbox/extras/models.py
@@ -127,7 +127,7 @@ def deserialize_value(self, serialized_value):
         """
         Convert a string into the object it represents depending on the type of field
         """
-        if serialized_value is '':
+        if serialized_value == '':
             return None
         if self.type == CF_TYPE_INTEGER:
             return int(serialized_value)


Test patch: