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:
Oliver 2022-08-07 22:46:33 +10:00 committed by GitHub
parent 83b471b4f7
commit 63d221854b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 83 additions and 20 deletions

View File

@ -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():

View File

@ -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]

View 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'),
),
]

View File

@ -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")
)

View File

@ -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()