BugFix and docs for InvenTreeTree

This commit is contained in:
Oliver Walters 2017-03-27 22:55:21 +11:00
parent f17e9de37b
commit 8229f02db6
4 changed files with 64 additions and 32 deletions

View File

@ -5,6 +5,11 @@ from django.core.exceptions import ObjectDoesNotExist
from django.contrib.contenttypes.models import ContentType
class InvenTreeTree(models.Model):
""" Provides an abstracted self-referencing tree model for data categories.
- Each Category has one parent Category, which can be blank (for a top-level Category).
- Each Category can have zero-or-more child Categor(y/ies)
"""
name = models.CharField(max_length=100)
description = models.CharField(max_length=250)
parent = models.ForeignKey('self',
@ -13,8 +18,10 @@ class InvenTreeTree(models.Model):
null=True)
#limit_choices_to={id: getAcceptableParents})
# Return a flat set of all child items under this node
def getUniqueChildren(self, unique=None):
""" Return a flat set of all child items that exist under this node.
If any child items are repeated, the repetitions are omitted.
"""
if unique is None:
unique = set()
@ -33,8 +40,11 @@ class InvenTreeTree(models.Model):
return unique
# Return a list of acceptable other parents
def getAcceptableParents(self):
""" Returns a list of acceptable parent items within this model
Acceptable parents are ones which are not underneath this item.
Setting the parent of an item to its own child results in recursion.
"""
contents = ContentType.objects.get_for_model(type(self))
available = contents.get_all_objects_for_this_type()
@ -50,9 +60,15 @@ class InvenTreeTree(models.Model):
return acceptable
# Return the parent path of this category
@property
def path(self):
""" Return the parent path of this category
Todo:
This function is recursive and expensive.
It should be reworked such that only a single db call is required
"""
if self.parent:
return self.parent.path + [self.parent]
else:
@ -60,12 +76,25 @@ class InvenTreeTree(models.Model):
return parent_path
# Custom SetAttribute function to prevent parent recursion
def __setattr__(self, attrname, val):
# Prevent parent from being set such that it would cause a recursion loop
""" Custom Attribute Setting function
Parent:
Setting the parent of an item to its own child results in an infinite loop.
The parent of an item cannot be set to:
a) Its own ID
b) The ID of any child items that exist underneath it
Name:
Tree node names are limited to a reduced character set
"""
if attrname == 'parent_id':
# If current ID is None, continue (as this object is just being created)
if self.id is None:
pass
# Parent cannot be set to same ID (this would cause looping)
if val == self.id:
elif val == self.id:
return
# Null parent is OK
elif val is None:
@ -76,7 +105,24 @@ class InvenTreeTree(models.Model):
if val in kids:
return
# Prohibit certain characters from tree node names
elif attrname == 'name':
val = val.translate({ord(c): None for c in "!@#$%^&*'\"\\/[]{}<>,|+=~`"})
super(InvenTreeTree, self).__setattr__(attrname, val)
def __str__(self):
""" String representation of a category is the full path to that category
Todo:
This is recursive - Make it not so.
"""
if self.parent:
return "/".join([p.name for p in self.path]) + "/" + self.name
else:
return self.name
class Meta:
abstract = True

View File

@ -6,17 +6,16 @@ from django.core.exceptions import ObjectDoesNotExist
from InvenTree.models import InvenTreeTree
class PartCategory(InvenTreeTree):
def __str__(self):
if self.parent:
return "/".join([p.name for p in self.path]) + "/" + self.name
else:
return self.name
""" PartCategory provides hierarchical organization of Part objects.
"""
class Meta:
verbose_name = "Part Category"
verbose_name_plural = "Part Categories"
class Part(models.Model):
""" Represents a """
name = models.CharField(max_length=100)
description = models.CharField(max_length=250, blank=True)
IPN = models.CharField(max_length=100, blank=True)

View File

@ -3,25 +3,10 @@ from __future__ import unicode_literals
from django.db import models
from part.models import Part
from InvenTree.models import InvenTreeTree
class Warehouse(models.Model):
name = models.CharField(max_length=100)
description = models.CharField(max_length=250, blank=True)
parent = models.ForeignKey('self', on_delete=models.CASCADE, blank=True, null=True)
def __str__(self):
if self.parent:
return "/".join([p.name for p in self.path]) + "/" + self.name
else:
return self.name
# Return path of this category
@property
def path(self):
if self.parent:
return self.parent.path + [self.parent]
else:
return []
class Warehouse(InvenTreeTree):
pass
class StockItem(models.Model):
part = models.ForeignKey(Part, on_delete=models.CASCADE)

View File

@ -1,3 +1,5 @@
from django.shortcuts import render
from django.shortcuts import render, get_object_or_404
from django.http import HttpResponse
# Create your views here.
def index(request):
return HttpResponse("This is the Tracking page")