Fixed up some stupid recursion on the Tree model template

This commit is contained in:
Oliver Walters 2019-06-18 00:59:54 +10:00
parent 642660d76e
commit 16b6ae8d61
8 changed files with 73 additions and 39 deletions

View File

@ -11,6 +11,8 @@ from rest_framework.exceptions import ValidationError
from django.db.models.signals import pre_delete from django.db.models.signals import pre_delete
from django.dispatch import receiver from django.dispatch import receiver
from .validators import validate_tree_name
class InvenTreeTree(models.Model): class InvenTreeTree(models.Model):
""" Provides an abstracted self-referencing tree model for data categories. """ Provides an abstracted self-referencing tree model for data categories.
@ -31,7 +33,8 @@ class InvenTreeTree(models.Model):
name = models.CharField( name = models.CharField(
blank=False, blank=False,
max_length=100, max_length=100,
unique=True unique=True,
validators=[validate_tree_name]
) )
description = models.CharField( description = models.CharField(
@ -104,14 +107,6 @@ class InvenTreeTree(models.Model):
""" True if there are any children under this item """ """ True if there are any children under this item """
return self.children.count() > 0 return self.children.count() > 0
@property
def children(self):
""" Return the children of this item """
contents = ContentType.objects.get_for_model(type(self))
childs = contents.get_all_objects_for_this_type(parent=self.id)
return childs
def getAcceptableParents(self): def getAcceptableParents(self):
""" Returns a list of acceptable parent items within this model """ Returns a list of acceptable parent items within this model
Acceptable parents are ones which are not underneath this item. Acceptable parents are ones which are not underneath this item.
@ -164,8 +159,8 @@ class InvenTreeTree(models.Model):
""" """
return '/'.join([item.name for item in self.path]) return '/'.join([item.name for item in self.path])
def __setattr__(self, attrname, val): def clean(self):
""" Custom Attribute Setting function """ Custom cleaning
Parent: Parent:
Setting the parent of an item to its own child results in an infinite loop. Setting the parent of an item to its own child results in an infinite loop.
@ -177,28 +172,18 @@ class InvenTreeTree(models.Model):
Tree node names are limited to a reduced character set Tree node names are limited to a reduced character set
""" """
if attrname == 'parent_id': super().clean()
# If current ID is None, continue
# - This object is just being created
if self.id is None:
pass
# Parent cannot be set to same ID (this would cause looping)
elif val == self.id:
raise ValidationError("Category cannot set itself as parent")
# Null parent is OK
elif val is None:
pass
# Ensure that the new parent is not already a child
else:
kids = self.getUniqueChildren()
if val in kids:
raise ValidationError("Category cannot set a child as parent")
# Prohibit certain characters from tree node names # Parent cannot be set to same ID (this would cause looping)
elif attrname == 'name': try:
val = val.translate({ord(c): None for c in "!@#$%^&*'\"\\/[]{}<>,|+=~`"}) if self.parent.id == self.id:
raise ValidationError("Category cannot set itself as parent")
except:
pass
super(InvenTreeTree, self).__setattr__(attrname, val) # Ensure that the new parent is not already a child
if self.id in self.getUniqueChildren():
raise ValidationError("Category cannot set a child as parent")
def __str__(self): def __str__(self):
""" String representation of a category is the full path to that category """ """ String representation of a category is the full path to that category """

View File

@ -17,6 +17,14 @@ def validate_part_name(value):
) )
def validate_tree_name(value):
""" Prevent illegal characters in tree item names """
for c in "!@#$%^&*'\"\\/[]{}<>,|+=~`\"":
if c in str(value):
raise ValidationError({'name': _('Illegal character in name')})
def validate_overage(value): def validate_overage(value):
""" Validate that a BOM overage string is properly formatted. """ Validate that a BOM overage string is properly formatted.

View File

@ -52,10 +52,8 @@ class TreeSerializer(views.APIView):
if item.has_children: if item.has_children:
nodes = [] nodes = []
"""
for child in item.children.all().order_by('name'): for child in item.children.all().order_by('name'):
nodes.append(self.itemToJson(child)) nodes.append(self.itemToJson(child))
"""
data['nodes'] = nodes data['nodes'] = nodes

View File

@ -35,8 +35,6 @@ class PartCategoryTree(TreeSerializer):
return reverse('part-index') return reverse('part-index')
def get_items(self): def get_items(self):
print("hello world")
return PartCategory.objects.all().prefetch_related('parts', 'children') return PartCategory.objects.all().prefetch_related('parts', 'children')
@ -112,7 +110,9 @@ class PartList(generics.ListCreateAPIView):
if cat_id: if cat_id:
try: try:
category = PartCategory.objects.get(pk=cat_id) category = PartCategory.objects.get(pk=cat_id)
parts_list = parts_list.filter(category__in=category.getUniqueChildren()) cats = [category.id]
cats += [cat for cat in category.getUniqueChildren()]
parts_list = parts_list.filter(category__in=cats)
except PartCategory.DoesNotExist: except PartCategory.DoesNotExist:
pass pass

View File

@ -0,0 +1,19 @@
# Generated by Django 2.2.2 on 2019-06-17 14:42
import InvenTree.validators
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('part', '0007_auto_20190602_1944'),
]
operations = [
migrations.AlterField(
model_name='partcategory',
name='name',
field=models.CharField(max_length=100, unique=True, validators=[InvenTree.validators.validate_tree_name]),
),
]

View File

@ -73,10 +73,12 @@ class PartCategory(InvenTreeTree):
(including children of child categories) (including children of child categories)
""" """
cats = [self.id]
if cascade: if cascade:
query = Part.objects.filter(category__in=self.getUniqueChildren()) cats += [cat for cat in self.getUniqueChildren()]
else:
query = Part.objects.filter(category=self) query = Part.objects.filter(category__in=cats)
if active: if active:
query = query.filter(active=True) query = query.filter(active=True)

View File

@ -38,6 +38,9 @@ class StockCategoryTree(TreeSerializer):
def root_url(self): def root_url(self):
return reverse('stock-index') return reverse('stock-index')
def get_items(self):
return StockLocation.objects.all().prefetch_related('stock_items', 'children')
class StockDetail(generics.RetrieveUpdateDestroyAPIView): class StockDetail(generics.RetrieveUpdateDestroyAPIView):
""" API detail endpoint for Stock object """ API detail endpoint for Stock object

View File

@ -0,0 +1,19 @@
# Generated by Django 2.2.2 on 2019-06-17 14:42
import InvenTree.validators
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('stock', '0006_stockitem_purchase_order'),
]
operations = [
migrations.AlterField(
model_name='stocklocation',
name='name',
field=models.CharField(max_length=100, unique=True, validators=[InvenTree.validators.validate_tree_name]),
),
]