mirror of
https://github.com/inventree/InvenTree
synced 2024-08-30 18:33:04 +00:00
Fixed up some stupid recursion on the Tree model template
This commit is contained in:
parent
642660d76e
commit
16b6ae8d61
@ -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 """
|
||||||
|
@ -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.
|
||||||
|
|
||||||
|
@ -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
|
||||||
|
|
||||||
|
@ -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
|
||||||
|
|
||||||
|
19
InvenTree/part/migrations/0008_auto_20190618_0042.py
Normal file
19
InvenTree/part/migrations/0008_auto_20190618_0042.py
Normal 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]),
|
||||||
|
),
|
||||||
|
]
|
@ -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)
|
||||||
|
@ -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
|
||||||
|
19
InvenTree/stock/migrations/0007_auto_20190618_0042.py
Normal file
19
InvenTree/stock/migrations/0007_auto_20190618_0042.py
Normal 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]),
|
||||||
|
),
|
||||||
|
]
|
Loading…
Reference in New Issue
Block a user