anon-iclr-submission/benchname-bug-localization huggingface dataset:
Repository: netbox-community/netbox
Issue: Broken image URLs in rack view

### NetBox version

v3.2.5

### Python version

3.9

### Steps to Reproduce

1. Have device types with front and rear device pictures uploaded and hosted on a separate domain (we use it for static content, let's say https://static.domain/images/front.png)
2. Have devices installed in a rack
3. View the rack with https://your.netbox.domain/dcim/racks/$some_id/

### Expected Behavior

Front and Rear rack view filled with images of device types of the devices installed to this rack.

### Observed Behavior

Blueish tint instead of images because the URLs for images are now prefixed with the netbox domain (like https://your.netbox.domainhttps://static.domain/images/front.png which is obviously unavailable)
Seems like this is caused by https://github.com/netbox-community/netbox/issues/9503. Rack views were fine on 3.1 which we had before the update.
Device type views (https://your.netbox.domain/dcim/device-types/$id/) show images just fine on 3.2.5, links are not broken.

Changed files:
netbox/dcim/svg.py

diff --git a/netbox/dcim/svg.py b/netbox/dcim/svg.py
index 1de68ec36..4c093a312 100644
--- a/netbox/dcim/svg.py
+++ b/netbox/dcim/svg.py
@@ -113,8 +113,12 @@ class RackElevationSVG:
 
         # Embed front device type image if one exists
         if self.include_images and device.device_type.front_image:
+            url = device.device_type.front_image.url
+            # Convert any relative URLs to absolute
+            if url.startswith('/'):
+                url = '{}{}'.format(self.base_url, url)
             image = drawing.image(
-                href='{}{}'.format(self.base_url, device.device_type.front_image.url),
+                href=url,
                 insert=start,
                 size=end,
                 class_='device-image'
@@ -139,8 +143,12 @@ class RackElevationSVG:
 
         # Embed rear device type image if one exists
         if self.include_images and device.device_type.rear_image:
+            url = device.device_type.rear_image.url
+            # Convert any relative URLs to absolute
+            if url.startswith('/'):
+                url = '{}{}'.format(self.base_url, url)
             image = drawing.image(
-                href='{}{}'.format(self.base_url, device.device_type.rear_image.url),
+                href=url,
                 insert=start,
                 size=end,
                 class_='device-image'
Repository: netbox-community/netbox
Issue: Typo in REARPORT_BUTTONS template code

### NetBox version

v3.3-beta

### Python version

3.8

### Steps to Reproduce

1. Analyse code in `dcim/tables/template_code.py` -> `REARPORT_BUTTONS`

### Expected Behavior

b_termination_type points to `circuits.circuittermination` and not to `circuits.circuitterminations` (s)

### Observed Behavior

Actual code:
```
                <li><a class="dropdown-item" href="{% url 'dcim:cable_add' %}?a_terminations_type=dcim.rearport&a_terminations={{ record.pk }}&b_terminations_type=circuits.circuitterminations&return_url={% url 'dcim:device_rearports' pk=object.pk %}">Circuit Termination</a></li>
```

Changed files:
netbox/dcim/tables/template_code.py

diff --git a/netbox/dcim/tables/template_code.py b/netbox/dcim/tables/template_code.py
index 90befe0a4..082df56df 100644
--- a/netbox/dcim/tables/template_code.py
+++ b/netbox/dcim/tables/template_code.py
@@ -343,7 +343,7 @@ REARPORT_BUTTONS = """
                 <li><a class="dropdown-item" href="{% url 'dcim:cable_add' %}?a_terminations_type=dcim.rearport&a_terminations={{ record.pk }}&b_terminations_type=dcim.consoleport&return_url={% url 'dcim:device_rearports' pk=object.pk %}">Console Port</a></li>
                 <li><a class="dropdown-item" href="{% url 'dcim:cable_add' %}?a_terminations_type=dcim.rearport&a_terminations={{ record.pk }}&b_terminations_type=dcim.frontport&return_url={% url 'dcim:device_rearports' pk=object.pk %}">Front Port</a></li>
                 <li><a class="dropdown-item" href="{% url 'dcim:cable_add' %}?a_terminations_type=dcim.rearport&a_terminations={{ record.pk }}&b_terminations_type=dcim.rearport&return_url={% url 'dcim:device_rearports' pk=object.pk %}">Rear Port</a></li>
-                <li><a class="dropdown-item" href="{% url 'dcim:cable_add' %}?a_terminations_type=dcim.rearport&a_terminations={{ record.pk }}&b_terminations_type=circuits.circuitterminations&return_url={% url 'dcim:device_rearports' pk=object.pk %}">Circuit Termination</a></li>
+                <li><a class="dropdown-item" href="{% url 'dcim:cable_add' %}?a_terminations_type=dcim.rearport&a_terminations={{ record.pk }}&b_terminations_type=circuits.circuittermination&return_url={% url 'dcim:device_rearports' pk=object.pk %}">Circuit Termination</a></li>
             </ul>
         </span>
     {% else %}
Repository: netbox-community/netbox
Issue: Circuit termination on interface not working when accesssed from interface table

### NetBox version

v3.3-beta1

### Python version

3.9

### Steps to Reproduce

1. Create device with interfaces
2. Create circuit with Z-side on same site as device
3. Try to connect interface to circuit termination from interface table
4. Select B Side Cicuit
5. Try to select Side for circuit

### Expected Behavior

On B Side you are able to select side for circuit

### Observed Behavior

Side option menu is empty because.

This is caused because $ is missing for `$termination_{cable_end}_circuit`

https://github.com/netbox-community/netbox/blob/abfa6a325af17d65038304feed2536330d8c60a7/netbox/dcim/forms/connections.py#L141

Changed files:
netbox/dcim/forms/connections.py

diff --git a/netbox/dcim/forms/connections.py b/netbox/dcim/forms/connections.py
index 62247e3e3..7552c0c87 100644
--- a/netbox/dcim/forms/connections.py
+++ b/netbox/dcim/forms/connections.py
@@ -138,7 +138,7 @@ def get_cable_form(a_type, b_type):
                         label='Side',
                         disabled_indicator='_occupied',
                         query_params={
-                            'circuit_id': f'termination_{cable_end}_circuit',
+                            'circuit_id': f'$termination_{cable_end}_circuit',
                         }
                     )
Repository: netbox-community/netbox
Issue: ChangeLog false positive for wwn 

### NetBox version

v3.3.2

### Python version

3.8

### Steps to Reproduce

1. Update a Interface
2. Display the generated change log.


### Expected Behavior

Only changed properties are detected as changed.

### Observed Behavior

`wwn` is detected as a changed from `null` to `""`

Changed files:
netbox/dcim/forms/models.py

diff --git a/netbox/dcim/forms/models.py b/netbox/dcim/forms/models.py
index d1d5b1683..a21265db4 100644
--- a/netbox/dcim/forms/models.py
+++ b/netbox/dcim/forms/models.py
@@ -1331,6 +1331,12 @@ class InterfaceForm(InterfaceCommonForm, NetBoxModelForm):
         label='VRF'
     )
 
+    wwn = forms.CharField(
+        empty_value=None,
+        required=False,
+        label='WWN'
+    )
+
     fieldsets = (
         ('Interface', ('device', 'module', 'name', 'type', 'speed', 'duplex', 'label', 'description', 'tags')),
         ('Addressing', ('vrf', 'mac_address', 'wwn')),
Repository: netbox-community/netbox
Issue: Add missing Serializer annotations

### NetBox version

v3.3.1

### Python version

3.10

### Steps to Reproduce

1. Download swagger.json
2. GET request on /api/ipam/vlan-groups/{ID} on vlan groups with sope

### Expected Behavior

API documentation and returned object use same types.

### Observed Behavior

Swagger.json list field sope as type string, field in returned object is JSON

Changed files:
netbox/users/api/nested_serializers.py, netbox/ipam/api/serializers.py, netbox/extras/api/serializers.py

diff --git a/netbox/extras/api/serializers.py b/netbox/extras/api/serializers.py
index 533238d36..764c7750a 100644
--- a/netbox/extras/api/serializers.py
+++ b/netbox/extras/api/serializers.py
@@ -403,6 +403,7 @@ class ScriptSerializer(serializers.Serializer):
     vars = serializers.SerializerMethodField(read_only=True)
     result = NestedJobResultSerializer()
 
+    @swagger_serializer_method(serializer_or_field=serializers.JSONField)
     def get_vars(self, instance):
         return {
             k: v.__class__.__name__ for k, v in instance._get_vars().items()
diff --git a/netbox/ipam/api/serializers.py b/netbox/ipam/api/serializers.py
index 6244e5f04..fa8b563e9 100644
--- a/netbox/ipam/api/serializers.py
+++ b/netbox/ipam/api/serializers.py
@@ -190,6 +190,7 @@ class VLANGroupSerializer(NetBoxModelSerializer):
         ]
         validators = []
 
+    @swagger_serializer_method(serializer_or_field=serializers.JSONField)
     def get_scope(self, obj):
         if obj.scope_id is None:
             return None
diff --git a/netbox/users/api/nested_serializers.py b/netbox/users/api/nested_serializers.py
index e9e730cc4..0d8f7ae42 100644
--- a/netbox/users/api/nested_serializers.py
+++ b/netbox/users/api/nested_serializers.py
@@ -1,5 +1,6 @@
 from django.contrib.auth.models import Group, User
 from django.contrib.contenttypes.models import ContentType
+from drf_yasg.utils import swagger_serializer_method
 from rest_framework import serializers
 
 from netbox.api.fields import ContentTypeField
@@ -56,8 +57,10 @@ class NestedObjectPermissionSerializer(WritableNestedSerializer):
         model = ObjectPermission
         fields = ['id', 'url', 'display', 'name', 'enabled', 'object_types', 'groups', 'users', 'actions']
 
+    @swagger_serializer_method(serializer_or_field=serializers.ListField)
     def get_groups(self, obj):
         return [g.name for g in obj.groups.all()]
 
+    @swagger_serializer_method(serializer_or_field=serializers.ListField)
     def get_users(self, obj):
         return [u.username for u in obj.users.all()]
Repository: netbox-community/netbox
Issue: Allow MultiObjectVar to accept PKs higher than 9 when script is called with a single URL param

### NetBox version

v3.2.3

### Python version

3.9

### Steps to Reproduce

0. Start with a clean, empty installation
1. Create a custom script `testscript.py`:
> ```python
> from extras.scripts import *
> from dcim.models import Device
> 
> class MultiObjectVarTest(Script):
>     devices = MultiObjectVar (model=Device)
> 
>     def run(data, commit):
>         pass
> ```
2. Create a dummy `Manufacturer` and `DeviceType`
3. Fill the database with multiple `Device` objects (more than 10)
4. Confirm that devices have at least picked up PKs 1 thru 10
5. Access `http://netbox/extras/scripts/testscript.MultiObjectVarTest/?devices=1` (1 is a valid, existing device pk) -> Confirm that the `devices` field is properly populated with the `Device` which has pk 1
6. Access `http://netbox/extras/scripts/testscript.MultiObjectVarTest/?devices=10` (10 is also a valid, existing device pk) -> Notice that the `devices` field is now empty


### Expected Behavior

Access `http://netbox/extras/scripts/testscript.MultiObjectVarTest/?devices=10` (10 is a valid, existing device pk) and confirm that the `devices` field is properly populated with the `Device` which has pk 10

### Observed Behavior

The devices field is not populated with the `Device` which has PK 10, but can be searched manually.


I believe that this is due to the widget only prefetching the first few items and not knowing what to do with higher-count objects.

Changed files:
netbox/utilities/forms/fields/dynamic.py

diff --git a/netbox/utilities/forms/fields/dynamic.py b/netbox/utilities/forms/fields/dynamic.py
index f83fc6a7c..dc3bab9fc 100644
--- a/netbox/utilities/forms/fields/dynamic.py
+++ b/netbox/utilities/forms/fields/dynamic.py
@@ -88,7 +88,12 @@ class DynamicModelChoiceMixin:
         # Modify the QuerySet of the field before we return it. Limit choices to any data already bound: Options
         # will be populated on-demand via the APISelect widget.
         data = bound_field.value()
+
         if data:
+            # When the field is multiple choice pass the data as a list if it's not already
+            if isinstance(bound_field.field, DynamicModelMultipleChoiceField) and not type(data) is list:
+                data = [data]
+
             field_name = getattr(self, 'to_field_name') or 'pk'
             filter = self.filter(field_name=field_name)
             try:
Repository: netbox-community/netbox
Issue: API created sites duplicated in search results (both GUI and API)

### NetBox version

v3.2.3

### Python version

3.9

### Steps to Reproduce

* Create RIR
* Create two ASNs 123 & 1234
* Create site test123 with both ASNs assigned 
* Search for Sites with the q value "123"

### Expected Behavior

Only showing one result for the site

### Observed Behavior

Duplicate site referring to the same site id.

Changed files:
netbox/dcim/filtersets.py

diff --git a/netbox/dcim/filtersets.py b/netbox/dcim/filtersets.py
index d57d0a59b..f052a8be9 100644
--- a/netbox/dcim/filtersets.py
+++ b/netbox/dcim/filtersets.py
@@ -163,7 +163,7 @@ class SiteFilterSet(NetBoxModelFilterSet, TenancyFilterSet, ContactModelFilterSe
             qs_filter |= Q(asns__asn=int(value.strip()))
         except ValueError:
             pass
-        return queryset.filter(qs_filter)
+        return queryset.filter(qs_filter).distinct()
 
 
 class LocationFilterSet(TenancyFilterSet, ContactModelFilterSet, OrganizationalModelFilterSet):
Repository: netbox-community/netbox
Issue: Showing prefix of the site that has many prefixes is slow

### NetBox version

v3.0.3

### Python version

3.9

### Steps to Reproduce

1. Add a site and some prefixes under the site. (The site has 48 prefixes in our environment, and some of them have some child prefixes. One of them has over 30 child prefixes.)
2. Click site from the left menu, select the added site, click prefix on the right corner of the site page.


### Expected Behavior

The prefix page of the site shows within seconds.

### Observed Behavior

It took around 40 seconds to show 50 prefixes on a page.

Calculation of prefix utilization seems to consume a lot of execution time: after hiding the utilization bar (%) by "Configure Table," it took 1 second to show.
I'm preparing a Pull Request to optimize the utilization calculation.


Changed files:
netbox/ipam/models/ip.py

diff --git a/netbox/ipam/models/ip.py b/netbox/ipam/models/ip.py
index 3e2e671ca..b5360a7b7 100644
--- a/netbox/ipam/models/ip.py
+++ b/netbox/ipam/models/ip.py
@@ -487,11 +487,9 @@ class Prefix(PrimaryModel):
             utilization = int(float(child_prefixes.size) / self.prefix.size * 100)
         else:
             # Compile an IPSet to avoid counting duplicate IPs
-            child_ips = netaddr.IPSet()
-            for iprange in self.get_child_ranges():
-                child_ips.add(iprange.range)
-            for ip in self.get_child_ips():
-                child_ips.add(ip.address.ip)
+            child_ips = netaddr.IPSet(
+                [_.range for _ in self.get_child_ranges()] + [_.address.ip for _ in self.get_child_ips()]
+            )
 
             prefix_size = self.prefix.size
             if self.prefix.version == 4 and self.prefix.prefixlen < 31 and not self.is_pool:
Repository: netbox-community/netbox
Issue: Device table not sortable by status

### NetBox version

v3.0.9

### Python version

3.8

### Steps to Reproduce

1. Click on sidebar `Devices` -> `Device Bays`
2. On the displayed table's header click on `Status`

### Expected Behavior

Table is displayed reordered, by status

### Observed Behavior

Server Error

Changed files:
netbox/dcim/tables/devices.py

diff --git a/netbox/dcim/tables/devices.py b/netbox/dcim/tables/devices.py
index 675f7d777..c8559458c 100644
--- a/netbox/dcim/tables/devices.py
+++ b/netbox/dcim/tables/devices.py
@@ -653,7 +653,8 @@ class DeviceBayTable(DeviceComponentTable):
         }
     )
     status = tables.TemplateColumn(
-        template_code=DEVICEBAY_STATUS
+        template_code=DEVICEBAY_STATUS,
+        order_by=Accessor('installed_device__status')
     )
     installed_device = tables.Column(
         linkify=True
Repository: netbox-community/netbox
Issue: Cluster count missing from tenant api output

### NetBox version

3.1.5

### Python version

3.9

### Steps to Reproduce

Assign a Cluster to a Tenant. 
Retrieve Tenant details via API i.e. /api/tenancy/tenants/5/

### Expected Behavior

cluster_count is returned as part of the API response

### Observed Behavior

cluster_count is missing from the API response

Changed files:
netbox/tenancy/api/views.py

diff --git a/netbox/tenancy/api/views.py b/netbox/tenancy/api/views.py
index 50b188b5f..c336c88b6 100644
--- a/netbox/tenancy/api/views.py
+++ b/netbox/tenancy/api/views.py
@@ -7,7 +7,7 @@ from ipam.models import IPAddress, Prefix, VLAN, VRF
 from tenancy import filtersets
 from tenancy.models import *
 from utilities.utils import count_related
-from virtualization.models import VirtualMachine
+from virtualization.models import VirtualMachine, Cluster
 from . import serializers
 
 
@@ -47,7 +47,8 @@ class TenantViewSet(CustomFieldModelViewSet):
         site_count=count_related(Site, 'tenant'),
         virtualmachine_count=count_related(VirtualMachine, 'tenant'),
         vlan_count=count_related(VLAN, 'tenant'),
-        vrf_count=count_related(VRF, 'tenant')
+        vrf_count=count_related(VRF, 'tenant'),
+        cluster_count=count_related(Cluster, 'tenant')
     )
     serializer_class = serializers.TenantSerializer
     filterset_class = filtersets.TenantFilterSet
Repository: netbox-community/netbox
Issue: No virtual chassis name in rack view

### NetBox version

v3.1.4

### Python version

3.8

### Steps to Reproduce

1. Create a rack
2. Add 2 devices with no name in rack
3. Create virtual chassis
4. Add devices as member
5. Open rack

### Expected Behavior

The name displayed should be something like [virtual-chassis name]:[virtual-chassis position], like in older versions (before 3.1)

### Observed Behavior

Device Type name is being displayed

Changed files:
netbox/dcim/svg.py

diff --git a/netbox/dcim/svg.py b/netbox/dcim/svg.py
index e19e8fa2f..1058d8385 100644
--- a/netbox/dcim/svg.py
+++ b/netbox/dcim/svg.py
@@ -19,7 +19,12 @@ __all__ = (
 
 
 def get_device_name(device):
-    return device.name or str(device.device_type)
+    if device.virtual_chassis:
+        return f'{device.virtual_chassis.name}:{device.vc_position}'
+    elif device.name:
+        return device.name
+    else:
+        return str(device.device_type)
 
 
 class RackElevationSVG:
Repository: netbox-community/netbox
Issue: Filter view for Locations is missing tags field

### NetBox version

v3.1.5

### Python version

3.8

### Steps to Reproduce

Navigate to Organization -> Locations.
e.g https://demo.netbox.dev/dcim/locations/
and then open the filters tab.

### Expected Behavior

Under the first search field there should be a field for tags to compliment the Location model which was extended to include a tag field.

### Observed Behavior

Other then the missing GUI field for tags, the filtering is working as expected in the background.
Verified by trying https://demo.netbox.dev/dcim/locations/?tag=my-tag

Changed files:
netbox/dcim/forms/filtersets.py

diff --git a/netbox/dcim/forms/filtersets.py b/netbox/dcim/forms/filtersets.py
index cb9575d42..f4b4c0a87 100644
--- a/netbox/dcim/forms/filtersets.py
+++ b/netbox/dcim/forms/filtersets.py
@@ -152,7 +152,7 @@ class SiteFilterForm(TenancyFilterForm, CustomFieldModelFilterForm):
 class LocationFilterForm(TenancyFilterForm, CustomFieldModelFilterForm):
     model = Location
     field_groups = [
-        ['q'],
+        ['q', 'tag'],
         ['region_id', 'site_group_id', 'site_id', 'parent_id'],
         ['tenant_group_id', 'tenant_id'],
     ]
Repository: netbox-community/netbox
Issue: Circuit Install Date set to NULL exports to csv as â€”

### NetBox version

v3.1.6

### Python version

3.9

### Steps to Reproduce

1. Create a circuit with no Install Date
2. Export circuits to CSV
3. Notice Install Date Field value displayed as `â€”`

### Expected Behavior

Install Date shows as NULL or empty

### Observed Behavior

Install Date shows as `â€”`

Changed files:
netbox/utilities/tables.py

diff --git a/netbox/utilities/tables.py b/netbox/utilities/tables.py
index c640e0e85..4821551b9 100644
--- a/netbox/utilities/tables.py
+++ b/netbox/utilities/tables.py
@@ -4,10 +4,13 @@ from django.contrib.auth.models import AnonymousUser
 from django.contrib.contenttypes.fields import GenericForeignKey
 from django.contrib.contenttypes.models import ContentType
 from django.core.exceptions import FieldDoesNotExist
+from django.db.models import DateField, DateTimeField
 from django.db.models.fields.related import RelatedField
 from django.urls import reverse
+from django.utils.formats import date_format
 from django.utils.safestring import mark_safe
 from django_tables2 import RequestConfig
+from django_tables2.columns import library
 from django_tables2.data import TableQuerysetData
 from django_tables2.utils import Accessor
 
@@ -205,6 +208,42 @@ class TemplateColumn(tables.TemplateColumn):
         return ret
 
 
+@library.register
+class DateColumn(tables.DateColumn):
+    """
+    Overrides the default implementation of DateColumn to better handle null values, returning a default value for
+    tables and null when exporting data. It is registered in the tables library to use this class instead of the
+    default, making this behavior consistent in all fields of type DateField.
+    """
+
+    def value(self, value):
+        return value
+
+    @classmethod
+    def from_field(cls, field, **kwargs):
+        if isinstance(field, DateField):
+            return cls(**kwargs)
+
+
+@library.register
+class DateTimeColumn(tables.DateTimeColumn):
+    """
+    Overrides the default implementation of DateTimeColumn to better handle null values, returning a default value for
+    tables and null when exporting data. It is registered in the tables library to use this class instead of the
+    default, making this behavior consistent in all fields of type DateTimeField.
+    """
+
+    def value(self, value):
+        if value:
+            return date_format(value, format="SHORT_DATETIME_FORMAT")
+        return None
+
+    @classmethod
+    def from_field(cls, field, **kwargs):
+        if isinstance(field, DateTimeField):
+            return cls(**kwargs)
+
+
 class ButtonsColumn(tables.TemplateColumn):
     """
     Render edit, delete, and changelog buttons for an object.
Repository: netbox-community/netbox
Issue: Contact assignment amounts not shown during contact global search

### NetBox version

v3.1.7

### Python version

3.8

### Steps to Reproduce

1. Search for a name in global search
2. View the "assignments" column


### Expected Behavior

Number of assignments should be shown.

### Observed Behavior

Instead of the number of assignments being shown, a hyphen is displayed instead.

Changed files:
netbox/netbox/constants.py

diff --git a/netbox/netbox/constants.py b/netbox/netbox/constants.py
index be5f12980..e29da6617 100644
--- a/netbox/netbox/constants.py
+++ b/netbox/netbox/constants.py
@@ -18,7 +18,7 @@ from ipam.filtersets import (
 from ipam.models import Aggregate, ASN, IPAddress, Prefix, VLAN, VRF
 from ipam.tables import AggregateTable, ASNTable, IPAddressTable, PrefixTable, VLANTable, VRFTable
 from tenancy.filtersets import ContactFilterSet, TenantFilterSet
-from tenancy.models import Contact, Tenant
+from tenancy.models import Contact, Tenant, ContactAssignment
 from tenancy.tables import ContactTable, TenantTable
 from utilities.utils import count_related
 from virtualization.filtersets import ClusterFilterSet, VirtualMachineFilterSet
@@ -186,7 +186,7 @@ SEARCH_TYPES = OrderedDict((
         'url': 'tenancy:tenant_list',
     }),
     ('contact', {
-        'queryset': Contact.objects.prefetch_related('group', 'assignments'),
+        'queryset': Contact.objects.prefetch_related('group', 'assignments').annotate(assignment_count=count_related(ContactAssignment, 'contact')),
         'filterset': ContactFilterSet,
         'table': ContactTable,
         'url': 'tenancy:contact_list',
Repository: netbox-community/netbox
Issue: Devices with Images on the rear side are not clickable in the rack view svg.

### NetBox version

v3.1.9

### Python version

3.9

### Steps to Reproduce

1. create a rack
2. create a full-depth device type
3. add front and read pictures to the device type
4. create a device with the created device type in the rack
5. look at the front and rear of the device in the SVG with images enabled.

### Expected Behavior

Front as well as rear should have a link to the device, independently of whether images are shown or not.

### Observed Behavior

Only the front can be clicked. When only labels are show the Link can be clicked.

Changed files:
netbox/dcim/svg.py

diff --git a/netbox/dcim/svg.py b/netbox/dcim/svg.py
index e333320b6..7cd0fa417 100644
--- a/netbox/dcim/svg.py
+++ b/netbox/dcim/svg.py
@@ -146,10 +146,10 @@ class RackElevationSVG:
                 class_='device-image'
             )
             image.fit(scale='slice')
-            drawing.add(image)
-            drawing.add(drawing.text(get_device_name(device), insert=text, stroke='black',
-                        stroke_width='0.2em', stroke_linejoin='round', class_='device-image-label'))
-            drawing.add(drawing.text(get_device_name(device), insert=text, fill='white', class_='device-image-label'))
+            link.add(image)
+            link.add(drawing.text(get_device_name(device), insert=text, stroke='black',
+                     stroke_width='0.2em', stroke_linejoin='round', class_='device-image-label'))
+            link.add(drawing.text(get_device_name(device), insert=text, fill='white', class_='device-image-label'))
 
     @staticmethod
     def _draw_empty(drawing, rack, start, end, text, id_, face_id, class_, reservation):
Repository: netbox-community/netbox
Issue: Individual ASN view broken when sorting by circuit count

### NetBox version

v3.2.2

### Python version

3.8

### Steps to Reproduce

1. Connect to Netbox and authenticated yourself.
2. Navigate to any kind of view that displays a link to an ASN object, and click on that link


### Expected Behavior

Display of the detail page of the selected ASN object.

### Observed Behavior

A field error exception was raised:

---
<class 'django.core.exceptions.FieldError'>

Cannot resolve keyword 'count_circuits' into field. Choices are: account, admin_contact, asn, asns, circuits, comments, contacts, created, custom_field_data, id, journal_entries, last_updated, name, networks, noc_contact, portal_url, slug, tagged_items, tags

Python version: 3.8.10
NetBox version: 3.2.2

---

Please note that in our context unauthenticated users have a read only rights to most object types and that, strangely, **only authenticated users trigger this behaviour.**

Changed files:
netbox/ipam/views.py

diff --git a/netbox/ipam/views.py b/netbox/ipam/views.py
index d5c1e670e..84f6db6d5 100644
--- a/netbox/ipam/views.py
+++ b/netbox/ipam/views.py
@@ -4,7 +4,7 @@ from django.db.models.expressions import RawSQL
 from django.shortcuts import get_object_or_404, redirect, render
 from django.urls import reverse
 
-from circuits.models import Provider
+from circuits.models import Provider, Circuit
 from circuits.tables import ProviderTable
 from dcim.filtersets import InterfaceFilterSet
 from dcim.models import Interface, Site
@@ -225,7 +225,9 @@ class ASNView(generic.ObjectView):
         sites_table.configure(request)
 
         # Gather assigned Providers
-        providers = instance.providers.restrict(request.user, 'view')
+        providers = instance.providers.restrict(request.user, 'view').annotate(
+            count_circuits=count_related(Circuit, 'provider')
+        )
         providers_table = ProviderTable(providers, user=request.user)
         providers_table.configure(request)
Repository: netbox-community/netbox
Issue: Exception when adding ?sort=ports to Service and ServiceTemplate list view

### NetBox version

v3.2.4

### Python version

3.8

### Steps to Reproduce

1. Login netbox
2. Select "IPAM"
3. Select "Service Templates" or "Services"
4. Append ?sort=ports to the URL

### Expected Behavior

Show the list of configured templates.

### Observed Behavior

<class 'django.core.exceptions.FieldError'>

Cannot resolve keyword 'port_list' into field. Choices are: created, custom_field_data, description, id, journal_entries, last_updated, name, ports, protocol, tagged_items, tags

Python version: 3.8.10
NetBox version: 3.2.4

Changed files:
netbox/ipam/tables/services.py

diff --git a/netbox/ipam/tables/services.py b/netbox/ipam/tables/services.py
index 8c81a28c2..58d0a9aff 100644
--- a/netbox/ipam/tables/services.py
+++ b/netbox/ipam/tables/services.py
@@ -14,7 +14,8 @@ class ServiceTemplateTable(NetBoxTable):
         linkify=True
     )
     ports = tables.Column(
-        accessor=tables.A('port_list')
+        accessor=tables.A('port_list'),
+        order_by=tables.A('ports'),
     )
     tags = columns.TagColumn(
         url_name='ipam:servicetemplate_list'
@@ -35,7 +36,8 @@ class ServiceTable(NetBoxTable):
         order_by=('device', 'virtual_machine')
     )
     ports = tables.Column(
-        accessor=tables.A('port_list')
+        accessor=tables.A('port_list'),
+        order_by=tables.A('ports'),
     )
     tags = columns.TagColumn(
         url_name='ipam:service_list'
Repository: netbox-community/netbox
Issue: List of services associated to IP address is missing services listening on "All IPs"

### NetBox version

v3.2.4

### Python version

3.8

### Steps to Reproduce

1. Create a Device or VM
2. Add Interface(s) and IP(s)
3. Add a Service and set an IP Address
4. Add another Service and leave IP Address empty (listening on "All IPs")
5. Open IP address page ( /ipam/ip-addresses/XXX/ )

### Expected Behavior

Show all Services.

### Observed Behavior

Services listening on "All IPs" are missing.

Related to: #8922

Changed files:
netbox/ipam/views.py

diff --git a/netbox/ipam/views.py b/netbox/ipam/views.py
index 84f6db6d5..a01f2d052 100644
--- a/netbox/ipam/views.py
+++ b/netbox/ipam/views.py
@@ -7,12 +7,12 @@ from django.urls import reverse
 from circuits.models import Provider, Circuit
 from circuits.tables import ProviderTable
 from dcim.filtersets import InterfaceFilterSet
-from dcim.models import Interface, Site
+from dcim.models import Interface, Site, Device
 from dcim.tables import SiteTable
 from netbox.views import generic
 from utilities.utils import count_related
 from virtualization.filtersets import VMInterfaceFilterSet
-from virtualization.models import VMInterface
+from virtualization.models import VMInterface, VirtualMachine
 from . import filtersets, forms, tables
 from .constants import *
 from .models import *
@@ -676,7 +676,19 @@ class IPAddressView(generic.ObjectView):
         related_ips_table = tables.IPAddressTable(related_ips, orderable=False)
         related_ips_table.configure(request)
 
-        services = Service.objects.restrict(request.user, 'view').filter(ipaddresses=instance)
+        # Find services belonging to the IP
+        service_filter = Q(ipaddresses=instance)
+
+        # Find services listening on all IPs on the assigned device/vm
+        if instance.assigned_object and instance.assigned_object.parent_object:
+            parent_object = instance.assigned_object.parent_object
+
+            if isinstance(parent_object, VirtualMachine):
+                service_filter |= (Q(virtual_machine=parent_object) & Q(ipaddresses=None))
+            elif isinstance(parent_object, Device):
+                service_filter |= (Q(device=parent_object) & Q(ipaddresses=None))
+
+        services = Service.objects.restrict(request.user, 'view').filter(service_filter)
 
         return {
             'parent_prefixes_table': parent_prefixes_table,
Repository: netbox-community/netbox
Issue: Interface PoE type reference error

### NetBox version

v3.3.2

### Python version

3.10

### Steps to Reproduce

When choosing interface PoE type, select `Passive 48V (2-pair)`, option `Passive 48V (4-pair)` will be chosen instead.

PoE type of `Passive 48V (2-pair)` could not be selected as `Passive 48V (4-pair)` had the same key for that value.

### Expected Behavior

Option `Passive 48V (2-pair)` should be selected.

### Observed Behavior

Option `Passive 48V (4-pair)` will be chosen instead.

Changed files:
netbox/dcim/choices.py

diff --git a/netbox/dcim/choices.py b/netbox/dcim/choices.py
index 019ae09a4..7d35a40f9 100644
--- a/netbox/dcim/choices.py
+++ b/netbox/dcim/choices.py
@@ -1096,7 +1096,7 @@ class InterfacePoETypeChoices(ChoiceSet):
                 (PASSIVE_24V_2PAIR, 'Passive 24V (2-pair)'),
                 (PASSIVE_24V_4PAIR, 'Passive 24V (4-pair)'),
                 (PASSIVE_48V_2PAIR, 'Passive 48V (2-pair)'),
-                (PASSIVE_48V_2PAIR, 'Passive 48V (4-pair)'),
+                (PASSIVE_48V_4PAIR, 'Passive 48V (4-pair)'),
             )
         ),
     )
Repository: netbox-community/netbox
Issue: 'ui_visibility' help is missing in Custom Fields Bulk Import form

### NetBox version

v3.3.2

### Python version

3.10

### Steps to Reproduce

1. Browse to the Custom Field Bulk Import
2. Reach the documentation of the `ui_visibility` field
3. Notice that the blue help button is missing to describe the available choices


### Expected Behavior

A blue help button should be present to describe the available choices.

### Observed Behavior

The `ui_visibility` field should be a `CSVChoiceField` to allow for the Choices modal to display with its button.

Changed files:
netbox/extras/forms/bulk_import.py

diff --git a/netbox/extras/forms/bulk_import.py b/netbox/extras/forms/bulk_import.py
index d9148a5c3..e83cac3b9 100644
--- a/netbox/extras/forms/bulk_import.py
+++ b/netbox/extras/forms/bulk_import.py
@@ -3,7 +3,7 @@ from django.contrib.contenttypes.models import ContentType
 from django.contrib.postgres.forms import SimpleArrayField
 from django.utils.safestring import mark_safe
 
-from extras.choices import CustomFieldTypeChoices
+from extras.choices import CustomFieldVisibilityChoices, CustomFieldTypeChoices
 from extras.models import *
 from extras.utils import FeatureQuery
 from utilities.forms import CSVChoiceField, CSVContentTypeField, CSVModelForm, CSVMultipleContentTypeField, SlugField
@@ -38,6 +38,10 @@ class CustomFieldCSVForm(CSVModelForm):
         required=False,
         help_text='Comma-separated list of field choices'
     )
+    ui_visibility = CSVChoiceField(
+        choices=CustomFieldVisibilityChoices,
+        help_text='How the custom field is displayed in the user interface'
+    )
 
     class Meta:
         model = CustomField
Repository: netbox-community/netbox
Issue: Device filter with non-racked devices

### NetBox version

v3.2.4

### Python version

3.10

### Steps to Reproduce

1. Go to a location with more than 10 non-racked devices
2. Click **View full list**

### Expected Behavior

The filter should show non-racked devices

### Observed Behavior

A view of devices with the filters for *Location: foobar* and *Rack: None* show no devices

Changed files:
netbox/dcim/views.py

diff --git a/netbox/dcim/views.py b/netbox/dcim/views.py
index 6ee74377a..b1f94d785 100644
--- a/netbox/dcim/views.py
+++ b/netbox/dcim/views.py
@@ -355,7 +355,7 @@ class SiteView(generic.ObjectView):
 
         nonracked_devices = Device.objects.filter(
             site=instance,
-            position__isnull=True,
+            rack__isnull=True,
             parent_bay__isnull=True
         ).prefetch_related('device_type__manufacturer', 'parent_bay', 'device_role')
 
@@ -450,7 +450,7 @@ class LocationView(generic.ObjectView):
 
         nonracked_devices = Device.objects.filter(
             location=instance,
-            position__isnull=True,
+            rack__isnull=True,
             parent_bay__isnull=True
         ).prefetch_related('device_type__manufacturer', 'parent_bay', 'device_role')
Repository: netbox-community/netbox
Issue: Finish implemantation of #10156, link on nodes in cable-trace svg still open in new window

### NetBox version

v3.3.4

### Python version

3.10

### Steps to Reproduce

Click on a node on a cable trace. The link target is opened in a new window/tab.
The connector ans wireless link were already fixed with #10156.

I have a PR ready for this.

### Expected Behavior

Link on a node on a cable trace open in the same window.

### Observed Behavior

Link on a node on a cable trace open in a new tab/window.

Changed files:
netbox/dcim/svg/cables.py

diff --git a/netbox/dcim/svg/cables.py b/netbox/dcim/svg/cables.py
index 3872bc4fe..9a847acc9 100644
--- a/netbox/dcim/svg/cables.py
+++ b/netbox/dcim/svg/cables.py
@@ -35,7 +35,7 @@ class Node(Hyperlink):
     """
 
     def __init__(self, position, width, url, color, labels, radius=10, **extra):
-        super(Node, self).__init__(href=url, target='_blank', **extra)
+        super(Node, self).__init__(href=url, target='_parent', **extra)
 
         x, y = position
Repository: netbox-community/netbox
Issue: DataSource logs wrong count for deleted Datafiles in sync

### NetBox version

v3.5-beta1

### Python version

3.10

### Steps to Reproduce

-

### Expected Behavior

Log contains count for deleted files

### Observed Behavior

Count for updated files is logged twice


Changed files:
netbox/core/models/data.py

diff --git a/netbox/core/models/data.py b/netbox/core/models/data.py
index 070ae52e0..1738190ee 100644
--- a/netbox/core/models/data.py
+++ b/netbox/core/models/data.py
@@ -176,7 +176,7 @@ class DataSource(JobsMixin, PrimaryModel):
 
             # Bulk delete deleted files
             deleted_count, _ = DataFile.objects.filter(pk__in=deleted_file_ids).delete()
-            logger.debug(f"Deleted {updated_count} files")
+            logger.debug(f"Deleted {deleted_count} files")
 
             # Walk the local replication to find new files
             new_paths = self._walk(local_path) - known_paths
Repository: netbox-community/netbox
Issue: Site filter does not apply when clicking on VLAN Groups from the Site view page

### NetBox version

v3.5.0

### Python version

3.8

### Steps to Reproduce

1. Open a site (eg. http://netbox/dcim/sites/1350/)
2. Click on VLAN Groups under Related Objects

### Expected Behavior

Only the VLAN Groups associated to that site should be displayed.

### Observed Behavior

All VLAN groups are shown.
It looks like the filter parameter in the URL is for site_id and it should be for site.
eg. should be http://netbox/ipam/vlan-groups/?site=1350 not http://netbox/ipam/vlan-groups/?site_id=1350

Changed files:
netbox/dcim/views.py

diff --git a/netbox/dcim/views.py b/netbox/dcim/views.py
index ee97900a4..bcbbf1739 100644
--- a/netbox/dcim/views.py
+++ b/netbox/dcim/views.py
@@ -371,7 +371,7 @@ class SiteView(generic.ObjectView):
             (VLANGroup.objects.restrict(request.user, 'view').filter(
                 scope_type=ContentType.objects.get_for_model(Site),
                 scope_id=instance.pk
-            ), 'site_id'),
+            ), 'site'),
             (VLAN.objects.restrict(request.user, 'view').filter(site=instance), 'site_id'),
             # Circuits
             (Circuit.objects.restrict(request.user, 'view').filter(terminations__site=instance).distinct(), 'site_id'),
Repository: netbox-community/netbox
Issue: Circuit Provider Account field required API not in GUI

### NetBox version

v3.5.0

### Python version

3.8

### Steps to Reproduce

1. Use the REST API to create a new circuit
`
{
    "cid": "12345",
    "provider": 1,
    "type": 1,
}
`
Error: {"provider_account":["This field is required."]}
2. Use the GUI to add circuit, `provider_account` is an optional field
3. Try to add circuit with provider_account set as 0
`
{
    "cid": "12345",
    "provider": 1,
    "type": 1,
    "provider_account": 0
}
`
Error: {"provider_account":["Related object not found using the provided numeric ID: 0"]}
4. Read existing migrated circuit from netbox
` ...."provider_account":null ...
` 

### Expected Behavior

The circuit `provider_account` field should be optional in the RESTAPI as it current is in the GUI.

### Observed Behavior

Error was shown requiring the provider_account field to be defined

Changed files:
netbox/circuits/forms/bulk_import.py, netbox/circuits/api/serializers.py

diff --git a/netbox/circuits/api/serializers.py b/netbox/circuits/api/serializers.py
index 5635b6730..f4abda645 100644
--- a/netbox/circuits/api/serializers.py
+++ b/netbox/circuits/api/serializers.py
@@ -106,7 +106,7 @@ class CircuitCircuitTerminationSerializer(WritableNestedSerializer):
 class CircuitSerializer(NetBoxModelSerializer):
     url = serializers.HyperlinkedIdentityField(view_name='circuits-api:circuit-detail')
     provider = NestedProviderSerializer()
-    provider_account = NestedProviderAccountSerializer()
+    provider_account = NestedProviderAccountSerializer(required=False, allow_null=True)
     status = ChoiceField(choices=CircuitStatusChoices, required=False)
     type = NestedCircuitTypeSerializer()
     tenant = NestedTenantSerializer(required=False, allow_null=True)
diff --git a/netbox/circuits/forms/bulk_import.py b/netbox/circuits/forms/bulk_import.py
index d55831008..3941ef574 100644
--- a/netbox/circuits/forms/bulk_import.py
+++ b/netbox/circuits/forms/bulk_import.py
@@ -74,7 +74,8 @@ class CircuitImportForm(NetBoxModelImportForm):
     provider_account = CSVModelChoiceField(
         queryset=ProviderAccount.objects.all(),
         to_field_name='name',
-        help_text=_('Assigned provider account')
+        help_text=_('Assigned provider account'),
+        required=False
     )
     type = CSVModelChoiceField(
         queryset=CircuitType.objects.all(),
Repository: netbox-community/netbox
Issue: Virtual Chassis master field cannot be null according to the API

### NetBox version

v3.2.9

### Python version

3.10

### Steps to Reproduce

1. Submit API write request to the VirtualChassis with "master": null in it

### Expected Behavior

Requests is accepted and the master is unset for the specific VirtualChassis

### Observed Behavior

HTTP 400 is returned with the message: `[{"master":["This field may not be null."]}]`

Changed files:
netbox/dcim/tests/test_api.py, netbox/dcim/api/serializers.py

diff --git a/netbox/dcim/api/serializers.py b/netbox/dcim/api/serializers.py
index 79f5339ad..897ee4ca3 100644
--- a/netbox/dcim/api/serializers.py
+++ b/netbox/dcim/api/serializers.py
@@ -1076,7 +1076,7 @@ class CablePathSerializer(serializers.ModelSerializer):
 
 class VirtualChassisSerializer(NetBoxModelSerializer):
     url = serializers.HyperlinkedIdentityField(view_name='dcim-api:virtualchassis-detail')
-    master = NestedDeviceSerializer(required=False)
+    master = NestedDeviceSerializer(required=False, allow_null=True, default=None)
     member_count = serializers.IntegerField(read_only=True)
 
     class Meta:
diff --git a/netbox/dcim/tests/test_api.py b/netbox/dcim/tests/test_api.py
index acd52178d..2697c29b2 100644
--- a/netbox/dcim/tests/test_api.py
+++ b/netbox/dcim/tests/test_api.py
@@ -2057,6 +2057,7 @@ class VirtualChassisTest(APIViewTestCases.APIViewTestCase):
 
         cls.bulk_update_data = {
             'domain': 'newdomain',
+            'master': None
         }
Repository: nltk/nltk
Issue: AttributeError: 'itertools.chain' object has no attribute 'lookup'

nltk version: 3.7.
python version: 3.9.15
From the following code:

```
padded_line = [list(pad_both_ends(word_tokenize(input_text), n=N))]
train_data, vocab = padded_everygram_pipeline(order=N, text=padded_line)
lm = Lidstone(gamma=0.2, vocabulary=vocab, order=N)
lm.fit(text=train_data)
```

where input_text is a long string and N as in the Ngram model. From the last line of code above, I get the following error:

>lm.fit(text=train_data)
>  File "env\\lib\\site-packages\\nltk\\lm\\api.py", line 110, in fit
>  self.counts.update(self.vocab.lookup(sent) for sent in text)
>  File "env\\lib\\site-packages\\nltk\\lm\\counter.py", line 115, in update
>    for sent in ngram_text:
>  File "env\\lib\\site-packages\\nltk\\lm\\api.py", line 110, in <genexpr>
>    self.counts.update(self.vocab.lookup(sent) for sent in text)
> AttributeError: 'itertools.chain' object has no attribute 'lookup'

Can anyone fix this error for me?

Changed files:
nltk/lm/api.py

diff --git a/nltk/lm/api.py b/nltk/lm/api.py
index e7a6dca1b..bf1322aca 100644
--- a/nltk/lm/api.py
+++ b/nltk/lm/api.py
@@ -7,6 +7,7 @@
 """Language Model Interface."""
 
 import random
+import warnings
 from abc import ABCMeta, abstractmethod
 from bisect import bisect
 from itertools import accumulate
@@ -83,7 +84,7 @@ class LanguageModel(metaclass=ABCMeta):
             of creating a new one when training.
         :type vocabulary: `nltk.lm.Vocabulary` or None
         :param counter: If provided, use this object to count ngrams.
-        :type vocabulary: `nltk.lm.NgramCounter` or None
+        :type counter: `nltk.lm.NgramCounter` or None
         :param ngrams_fn: If given, defines how sentences in training text are turned to ngram
             sequences.
         :type ngrams_fn: function or None
@@ -91,6 +92,12 @@ class LanguageModel(metaclass=ABCMeta):
         :type pad_fn: function or None
         """
         self.order = order
+        if vocabulary and not isinstance(vocabulary, Vocabulary):
+            warnings.warn(
+                f"The `vocabulary` argument passed to {self.__class__.__name__!r} "
+                "must be an instance of `nltk.lm.Vocabulary`.",
+                stacklevel=3,
+            )
         self.vocab = Vocabulary() if vocabulary is None else vocabulary
         self.counts = NgramCounter() if counter is None else counter