mirror of
https://github.com/netbox-community/netbox.git
synced 2025-07-22 20:12:00 -06:00
Fixes #8201: Custom integer fields should allow negative integers as minimum/maximum values
This commit is contained in:
parent
7b0dff88ae
commit
05d4176d34
@ -13,6 +13,7 @@
|
||||
* [#8187](https://github.com/netbox-community/netbox/issues/8187) - Fix rendering of tags column in object tables
|
||||
* [#8191](https://github.com/netbox-community/netbox/issues/8191) - Fix return URL when adding IP addresses to VM interfaces
|
||||
* [#8196](https://github.com/netbox-community/netbox/issues/8196) - Fix IndexError exception when viewing large IPv6 prefixes in UI
|
||||
* [#8201](https://github.com/netbox-community/netbox/issues/8201) - Custom integer fields should allow negative integers as minimum/maximum values
|
||||
|
||||
---
|
||||
|
||||
|
21
netbox/extras/migrations/0067_customfield_min_max_values.py
Normal file
21
netbox/extras/migrations/0067_customfield_min_max_values.py
Normal file
@ -0,0 +1,21 @@
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('extras', '0066_customfield_name_validation'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='customfield',
|
||||
name='validation_maximum',
|
||||
field=models.IntegerField(blank=True, null=True),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='customfield',
|
||||
name='validation_minimum',
|
||||
field=models.IntegerField(blank=True, null=True),
|
||||
),
|
||||
]
|
@ -96,13 +96,13 @@ class CustomField(ChangeLoggedModel):
|
||||
default=100,
|
||||
help_text='Fields with higher weights appear lower in a form.'
|
||||
)
|
||||
validation_minimum = models.PositiveIntegerField(
|
||||
validation_minimum = models.IntegerField(
|
||||
blank=True,
|
||||
null=True,
|
||||
verbose_name='Minimum value',
|
||||
help_text='Minimum allowed value (for numeric fields)'
|
||||
)
|
||||
validation_maximum = models.PositiveIntegerField(
|
||||
validation_maximum = models.IntegerField(
|
||||
blank=True,
|
||||
null=True,
|
||||
verbose_name='Maximum value',
|
||||
|
@ -25,49 +25,68 @@ class CustomFieldTest(TestCase):
|
||||
def test_simple_fields(self):
|
||||
DATA = (
|
||||
{
|
||||
'field_type': CustomFieldTypeChoices.TYPE_TEXT,
|
||||
'field_value': 'Foobar!',
|
||||
'empty_value': '',
|
||||
'field': {
|
||||
'type': CustomFieldTypeChoices.TYPE_TEXT,
|
||||
},
|
||||
'value': 'Foobar!',
|
||||
},
|
||||
{
|
||||
'field_type': CustomFieldTypeChoices.TYPE_LONGTEXT,
|
||||
'field_value': 'Text with **Markdown**',
|
||||
'empty_value': '',
|
||||
'field': {
|
||||
'type': CustomFieldTypeChoices.TYPE_LONGTEXT,
|
||||
},
|
||||
'value': 'Text with **Markdown**',
|
||||
},
|
||||
{
|
||||
'field_type': CustomFieldTypeChoices.TYPE_INTEGER,
|
||||
'field_value': 0,
|
||||
'empty_value': None,
|
||||
'field': {
|
||||
'type': CustomFieldTypeChoices.TYPE_INTEGER,
|
||||
},
|
||||
'value': 0,
|
||||
},
|
||||
{
|
||||
'field_type': CustomFieldTypeChoices.TYPE_INTEGER,
|
||||
'field_value': 42,
|
||||
'empty_value': None,
|
||||
'field': {
|
||||
'type': CustomFieldTypeChoices.TYPE_INTEGER,
|
||||
'validation_minimum': 1,
|
||||
'validation_maximum': 100,
|
||||
},
|
||||
'value': 42,
|
||||
},
|
||||
{
|
||||
'field_type': CustomFieldTypeChoices.TYPE_BOOLEAN,
|
||||
'field_value': True,
|
||||
'empty_value': None,
|
||||
'field': {
|
||||
'type': CustomFieldTypeChoices.TYPE_INTEGER,
|
||||
'validation_minimum': -100,
|
||||
'validation_maximum': -1,
|
||||
},
|
||||
'value': -42,
|
||||
},
|
||||
{
|
||||
'field_type': CustomFieldTypeChoices.TYPE_BOOLEAN,
|
||||
'field_value': False,
|
||||
'empty_value': None,
|
||||
'field': {
|
||||
'type': CustomFieldTypeChoices.TYPE_BOOLEAN,
|
||||
},
|
||||
'value': True,
|
||||
},
|
||||
{
|
||||
'field_type': CustomFieldTypeChoices.TYPE_DATE,
|
||||
'field_value': '2016-06-23',
|
||||
'empty_value': None,
|
||||
'field': {
|
||||
'type': CustomFieldTypeChoices.TYPE_BOOLEAN,
|
||||
},
|
||||
'value': False,
|
||||
},
|
||||
{
|
||||
'field_type': CustomFieldTypeChoices.TYPE_URL,
|
||||
'field_value': 'http://example.com/',
|
||||
'empty_value': '',
|
||||
'field': {
|
||||
'type': CustomFieldTypeChoices.TYPE_DATE,
|
||||
},
|
||||
'value': '2016-06-23',
|
||||
},
|
||||
{
|
||||
'field_type': CustomFieldTypeChoices.TYPE_JSON,
|
||||
'field_value': '{"foo": 1, "bar": 2}',
|
||||
'empty_value': 'null',
|
||||
'field': {
|
||||
'type': CustomFieldTypeChoices.TYPE_URL,
|
||||
},
|
||||
'value': 'http://example.com/',
|
||||
},
|
||||
{
|
||||
'field': {
|
||||
'type': CustomFieldTypeChoices.TYPE_JSON,
|
||||
},
|
||||
'value': '{"foo": 1, "bar": 2}',
|
||||
},
|
||||
)
|
||||
|
||||
@ -76,7 +95,7 @@ class CustomFieldTest(TestCase):
|
||||
for data in DATA:
|
||||
|
||||
# Create a custom field
|
||||
cf = CustomField(type=data['field_type'], name='my_field', required=False)
|
||||
cf = CustomField(name='my_field', required=False, **data['field'])
|
||||
cf.save()
|
||||
cf.content_types.set([obj_type])
|
||||
|
||||
@ -85,12 +104,12 @@ class CustomFieldTest(TestCase):
|
||||
self.assertIsNone(site.custom_field_data[cf.name])
|
||||
|
||||
# Assign a value to the first Site
|
||||
site.custom_field_data[cf.name] = data['field_value']
|
||||
site.custom_field_data[cf.name] = data['value']
|
||||
site.save()
|
||||
|
||||
# Retrieve the stored value
|
||||
site.refresh_from_db()
|
||||
self.assertEqual(site.custom_field_data[cf.name], data['field_value'])
|
||||
self.assertEqual(site.custom_field_data[cf.name], data['value'])
|
||||
|
||||
# Delete the stored value
|
||||
site.custom_field_data.pop(cf.name)
|
||||
|
Loading…
Reference in New Issue
Block a user