internlm/SWE-Fixer-Train-110K huggingface dataset:
Repository: netbox-community/netbox

Issue:
Empty location field breaks bulk-import
### NetBox version

v3.6.2

### Python version

3.8

### Steps to Reproduce

Given data:
site named import-test
rack named import-rack in site import-test
device role named import-role
manufacturer named import-manufacturer
device-type named import-device with manufacturer of import-manufacturer

CSV data:
```
name,role,serial,description,manufacturer,device_type,airflow,status,site,location,rack,position,face
,import-role,3412341,,import-manufacturer,import-device,front-to-rear,active,import-test,,import-rack,,
,import-role,kljadf123,,import-manufacturer,import-device,front-to-rear,active,import-test,,import-rack,,
```

Steps to replicate import failure:
Devices -> Devices -> Import.
Paste data to direct import text box.
Submit.


### Expected Behavior

Devices from csv would be imported.

### Observed Behavior

![image](https://github.com/netbox-community/netbox/assets/11653069/d1b7767f-94d1-4f50-ac9a-cc1efebf0282)

Removing the location field (and leaving other empty fields) successfully imports devices.


New CSV:
```
name,role,serial,description,manufacturer,device_type,airflow,status,site,rack,position,face
,import-role,3412341,,import-manufacturer,import-device,front-to-rear,active,import-test,import-rack,,
,import-role,kljadf123,,import-manufacturer,import-device,front-to-rear,active,import-test,import-rack,,
```

Devices import as expected.



Discussion:

Resolving patch:
diff --git a/netbox/dcim/forms/bulk_import.py b/netbox/dcim/forms/bulk_import.py
--- a/netbox/dcim/forms/bulk_import.py
+++ b/netbox/dcim/forms/bulk_import.py
@@ -549,9 +549,9 @@ def __init__(self, data=None, *args, **kwargs):
             params = {
                 f"site__{self.fields['site'].to_field_name}": data.get('site'),
             }
-            if 'location' in data:
+            if location := data.get('location'):
                 params.update({
-                    f"location__{self.fields['location'].to_field_name}": data.get('location'),
+                    f"location__{self.fields['location'].to_field_name}": location,
                 })
             self.fields['rack'].queryset = self.fields['rack'].queryset.filter(**params)
 


Test patch:
Repository: netbox-community/netbox

Issue:
Add DATA_UPLOAD_MAX_MEMORY_SIZE as an configurable variable
### NetBox version

v3.5.3

### Feature type

New functionality

### Proposed functionality

Add to settings.py: DATA_UPLOAD_MAX_MEMORY_SIZE = getattr(configuration, 'DATA_UPLOAD_MAX_MEMORY_SIZE', 2621440)

### Use case

We use custom scripts, called through the API for data validation, and there is an hard limit on 2,6MB on the payload (body). We have cases were we are well above that (posting an JSON with all VM's fron an vCenter for validation), and I therefore suggest that variable is being added to the settings.py just as the file upload variable. Tests by setting this in settings.py our selves solves the challenge, but one must remember this when upgrading....

### Database changes

None

### External dependencies

None


Discussion:
Does this need to be configurable? Should we just set it to a much higher (but sane) value, or disable it entirely?
I suggest it to be configured so one can limit it to its own need, with the default as is (~2,5 MB).
This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. NetBox is governed by a small group of core maintainers which means not all opened issues may receive direct feedback. **Do not** attempt to circumvent this process by "bumping" the issue; doing so will result in its immediate closure and you may be barred from participating in any future discussions. Please see our [contributing guide](https://github.com/netbox-community/netbox/blob/develop/CONTRIBUTING.md).

Resolving patch:
diff --git a/netbox/netbox/settings.py b/netbox/netbox/settings.py
--- a/netbox/netbox/settings.py
+++ b/netbox/netbox/settings.py
@@ -95,6 +95,7 @@
 CSRF_COOKIE_NAME = getattr(configuration, 'CSRF_COOKIE_NAME', 'csrftoken')
 CSRF_COOKIE_SECURE = getattr(configuration, 'CSRF_COOKIE_SECURE', False)
 CSRF_TRUSTED_ORIGINS = getattr(configuration, 'CSRF_TRUSTED_ORIGINS', [])
+DATA_UPLOAD_MAX_MEMORY_SIZE = getattr(configuration, 'DATA_UPLOAD_MAX_MEMORY_SIZE', 2621440)
 DATE_FORMAT = getattr(configuration, 'DATE_FORMAT', 'N j, Y')
 DATETIME_FORMAT = getattr(configuration, 'DATETIME_FORMAT', 'N j, Y g:i a')
 DEBUG = getattr(configuration, 'DEBUG', False)


Test patch:
Repository: netbox-community/netbox

Issue:
Post to /api/ipam/prefixes/<int:pk>/available-ips/ is slow when the prefix is large
### NetBox version

v3.6.3

### Python version

3.11

### Steps to Reproduce

1. Create large prefix (e. g. 10.0.0.0/8)
2. Request an IP from the created prefix with:
 curl -v -X POST -d '{}' -H 'Content-Type: application/json' -H 'Accept: application/json' -H 'Authorization: Token REDACTED' http://localhost:8787/api/ipam/prefixes/$idOfPrefixFromStep1/available-ips/

### Expected Behavior

Get a fast response

### Observed Behavior

Response takes over 30 seconds


Discussion:

Resolving patch:
diff --git a/netbox/ipam/api/views.py b/netbox/ipam/api/views.py
--- a/netbox/ipam/api/views.py
+++ b/netbox/ipam/api/views.py
@@ -266,6 +266,7 @@ def post(self, request, pk):
 
         # Normalize request data to a list of objects
         requested_objects = request.data if isinstance(request.data, list) else [request.data]
+        limit = len(requested_objects)
 
         # Serialize and validate the request data
         serializer = self.write_serializer_class(data=requested_objects, many=True, context={
@@ -279,7 +280,7 @@ def post(self, request, pk):
             )
 
         with advisory_lock(ADVISORY_LOCK_KEYS[self.advisory_lock_key]):
-            available_objects = self.get_available_objects(parent)
+            available_objects = self.get_available_objects(parent, limit)
 
             # Determine if the requested number of objects is available
             if not self.check_sufficient_available(serializer.validated_data, available_objects):


Test patch:
Repository: netbox-community/netbox

Issue:
Add a copy-to-clipboard button to the API token creation form
### NetBox version

v3.6.3

### Feature type

New functionality

### Proposed functionality

On the API token creation form, add a button to conveniently copy the randomly-generated API token value to the system clipboard.

![API token creation form](https://github.com/netbox-community/netbox/assets/13487278/b8ffa826-c713-4f5b-8ca4-56309e68d215)


### Use case

Convenience

### Database changes

_No response_

### External dependencies

_No response_


Discussion:
Isn't that already supported by  [netbox/templates/account/token.html#L20](https://github.com/netbox-community/netbox/blob/v3.6.3/netbox/templates/account/token.html#L20) and [netbox/templates/account/token.html#L32]( https://github.com/netbox-community/netbox/blob/v3.6.3/netbox/templates/account/token.html#L32) -> [copy_content.html](https://github.com/netbox-community/netbox/blob/v3.6.3/netbox/utilities/templates/builtins/copy_content.html) in the detail view of tokens?

If I understand properly, I think the end goal is to prevent the token to be retrieved after saving in the future. In that case we can create a custom form widget with a "copy" button for the `key` field.

This can be assigned to me if I understand the end goal properly.

Resolving patch:
diff --git a/netbox/users/forms/model_forms.py b/netbox/users/forms/model_forms.py
--- a/netbox/users/forms/model_forms.py
+++ b/netbox/users/forms/model_forms.py
@@ -114,6 +114,9 @@ class UserTokenForm(BootstrapMixin, forms.ModelForm):
         help_text=_(
             'Keys must be at least 40 characters in length. <strong>Be sure to record your key</strong> prior to '
             'submitting this form, as it may no longer be accessible once the token has been created.'
+        ),
+        widget=forms.TextInput(
+            attrs={'data-clipboard': 'true'}
         )
     )
     allowed_ips = SimpleArrayField(


Test patch:
Repository: netbox-community/netbox

Issue:
Order global search results by value of matched fields
### NetBox version

v3.6.3

### Feature type

Change to existing functionality

### Proposed functionality

When returning global search results, order results of equal precedence and object type by value. This should ensure that otherwise equally-relevant results appear in a human-friendly order.

The current ordering for cached search result objects is:

```python
class CachedValue:
    class Meta:
        ordering = ('weight', 'object_type', 'object_id')
```

This FR would modify the above to:

```python
class CachedValue:
    class Meta:
        ordering = ('weight', 'object_type', 'value', 'object_id')
```

(`object_id` is retained as a tie-breaker for results having the same matched value, to ensure deterministic ordering.)

### Use case

This adjustment serves to ensure otherwise equally-relevant search results are listed in a human-friendly order. (This was first raised as a bug report under #13940.)

### Database changes

This will require a model migration to effect the new default ordering for CachedValue.

### External dependencies

None


Discussion:

Resolving patch:
diff --git a/netbox/extras/migrations/0099_cachedvalue_ordering.py b/netbox/extras/migrations/0099_cachedvalue_ordering.py
new file mode 100644
--- /dev/null
+++ b/netbox/extras/migrations/0099_cachedvalue_ordering.py
@@ -0,0 +1,17 @@
+# Generated by Django 4.2.6 on 2023-10-30 14:04
+
+from django.db import migrations
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('extras', '0098_webhook_custom_field_data_webhook_tags'),
+    ]
+
+    operations = [
+        migrations.AlterModelOptions(
+            name='cachedvalue',
+            options={'ordering': ('weight', 'object_type', 'value', 'object_id')},
+        ),
+    ]
diff --git a/netbox/extras/models/search.py b/netbox/extras/models/search.py
--- a/netbox/extras/models/search.py
+++ b/netbox/extras/models/search.py
@@ -50,7 +50,7 @@ class CachedValue(models.Model):
     )
 
     class Meta:
-        ordering = ('weight', 'object_type', 'object_id')
+        ordering = ('weight', 'object_type', 'value', 'object_id')
         verbose_name = _('cached value')
         verbose_name_plural = _('cached values')
 


Test patch:
Repository: netbox-community/netbox

Issue:
Bulk edit of Interfaces of VMs without cluster fails
### NetBox version

v3.6.5

### Python version

3.8

### Steps to Reproduce

1. Create VM and assign only a Site, not a Cluster
2. Create Interface for VM
3. Mark Interface and click on "Edit Selected"

### Expected Behavior

Edit form for selected VM Interface(s) appear

### Observed Behavior

Exception Window with the following Content:
```
<class 'AttributeError'>

'NoneType' object has no attribute 'site'

Python version: 3.8.10
NetBox version: 3.6.5
Plugins: 
  netbox_demo: 0.3.1
```

When generating the bulk edit form, the site is extracted from the cluster of the virtual machine, which fails if no cluster is assigned to the VM:
```
  File "/opt/netbox/netbox/virtualization/forms/bulk_edit.py", line 272, in __init__
     site = interface.virtual_machine.cluster.site
AttributeError: 'NoneType' object has no attribute 'site'
```


Discussion:

Resolving patch:
diff --git a/netbox/virtualization/forms/bulk_edit.py b/netbox/virtualization/forms/bulk_edit.py
--- a/netbox/virtualization/forms/bulk_edit.py
+++ b/netbox/virtualization/forms/bulk_edit.py
@@ -294,9 +294,10 @@ def __init__(self, *args, **kwargs):
                 # Check interface sites.  First interface should set site, further interfaces will either continue the
                 # loop or reset back to no site and break the loop.
                 for interface in interfaces:
+                    vm_site = interface.virtual_machine.site or interface.virtual_machine.cluster.site
                     if site is None:
-                        site = interface.virtual_machine.cluster.site
-                    elif interface.virtual_machine.cluster.site is not site:
+                        site = vm_site
+                    elif vm_site is not site:
                         site = None
                         break
 


Test patch:
Repository: netbox-community/netbox

Issue:
Custom Validation does not work for DataSource
### NetBox version

v3.6.5

### Python version

3.10

### Steps to Reproduce

1. Add this snippet to your configuration.py

```
from extras.validators import CustomValidator

class MyValidator(CustomValidator):
    def validate(self, instance):
        self.fail("This error won't appear")

CUSTOM_VALIDATORS = {"core.datasource": [MyValidator]}
```

2. Make sure that when you create Data Source from UI there is no validation error


This happens due to lack of `super().clean()` here:
https://github.com/netbox-community/netbox/blob/develop/netbox/core/models/data.py#L124

And, I suppose, it also causes other unpleasant side-effects because other NetBoxFeatureSet members `.clean()` are also not called

### Expected Behavior

Validation Error happens after creation of the new Data Source after MyValidator has been added to CUSTOM_VALIDATORS

### Observed Behavior

MyValidator is ignored, no error appeared.


Discussion:
@amyasnikov thanks for taking the time to track this down and report it!

Resolving patch:
diff --git a/netbox/core/models/data.py b/netbox/core/models/data.py
--- a/netbox/core/models/data.py
+++ b/netbox/core/models/data.py
@@ -122,6 +122,7 @@ def ready_for_sync(self):
         )
 
     def clean(self):
+        super().clean()
 
         # Ensure URL scheme matches selected type
         if self.type == DataSourceTypeChoices.LOCAL and self.url_scheme not in ('file', ''):


Test patch:
Repository: netbox-community/netbox

Issue:
Cannot load IPAM-ASNs page
### NetBox version

v3.6.5

### Python version

3.9

### Steps to Reproduce

1. Configure ASN table to include ASDOT column
2. On the left pane of homepage click 'IPAM'
3. Click 'ASNs'

### Expected Behavior

A page listing configured ASNs

### Observed Behavior

Server Error

There was a problem with your request. Please contact an administrator.

The complete exception is provided below:

<class 'django.core.exceptions.FieldError'>

Cannot resolve keyword 'asn_asdot' into field. Choices are: asn, bookmarks, comments, created, custom_field_data, description, id, journal_entries, last_updated, provider_count, providers, rir, rir_id, site_count, sites, tagged_items, tags, tenant, tenant_id

Python version: 3.9.16
NetBox version: 3.6.5
Plugins: None installed

If further assistance is required, please post to the [NetBox discussion forum](https://github.com/netbox-community/netbox/discussions) on GitHub.


Discussion:
The problem only happens when I configure ASN table to include ASDOT column.
Works fine for me on 3.6.5
There's a step missing from the reproduction instructions (thanks @abhi1693):

4. Click the "ASDOT" column header to order by that column, then reload the page.

The issue is that `asn_asdot` is actually an instance property rather than a table column, so we need to set the `order_by` accessor for the column to the raw `asn` value. This will fix the exception that occurs when attempting to sort the table by this column.

Resolving patch:
diff --git a/netbox/ipam/tables/asn.py b/netbox/ipam/tables/asn.py
--- a/netbox/ipam/tables/asn.py
+++ b/netbox/ipam/tables/asn.py
@@ -48,6 +48,7 @@ class ASNTable(TenancyColumnsMixin, NetBoxTable):
     asn_asdot = tables.Column(
         accessor=tables.A('asn_asdot'),
         linkify=True,
+        order_by=tables.A('asn'),
         verbose_name=_('ASDOT')
     )
     site_count = columns.LinkedCountColumn(


Test patch:
Repository: netbox-community/netbox

Issue:
"service" does not preserve the order of ports when editing
### NetBox version

v3.6.5

### Python version

3.8

### Steps to Reproduce

1. Create a "service", and enter the ports as "9093,9095,9998-9999"
2. View the list of services
3. Edit the service (i.e. click the pencil icon at the end of the service row)

### Expected Behavior

Either the ports to remain in the order originally entered, or to be sorted. (I note that the data type in the underlying Postgres column is `integer[]` which is an ordered list)

### Observed Behavior

When viewing the table of services (`/ipam/services/`), the ports are shown in order:

<img width="304" alt="image" src="https://github.com/netbox-community/netbox/assets/44789/632b5313-7241-45d3-8649-b16fb9c4b6f0">

It also shows the same when viewing the details of an individual service (e.g. `/ipam/services/2/`)

However, when editing the service (`/ipam/services/2/edit/`), the ports are in a randomized order:

<img width="681" alt="image" src="https://github.com/netbox-community/netbox/assets/44789/494f89cc-80b5-4b48-a27f-498992c159e3">

This matches what's in the database, which in the same randomized order:

```
netbox=# select ports from ipam_service where id=2
         ports
-----------------------
 {9999,9093,9998,9095}
(1 row)
```



Discussion:
This is due to a bug in `utilities.forms.utils.parse_numeric_range()`. We're calling `set()` on the expanded value to remove potential duplicates, but not ordering the result after casting it to a list.

Resolving patch:
diff --git a/netbox/utilities/forms/utils.py b/netbox/utilities/forms/utils.py
--- a/netbox/utilities/forms/utils.py
+++ b/netbox/utilities/forms/utils.py
@@ -40,7 +40,7 @@ def parse_numeric_range(string, base=10):
         except ValueError:
             raise forms.ValidationError(f'Range "{dash_range}" is invalid.')
         values.extend(range(begin, end))
-    return list(set(values))
+    return sorted(set(values))
 
 
 def parse_alphanumeric_range(string):


Test patch:
Repository: netbox-community/netbox

Issue:
"Tenancy > Contact Assignments" missing from Export Template "Content types" field.
### NetBox version

v3.6.5

### Python version

3.11

### Steps to Reproduce

1, Create a new Export Template
2. Try to select Tenancy > Contact Assignments in the "Content types" field.
3. It is not found.

### Expected Behavior

Expect to be able to select Tenancy > Contact Assignments in the "Content types" field.


### Observed Behavior

Unable to create an export template for the Contact Assignments as the option to select "Tenancy > Contact Assignments" is not available.
![Screenshot 2023-11-10 101859](https://github.com/netbox-community/netbox/assets/56978198/ee751792-8f38-46f4-8089-971f7ba63591)



Discussion:

Resolving patch:
diff --git a/netbox/tenancy/models/contacts.py b/netbox/tenancy/models/contacts.py
--- a/netbox/tenancy/models/contacts.py
+++ b/netbox/tenancy/models/contacts.py
@@ -5,7 +5,7 @@
 from django.utils.translation import gettext_lazy as _
 
 from netbox.models import ChangeLoggedModel, NestedGroupModel, OrganizationalModel, PrimaryModel
-from netbox.models.features import TagsMixin
+from netbox.models.features import ExportTemplatesMixin, TagsMixin
 from tenancy.choices import *
 
 __all__ = (
@@ -109,7 +109,7 @@ def get_absolute_url(self):
         return reverse('tenancy:contact', args=[self.pk])
 
 
-class ContactAssignment(ChangeLoggedModel, TagsMixin):
+class ContactAssignment(ChangeLoggedModel, ExportTemplatesMixin, TagsMixin):
     content_type = models.ForeignKey(
         to=ContentType,
         on_delete=models.CASCADE


Test patch:
Repository: netbox-community/netbox

Issue:
Jobs table is empty on Reports
### NetBox version

v3.6.4

### Python version

3.8

### Steps to Reproduce

1. Navigate to `/extras/reports/`
2. Click on the name of a report
3. Click on the "Jobs" tab

### Expected Behavior

The number of rows in the table should match the number in the badge.

### Observed Behavior

The table shows no rows, despite there being a number in the badge.

It looks like `ReportJobsView` has this line:
https://github.com/netbox-community/netbox/blob/22e474ff96ce9b8659455ad48ee96e766bbf7025/netbox/extras/views.py#L1076

While `ScriptJobsView` has this line:
https://github.com/netbox-community/netbox/blob/22e474ff96ce9b8659455ad48ee96e766bbf7025/netbox/extras/views.py#L1252

Changing `ReportJobsView` to have `report.class_name` instead of `report.name` seems to resolve this issue. Therefore, I suspect this might only be present on reports with a custom name set, but I am unable to test this at this time.


Discussion:
I also noticed that the badge count is wrong and only takes into account the Object and not the Name, so all the reports within the same module show the same badge count on the Jobs tab. I believe that's an issue with the way that the `JobsMixin` class is implemented and how the `jobs` attribute is being used, so you get back a list of all the jobs for that module, but it is never filtered by name. There also seem to be a number of places in both the report and script code that the `name` and `class_name` attributes are used inconsistently.
> Changing `ReportJobsView` to have `report.class_name` instead of `report.name` seems to resolve this issue. Therefore, I suspect this might only be present on reports with a custom name set, but I am unable to test this at this time.

I've confirmed that this happens only for reports which have a custom named defined.

Resolving patch:
diff --git a/netbox/extras/views.py b/netbox/extras/views.py
--- a/netbox/extras/views.py
+++ b/netbox/extras/views.py
@@ -1073,7 +1073,7 @@ def get(self, request, module, name):
         jobs = Job.objects.filter(
             object_type=object_type,
             object_id=module.pk,
-            name=report.name
+            name=report.class_name
         )
 
         jobs_table = JobTable(


Test patch:
Repository: netbox-community/netbox

Issue:
No 'Pre-Change Data' when updating interface via CSV import
### NetBox version

v3.6.3

### Python version

3.8

### Steps to Reproduce

1. Accidentally change names on a dozen of interfaces using a CSV import
2. Check the changelog
3. See **None** as **Pre-Change Data**

### Expected Behavior

**Pre-Change Data** should list the fields before the change.
**Difference** should show the difference

### Observed Behavior

![image](https://github.com/netbox-community/netbox/assets/8932945/ca16c839-c1f9-4424-89bd-7822266d4dd8)


Discussion:
I believe this would be resolved by FR #14059.

Resolving patch:
diff --git a/netbox/netbox/views/generic/bulk_views.py b/netbox/netbox/views/generic/bulk_views.py
--- a/netbox/netbox/views/generic/bulk_views.py
+++ b/netbox/netbox/views/generic/bulk_views.py
@@ -394,6 +394,10 @@ def create_and_update_objects(self, form, request):
                     form.add_error('data', f"Row {i}: Object with ID {object_id} does not exist")
                     raise ValidationError('')
 
+                # Take a snapshot for change logging
+                if instance.pk and hasattr(instance, 'snapshot'):
+                    instance.snapshot()
+
             # Instantiate the model form for the object
             model_form_kwargs = {
                 'data': record,


Test patch: