Repository: netbox-community/netbox

Issue:
Cannot import or clone a Cable
### NetBox version

v3.4.0

### Python version

3.9

### Steps to Reproduce

1. Import Cables
2. Add data to import a cable
3. Click Import

### Expected Behavior

A cable should be created.

### Observed Behavior

A ValueError was raised.
Creating a cable through the UI is done successfully.
Using the API creates the same error as importing.

```
<class 'ValueError'>

'Cable' instance needs to have a primary key value before this relationship can be used.

Python version: 3.9.2
NetBox version: 3.4.0
```


There seems to also be an issue with Cloning a Cable:
When you click Clone on a Cable you recieve this error:

```
<class 'AttributeError'>

'str' object has no attribute 'label'

Python version: 3.9.2
NetBox version: 3.4.0
```


Discussion:
If you provide the id for a cable it is updated correctly. This error is only when trying to import new cable objects.
> Add data to import a cable

Please provide all the steps required to replicate the issue, including example CSV data.

> Using the API creates the same error as importing.

Please provide replication steps for the API error also.

> There seems to also be an issue with Cloning a Cable:

This should probably be split out in a seperate bug report as they are unlikely to be related. I'm not even sure why it is possible to clone a cable as no fields are cloned and we don't provide a default "Add cable" option like most other models.
For reference I just tried importing the following cable and it worked without issue on 3.4.0:

```
side_a_device,side_a_type,side_a_name,side_b_device,side_b_type,side_b_name
dmi01-yonkers-sw01,dcim.interface,GigabitEthernet1/0/6,dmi01-yonkers-sw01,dcim.interface,GigabitEthernet1/0/7
```

If I try to import the same cable again or I try to import a cable that connects to an occupied interface I get the same error as you. This would indicate that there might be some missing validation, but I'm not sure if this is new in 3.4 or not.

I could not replicate it in the API.
I'm seeing similar behavior.  It feels like there are certain errors that aren't being caught.  While trying to bulk create if I had a bad interface type or name it would create the same primary key error but when I had included additional data in the cable color I received a specific error saying I provided 7 characters but it was only expecting 6.  

Resolving patch:
diff --git a/netbox/dcim/models/cables.py b/netbox/dcim/models/cables.py
--- a/netbox/dcim/models/cables.py
+++ b/netbox/dcim/models/cables.py
@@ -112,6 +112,10 @@ def get_absolute_url(self):
     def a_terminations(self):
         if hasattr(self, '_a_terminations'):
             return self._a_terminations
+
+        if not self.pk:
+            return []
+
         # Query self.terminations.all() to leverage cached results
         return [
             ct.termination for ct in self.terminations.all() if ct.cable_end == CableEndChoices.SIDE_A
@@ -126,6 +130,10 @@ def a_terminations(self, value):
     def b_terminations(self):
         if hasattr(self, '_b_terminations'):
             return self._b_terminations
+
+        if not self.pk:
+            return []
+
         # Query self.terminations.all() to leverage cached results
         return [
             ct.termination for ct in self.terminations.all() if ct.cable_end == CableEndChoices.SIDE_B


Test patch: