mirror of
https://github.com/inventree/InvenTree
synced 2024-08-30 18:33:04 +00:00
Url field fix (#3488)
* Updates for automated metadata extraction * Update link field for StockItem model - Increase max_length to 200 characters - Custom migration - Updates for InvenTreeUrlField model * Adding unit tests * Bug fix for metadata.py
This commit is contained in:
parent
83b471b4f7
commit
63d221854b
@ -6,7 +6,6 @@ from decimal import Decimal
|
||||
from django import forms
|
||||
from django.core import validators
|
||||
from django.db import models as models
|
||||
from django.forms.fields import URLField as FormURLField
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
from djmoney.forms.fields import MoneyField
|
||||
@ -23,26 +22,28 @@ class InvenTreeRestURLField(RestURLField):
|
||||
"""Custom field for DRF with custom scheme vaildators."""
|
||||
def __init__(self, **kwargs):
|
||||
"""Update schemes."""
|
||||
|
||||
# Enforce 'max length' parameter in form validation
|
||||
if 'max_length' not in kwargs:
|
||||
kwargs['max_length'] = 200
|
||||
|
||||
super().__init__(**kwargs)
|
||||
self.validators[-1].schemes = allowable_url_schemes()
|
||||
|
||||
|
||||
class InvenTreeURLFormField(FormURLField):
|
||||
"""Custom URL form field with custom scheme validators."""
|
||||
|
||||
default_validators = [validators.URLValidator(schemes=allowable_url_schemes())]
|
||||
|
||||
|
||||
class InvenTreeURLField(models.URLField):
|
||||
"""Custom URL field which has custom scheme validators."""
|
||||
|
||||
validators = [validators.URLValidator(schemes=allowable_url_schemes())]
|
||||
default_validators = [validators.URLValidator(schemes=allowable_url_schemes())]
|
||||
|
||||
def formfield(self, **kwargs):
|
||||
"""Return a Field instance for this field."""
|
||||
return super().formfield(**{
|
||||
'form_class': InvenTreeURLFormField
|
||||
})
|
||||
def __init__(self, **kwargs):
|
||||
"""Initialization method for InvenTreeURLField"""
|
||||
|
||||
# Max length for InvenTreeURLField defaults to 200
|
||||
if 'max_length' not in kwargs:
|
||||
kwargs['max_length'] = 200
|
||||
|
||||
super().__init__(**kwargs)
|
||||
|
||||
|
||||
def money_kwargs():
|
||||
|
@ -116,6 +116,12 @@ class InvenTreeMetadata(SimpleMetadata):
|
||||
|
||||
model_class = None
|
||||
|
||||
# Attributes to copy extra attributes from the model to the field (if they don't exist)
|
||||
extra_attributes = [
|
||||
'help_text',
|
||||
'max_length',
|
||||
]
|
||||
|
||||
try:
|
||||
model_class = serializer.Meta.model
|
||||
|
||||
@ -148,10 +154,7 @@ class InvenTreeMetadata(SimpleMetadata):
|
||||
elif name in model_default_values:
|
||||
serializer_info[name]['default'] = model_default_values[name]
|
||||
|
||||
# Attributes to copy from the model to the field (if they don't exist)
|
||||
attributes = ['help_text']
|
||||
|
||||
for attr in attributes:
|
||||
for attr in extra_attributes:
|
||||
if attr not in serializer_info[name]:
|
||||
|
||||
if hasattr(field, attr):
|
||||
@ -172,8 +175,9 @@ class InvenTreeMetadata(SimpleMetadata):
|
||||
# This is used to automatically filter AJAX requests
|
||||
serializer_info[name]['filters'] = relation.model_field.get_limit_choices_to()
|
||||
|
||||
if 'help_text' not in serializer_info[name] and hasattr(relation.model_field, 'help_text'):
|
||||
serializer_info[name]['help_text'] = relation.model_field.help_text
|
||||
for attr in extra_attributes:
|
||||
if attr not in serializer_info[name] and hasattr(relation.model_field, attr):
|
||||
serializer_info[name][attr] = getattr(relation.model_field, attr)
|
||||
|
||||
if name in model_default_values:
|
||||
serializer_info[name]['default'] = model_default_values[name]
|
||||
|
19
InvenTree/stock/migrations/0082_alter_stockitem_link.py
Normal file
19
InvenTree/stock/migrations/0082_alter_stockitem_link.py
Normal file
@ -0,0 +1,19 @@
|
||||
# Generated by Django 3.2.15 on 2022-08-07 02:38
|
||||
|
||||
import InvenTree.fields
|
||||
from django.db import migrations
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('stock', '0081_auto_20220801_0044'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='stockitem',
|
||||
name='link',
|
||||
field=InvenTree.fields.InvenTreeURLField(blank=True, help_text='Link to external URL', max_length=200, verbose_name='External Link'),
|
||||
),
|
||||
]
|
@ -647,7 +647,7 @@ class StockItem(MetadataMixin, MPTTModel):
|
||||
|
||||
link = InvenTreeURLField(
|
||||
verbose_name=_('External Link'),
|
||||
max_length=125, blank=True,
|
||||
blank=True, max_length=200,
|
||||
help_text=_("Link to external URL")
|
||||
)
|
||||
|
||||
|
@ -44,6 +44,45 @@ class StockTest(InvenTreeTestCase):
|
||||
Part.objects.rebuild()
|
||||
StockItem.objects.rebuild()
|
||||
|
||||
def test_link(self):
|
||||
"""Test the link URL field validation"""
|
||||
|
||||
item = StockItem.objects.get(pk=1)
|
||||
|
||||
# Check that invalid URLs fail
|
||||
for bad_url in [
|
||||
'test.com',
|
||||
'httpx://abc.xyz',
|
||||
'https:google.com',
|
||||
]:
|
||||
with self.assertRaises(ValidationError):
|
||||
item.link = bad_url
|
||||
item.save()
|
||||
item.full_clean()
|
||||
|
||||
# Check that valid URLs pass
|
||||
for good_url in [
|
||||
'https://test.com',
|
||||
'https://digikey.com/datasheets?file=1010101010101.bin',
|
||||
'ftp://download.com:8080/file.aspx',
|
||||
]:
|
||||
item.link = good_url
|
||||
item.save()
|
||||
item.full_clean()
|
||||
|
||||
# A long URL should fail
|
||||
long_url = 'https://website.co.uk?query=' + 'a' * 173
|
||||
|
||||
with self.assertRaises(ValidationError):
|
||||
item.link = long_url
|
||||
item.full_clean()
|
||||
|
||||
# Shorten by a single character, will pass
|
||||
long_url = long_url[:-1]
|
||||
|
||||
item.link = long_url
|
||||
item.save()
|
||||
|
||||
def test_expiry(self):
|
||||
"""Test expiry date functionality for StockItem model."""
|
||||
today = datetime.datetime.now().date()
|
||||
|
Loading…
Reference in New Issue
Block a user