Merge branch 'develop' into keyword_todo
This commit is contained in:
@ -47,6 +47,66 @@ class TreeManager(MP_NodeManager):
|
||||
return self.model.add_root(**kwargs), True
|
||||
|
||||
|
||||
class TreeModel(MP_Node):
|
||||
_full_name_separator = ' > '
|
||||
|
||||
def __str__(self):
|
||||
if self.icon:
|
||||
return f"{self.icon} {self.name}"
|
||||
else:
|
||||
return f"{self.name}"
|
||||
|
||||
@property
|
||||
def parent(self):
|
||||
parent = self.get_parent()
|
||||
if parent:
|
||||
return self.get_parent().id
|
||||
return None
|
||||
|
||||
@property
|
||||
def full_name(self):
|
||||
"""
|
||||
Returns a string representation of a tree node and it's ancestors,
|
||||
e.g. 'Cuisine > Asian > Chinese > Catonese'.
|
||||
"""
|
||||
names = [node.name for node in self.get_ancestors_and_self()]
|
||||
return self._full_name_separator.join(names)
|
||||
|
||||
def get_ancestors_and_self(self):
|
||||
"""
|
||||
Gets ancestors and includes itself. Use treebeard's get_ancestors
|
||||
if you don't want to include the node itself. It's a separate
|
||||
function as it's commonly used in templates.
|
||||
"""
|
||||
if self.is_root():
|
||||
return [self]
|
||||
return list(self.get_ancestors()) + [self]
|
||||
|
||||
def get_descendants_and_self(self):
|
||||
"""
|
||||
Gets descendants and includes itself. Use treebeard's get_descendants
|
||||
if you don't want to include the node itself. It's a separate
|
||||
function as it's commonly used in templates.
|
||||
"""
|
||||
return self.get_tree(self)
|
||||
|
||||
def has_children(self):
|
||||
return self.get_num_children() > 0
|
||||
|
||||
def get_num_children(self):
|
||||
return self.get_children().count()
|
||||
|
||||
# use self.objects.get_or_create() instead
|
||||
@classmethod
|
||||
def add_root(self, **kwargs):
|
||||
with scopes_disabled():
|
||||
return super().add_root(**kwargs)
|
||||
|
||||
class Meta:
|
||||
abstract = True
|
||||
|
||||
|
||||
|
||||
class PermissionModelMixin:
|
||||
@staticmethod
|
||||
def get_space_key():
|
||||
@ -275,7 +335,7 @@ class SyncLog(models.Model, PermissionModelMixin):
|
||||
return f"{self.created_at}:{self.sync} - {self.status}"
|
||||
|
||||
|
||||
class Keyword(ExportModelOperationsMixin('keyword'), MP_Node, PermissionModelMixin):
|
||||
class Keyword(ExportModelOperationsMixin('keyword'), TreeModel, PermissionModelMixin):
|
||||
# TODO add find and fix problem functions
|
||||
node_order_by = ['name']
|
||||
name = models.CharField(max_length=64)
|
||||
@ -287,60 +347,6 @@ class Keyword(ExportModelOperationsMixin('keyword'), MP_Node, PermissionModelMix
|
||||
space = models.ForeignKey(Space, on_delete=models.CASCADE)
|
||||
objects = ScopedManager(space='space', _manager_class=TreeManager)
|
||||
|
||||
_full_name_separator = ' > '
|
||||
|
||||
def __str__(self):
|
||||
if self.icon:
|
||||
return f"{self.icon} {self.name}"
|
||||
else:
|
||||
return f"{self.name}"
|
||||
|
||||
@property
|
||||
def parent(self):
|
||||
parent = self.get_parent()
|
||||
if parent:
|
||||
return self.get_parent().id
|
||||
return None
|
||||
|
||||
@property
|
||||
def full_name(self):
|
||||
"""
|
||||
Returns a string representation of the keyword and it's ancestors,
|
||||
e.g. 'Cuisine > Asian > Chinese > Catonese'.
|
||||
"""
|
||||
names = [keyword.name for keyword in self.get_ancestors_and_self()]
|
||||
return self._full_name_separator.join(names)
|
||||
|
||||
def get_ancestors_and_self(self):
|
||||
"""
|
||||
Gets ancestors and includes itself. Use treebeard's get_ancestors
|
||||
if you don't want to include the keyword itself. It's a separate
|
||||
function as it's commonly used in templates.
|
||||
"""
|
||||
if self.is_root():
|
||||
return [self]
|
||||
return list(self.get_ancestors()) + [self]
|
||||
|
||||
def get_descendants_and_self(self):
|
||||
"""
|
||||
Gets descendants and includes itself. Use treebeard's get_descendants
|
||||
if you don't want to include the keyword itself. It's a separate
|
||||
function as it's commonly used in templates.
|
||||
"""
|
||||
return self.get_tree(self)
|
||||
|
||||
def has_children(self):
|
||||
return self.get_num_children() > 0
|
||||
|
||||
def get_num_children(self):
|
||||
return self.get_children().count()
|
||||
|
||||
# use self.objects.get_or_create() instead
|
||||
@classmethod
|
||||
def add_root(self, **kwargs):
|
||||
with scopes_disabled():
|
||||
return super().add_root(**kwargs)
|
||||
|
||||
class Meta:
|
||||
constraints = [
|
||||
models.UniqueConstraint(fields=['space', 'name'], name='kw_unique_name_per_space')
|
||||
@ -364,7 +370,9 @@ class Unit(ExportModelOperationsMixin('unit'), models.Model, PermissionModelMixi
|
||||
]
|
||||
|
||||
|
||||
class Food(ExportModelOperationsMixin('food'), models.Model, PermissionModelMixin):
|
||||
class Food(ExportModelOperationsMixin('food'), TreeModel, PermissionModelMixin):
|
||||
# TODO add find and fix problem functions
|
||||
node_order_by = ['name']
|
||||
name = models.CharField(max_length=128, validators=[MinLengthValidator(1)])
|
||||
recipe = models.ForeignKey('Recipe', null=True, blank=True, on_delete=models.SET_NULL)
|
||||
supermarket_category = models.ForeignKey(SupermarketCategory, null=True, blank=True, on_delete=models.SET_NULL)
|
||||
@ -372,7 +380,7 @@ class Food(ExportModelOperationsMixin('food'), models.Model, PermissionModelMixi
|
||||
description = models.TextField(default='', blank=True)
|
||||
|
||||
space = models.ForeignKey(Space, on_delete=models.CASCADE)
|
||||
objects = ScopedManager(space='space')
|
||||
objects = ScopedManager(space='space', _manager_class=TreeManager)
|
||||
|
||||
def __str__(self):
|
||||
return self.name
|
||||
@ -742,7 +750,7 @@ class CookLog(ExportModelOperationsMixin('cook_log'), models.Model, PermissionMo
|
||||
return self.recipe.name
|
||||
|
||||
class Meta():
|
||||
indexes = (Index(fields=['id', 'recipe', '-created_at', 'rating']),)
|
||||
indexes = (Index(fields=['id', 'recipe', '-created_at', 'rating', 'created_by']),)
|
||||
|
||||
|
||||
class ViewLog(ExportModelOperationsMixin('view_log'), models.Model, PermissionModelMixin):
|
||||
@ -757,7 +765,7 @@ class ViewLog(ExportModelOperationsMixin('view_log'), models.Model, PermissionMo
|
||||
return self.recipe.name
|
||||
|
||||
class Meta():
|
||||
indexes = (Index(fields=['recipe', '-created_at']),)
|
||||
indexes = (Index(fields=['recipe', '-created_at', 'created_by']),)
|
||||
|
||||
|
||||
class ImportLog(models.Model, PermissionModelMixin):
|
||||
|
Reference in New Issue
Block a user