commit
ecd300d2db
@ -93,17 +93,6 @@ class KeywordAdmin(TreeAdmin):
|
|||||||
form = movenodeform_factory(Keyword)
|
form = movenodeform_factory(Keyword)
|
||||||
ordering = ('space', 'path',)
|
ordering = ('space', 'path',)
|
||||||
|
|
||||||
# removing ability to delete keywords from admin
|
|
||||||
# to avoid creating orphaned keywords
|
|
||||||
# def get_actions(self, request):
|
|
||||||
# actions = super().get_actions(request)
|
|
||||||
# if 'delete_selected' in actions:
|
|
||||||
# del actions['delete_selected']
|
|
||||||
# return actions
|
|
||||||
|
|
||||||
# def has_delete_permission(self, request, obj=None):
|
|
||||||
# return False
|
|
||||||
|
|
||||||
|
|
||||||
admin.site.register(Keyword, KeywordAdmin)
|
admin.site.register(Keyword, KeywordAdmin)
|
||||||
|
|
||||||
@ -144,7 +133,14 @@ class RecipeAdmin(admin.ModelAdmin):
|
|||||||
admin.site.register(Recipe, RecipeAdmin)
|
admin.site.register(Recipe, RecipeAdmin)
|
||||||
|
|
||||||
admin.site.register(Unit)
|
admin.site.register(Unit)
|
||||||
admin.site.register(Food)
|
|
||||||
|
|
||||||
|
class FoodAdmin(TreeAdmin):
|
||||||
|
form = movenodeform_factory(Keyword)
|
||||||
|
ordering = ('space', 'path',)
|
||||||
|
|
||||||
|
|
||||||
|
admin.site.register(Food, FoodAdmin)
|
||||||
|
|
||||||
|
|
||||||
class IngredientAdmin(admin.ModelAdmin):
|
class IngredientAdmin(admin.ModelAdmin):
|
||||||
|
106
cookbook/migrations/0153_auto_20210915_2327.py
Normal file
106
cookbook/migrations/0153_auto_20210915_2327.py
Normal file
@ -0,0 +1,106 @@
|
|||||||
|
# Generated by Django 3.2.7 on 2021-09-15 21:27
|
||||||
|
|
||||||
|
import django.contrib.postgres.indexes
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('cookbook', '0152_automation'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.RemoveIndex(
|
||||||
|
model_name='cooklog',
|
||||||
|
name='cookbook_co_id_93d841_idx',
|
||||||
|
),
|
||||||
|
migrations.RemoveIndex(
|
||||||
|
model_name='food',
|
||||||
|
name='cookbook_fo_id_22b733_idx',
|
||||||
|
),
|
||||||
|
migrations.RemoveIndex(
|
||||||
|
model_name='ingredient',
|
||||||
|
name='cookbook_in_id_3368be_idx',
|
||||||
|
),
|
||||||
|
migrations.RemoveIndex(
|
||||||
|
model_name='recipe',
|
||||||
|
name='cookbook_re_name_se_bdf3ca_gin',
|
||||||
|
),
|
||||||
|
migrations.RemoveIndex(
|
||||||
|
model_name='recipe',
|
||||||
|
name='cookbook_re_id_e4c2d4_idx',
|
||||||
|
),
|
||||||
|
migrations.RemoveIndex(
|
||||||
|
model_name='recipebook',
|
||||||
|
name='cookbook_re_name_bbe446_idx',
|
||||||
|
),
|
||||||
|
migrations.AddIndex(
|
||||||
|
model_name='cooklog',
|
||||||
|
index=models.Index(fields=['id'], name='cookbook_co_id_553a6d_idx'),
|
||||||
|
),
|
||||||
|
migrations.AddIndex(
|
||||||
|
model_name='cooklog',
|
||||||
|
index=models.Index(fields=['recipe'], name='cookbook_co_recipe__8ec719_idx'),
|
||||||
|
),
|
||||||
|
migrations.AddIndex(
|
||||||
|
model_name='cooklog',
|
||||||
|
index=models.Index(fields=['-created_at'], name='cookbook_co_created_f6e244_idx'),
|
||||||
|
),
|
||||||
|
migrations.AddIndex(
|
||||||
|
model_name='cooklog',
|
||||||
|
index=models.Index(fields=['rating'], name='cookbook_co_rating_aa7662_idx'),
|
||||||
|
),
|
||||||
|
migrations.AddIndex(
|
||||||
|
model_name='cooklog',
|
||||||
|
index=models.Index(fields=['created_by'], name='cookbook_co_created_7ea086_idx'),
|
||||||
|
),
|
||||||
|
migrations.AddIndex(
|
||||||
|
model_name='cooklog',
|
||||||
|
index=models.Index(fields=['created_by', 'rating'], name='cookbook_co_created_f5ccd7_idx'),
|
||||||
|
),
|
||||||
|
migrations.AddIndex(
|
||||||
|
model_name='food',
|
||||||
|
index=models.Index(fields=['id'], name='cookbook_fo_id_3c379b_idx'),
|
||||||
|
),
|
||||||
|
migrations.AddIndex(
|
||||||
|
model_name='food',
|
||||||
|
index=models.Index(fields=['name'], name='cookbook_fo_name_c848b6_idx'),
|
||||||
|
),
|
||||||
|
migrations.AddIndex(
|
||||||
|
model_name='ingredient',
|
||||||
|
index=models.Index(fields=['id'], name='cookbook_in_id_2c1f57_idx'),
|
||||||
|
),
|
||||||
|
migrations.AddIndex(
|
||||||
|
model_name='recipe',
|
||||||
|
index=django.contrib.postgres.indexes.GinIndex(fields=['name_search_vector'], name='cookbook_re_name_se_5dbbd5_gin'),
|
||||||
|
),
|
||||||
|
migrations.AddIndex(
|
||||||
|
model_name='recipe',
|
||||||
|
index=django.contrib.postgres.indexes.GinIndex(fields=['desc_search_vector'], name='cookbook_re_desc_se_fdee30_gin'),
|
||||||
|
),
|
||||||
|
migrations.AddIndex(
|
||||||
|
model_name='recipe',
|
||||||
|
index=models.Index(fields=['id'], name='cookbook_re_id_b2bdcf_idx'),
|
||||||
|
),
|
||||||
|
migrations.AddIndex(
|
||||||
|
model_name='recipe',
|
||||||
|
index=models.Index(fields=['name'], name='cookbook_re_name_b8a027_idx'),
|
||||||
|
),
|
||||||
|
migrations.AddIndex(
|
||||||
|
model_name='recipebook',
|
||||||
|
index=models.Index(fields=['name'], name='cookbook_re_name_94cc63_idx'),
|
||||||
|
),
|
||||||
|
migrations.AddIndex(
|
||||||
|
model_name='viewlog',
|
||||||
|
index=models.Index(fields=['recipe'], name='cookbook_vi_recipe__ce995d_idx'),
|
||||||
|
),
|
||||||
|
migrations.AddIndex(
|
||||||
|
model_name='viewlog',
|
||||||
|
index=models.Index(fields=['-created_at'], name='cookbook_vi_created_bd2b5f_idx'),
|
||||||
|
),
|
||||||
|
migrations.AddIndex(
|
||||||
|
model_name='viewlog',
|
||||||
|
index=models.Index(fields=['created_by'], name='cookbook_vi_created_f9385c_idx'),
|
||||||
|
),
|
||||||
|
]
|
@ -336,7 +336,7 @@ class SyncLog(models.Model, PermissionModelMixin):
|
|||||||
|
|
||||||
class Keyword(ExportModelOperationsMixin('keyword'), TreeModel, PermissionModelMixin):
|
class Keyword(ExportModelOperationsMixin('keyword'), TreeModel, PermissionModelMixin):
|
||||||
# TODO add find and fix problem functions
|
# TODO add find and fix problem functions
|
||||||
node_order_by = ['name']
|
# node_order_by = ['name']
|
||||||
name = models.CharField(max_length=64)
|
name = models.CharField(max_length=64)
|
||||||
icon = models.CharField(max_length=16, blank=True, null=True)
|
icon = models.CharField(max_length=16, blank=True, null=True)
|
||||||
description = models.TextField(default="", blank=True)
|
description = models.TextField(default="", blank=True)
|
||||||
@ -371,7 +371,7 @@ class Unit(ExportModelOperationsMixin('unit'), models.Model, PermissionModelMixi
|
|||||||
|
|
||||||
class Food(ExportModelOperationsMixin('food'), TreeModel, PermissionModelMixin):
|
class Food(ExportModelOperationsMixin('food'), TreeModel, PermissionModelMixin):
|
||||||
# TODO add find and fix problem functions
|
# TODO add find and fix problem functions
|
||||||
node_order_by = ['name']
|
# node_order_by = ['name']
|
||||||
name = models.CharField(max_length=128, validators=[MinLengthValidator(1)])
|
name = models.CharField(max_length=128, validators=[MinLengthValidator(1)])
|
||||||
recipe = models.ForeignKey('Recipe', null=True, blank=True, on_delete=models.SET_NULL)
|
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)
|
supermarket_category = models.ForeignKey(SupermarketCategory, null=True, blank=True, on_delete=models.SET_NULL)
|
||||||
@ -394,7 +394,10 @@ class Food(ExportModelOperationsMixin('food'), TreeModel, PermissionModelMixin):
|
|||||||
constraints = [
|
constraints = [
|
||||||
models.UniqueConstraint(fields=['space', 'name'], name='f_unique_name_per_space')
|
models.UniqueConstraint(fields=['space', 'name'], name='f_unique_name_per_space')
|
||||||
]
|
]
|
||||||
indexes = (Index(fields=['id', 'name']),)
|
indexes = (
|
||||||
|
Index(fields=['id']),
|
||||||
|
Index(fields=['name']),
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class Ingredient(ExportModelOperationsMixin('ingredient'), models.Model, PermissionModelMixin):
|
class Ingredient(ExportModelOperationsMixin('ingredient'), models.Model, PermissionModelMixin):
|
||||||
@ -415,7 +418,9 @@ class Ingredient(ExportModelOperationsMixin('ingredient'), models.Model, Permiss
|
|||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
ordering = ['order', 'pk']
|
ordering = ['order', 'pk']
|
||||||
indexes = (Index(fields=['id', 'food', 'unit']),)
|
indexes = (
|
||||||
|
Index(fields=['id']),
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class Step(ExportModelOperationsMixin('step'), models.Model, PermissionModelMixin):
|
class Step(ExportModelOperationsMixin('step'), models.Model, PermissionModelMixin):
|
||||||
@ -504,7 +509,12 @@ class Recipe(ExportModelOperationsMixin('recipe'), models.Model, PermissionModel
|
|||||||
return self.name
|
return self.name
|
||||||
|
|
||||||
class Meta():
|
class Meta():
|
||||||
indexes = (GinIndex(fields=["name_search_vector", "desc_search_vector"]), Index(fields=['id', 'name', 'description']),)
|
indexes = (
|
||||||
|
GinIndex(fields=["name_search_vector"]),
|
||||||
|
GinIndex(fields=["desc_search_vector"]),
|
||||||
|
Index(fields=['id']),
|
||||||
|
Index(fields=['name']),
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class Comment(ExportModelOperationsMixin('comment'), models.Model, PermissionModelMixin):
|
class Comment(ExportModelOperationsMixin('comment'), models.Model, PermissionModelMixin):
|
||||||
@ -555,7 +565,7 @@ class RecipeBook(ExportModelOperationsMixin('book'), models.Model, PermissionMod
|
|||||||
return self.name
|
return self.name
|
||||||
|
|
||||||
class Meta():
|
class Meta():
|
||||||
indexes = (Index(fields=['name', 'description']),)
|
indexes = (Index(fields=['name']),)
|
||||||
|
|
||||||
|
|
||||||
class RecipeBookEntry(ExportModelOperationsMixin('book_entry'), models.Model, PermissionModelMixin):
|
class RecipeBookEntry(ExportModelOperationsMixin('book_entry'), models.Model, PermissionModelMixin):
|
||||||
@ -756,7 +766,14 @@ class CookLog(ExportModelOperationsMixin('cook_log'), models.Model, PermissionMo
|
|||||||
return self.recipe.name
|
return self.recipe.name
|
||||||
|
|
||||||
class Meta():
|
class Meta():
|
||||||
indexes = (Index(fields=['id', 'recipe', '-created_at', 'rating', 'created_by']),)
|
indexes = (
|
||||||
|
Index(fields=['id']),
|
||||||
|
Index(fields=['recipe']),
|
||||||
|
Index(fields=['-created_at']),
|
||||||
|
Index(fields=['rating']),
|
||||||
|
Index(fields=['created_by']),
|
||||||
|
Index(fields=['created_by', 'rating']),
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class ViewLog(ExportModelOperationsMixin('view_log'), models.Model, PermissionModelMixin):
|
class ViewLog(ExportModelOperationsMixin('view_log'), models.Model, PermissionModelMixin):
|
||||||
@ -771,7 +788,12 @@ class ViewLog(ExportModelOperationsMixin('view_log'), models.Model, PermissionMo
|
|||||||
return self.recipe.name
|
return self.recipe.name
|
||||||
|
|
||||||
class Meta():
|
class Meta():
|
||||||
indexes = (Index(fields=['recipe', '-created_at', 'created_by']),)
|
indexes = (
|
||||||
|
Index(fields=['recipe']),
|
||||||
|
Index(fields=[ '-created_at']),
|
||||||
|
Index(fields=['created_by']),
|
||||||
|
Index(fields=['recipe', '-created_at', 'created_by']),
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class ImportLog(models.Model, PermissionModelMixin):
|
class ImportLog(models.Model, PermissionModelMixin):
|
||||||
|
@ -429,7 +429,7 @@ def test_root_filter(obj_1, obj_1_1, obj_1_1_1, obj_2, obj_3, u1_s1):
|
|||||||
assert len(response['results']) == 2
|
assert len(response['results']) == 2
|
||||||
|
|
||||||
with scopes_disabled():
|
with scopes_disabled():
|
||||||
obj_2.move(obj_1, 'sorted-child')
|
obj_2.move(obj_1, 'last-child')
|
||||||
# should return direct children of obj_1 (obj_1_1, obj_2), ignoring query filters
|
# should return direct children of obj_1 (obj_1_1, obj_2), ignoring query filters
|
||||||
response = json.loads(u1_s1.get(f'{reverse(LIST_URL)}?root={obj_1.id}').content)
|
response = json.loads(u1_s1.get(f'{reverse(LIST_URL)}?root={obj_1.id}').content)
|
||||||
assert response['count'] == 2
|
assert response['count'] == 2
|
||||||
@ -439,7 +439,7 @@ def test_root_filter(obj_1, obj_1_1, obj_1_1_1, obj_2, obj_3, u1_s1):
|
|||||||
|
|
||||||
def test_tree_filter(obj_1, obj_1_1, obj_1_1_1, obj_2, obj_3, u1_s1):
|
def test_tree_filter(obj_1, obj_1_1, obj_1_1_1, obj_2, obj_3, u1_s1):
|
||||||
with scopes_disabled():
|
with scopes_disabled():
|
||||||
obj_2.move(obj_1, 'sorted-child')
|
obj_2.move(obj_1, 'last-child')
|
||||||
# should return full tree starting at obj_1 (obj_1_1_1, obj_2), ignoring query filters
|
# should return full tree starting at obj_1 (obj_1_1_1, obj_2), ignoring query filters
|
||||||
response = json.loads(u1_s1.get(f'{reverse(LIST_URL)}?tree={obj_1.id}').content)
|
response = json.loads(u1_s1.get(f'{reverse(LIST_URL)}?tree={obj_1.id}').content)
|
||||||
assert response['count'] == 4
|
assert response['count'] == 4
|
||||||
|
@ -350,7 +350,7 @@ def test_root_filter(obj_1, obj_1_1, obj_1_1_1, obj_2, obj_3, u1_s1):
|
|||||||
assert len(response['results']) == 2
|
assert len(response['results']) == 2
|
||||||
|
|
||||||
with scopes_disabled():
|
with scopes_disabled():
|
||||||
obj_2.move(obj_1, 'sorted-child')
|
obj_2.move(obj_1, 'last-child')
|
||||||
# should return direct children of obj_1 (obj_1_1, obj_2), ignoring query filters
|
# should return direct children of obj_1 (obj_1_1, obj_2), ignoring query filters
|
||||||
response = json.loads(u1_s1.get(f'{reverse(LIST_URL)}?root={obj_1.id}').content)
|
response = json.loads(u1_s1.get(f'{reverse(LIST_URL)}?root={obj_1.id}').content)
|
||||||
assert response['count'] == 2
|
assert response['count'] == 2
|
||||||
@ -360,7 +360,7 @@ def test_root_filter(obj_1, obj_1_1, obj_1_1_1, obj_2, obj_3, u1_s1):
|
|||||||
|
|
||||||
def test_tree_filter(obj_1, obj_1_1, obj_1_1_1, obj_2, obj_3, u1_s1):
|
def test_tree_filter(obj_1, obj_1_1, obj_1_1_1, obj_2, obj_3, u1_s1):
|
||||||
with scopes_disabled():
|
with scopes_disabled():
|
||||||
obj_2.move(obj_1, 'sorted-child')
|
obj_2.move(obj_1, 'last-child')
|
||||||
# should return full tree starting at obj_1 (obj_1_1_1, obj_2), ignoring query filters
|
# should return full tree starting at obj_1 (obj_1_1_1, obj_2), ignoring query filters
|
||||||
response = json.loads(u1_s1.get(f'{reverse(LIST_URL)}?tree={obj_1.id}').content)
|
response = json.loads(u1_s1.get(f'{reverse(LIST_URL)}?tree={obj_1.id}').content)
|
||||||
assert response['count'] == 4
|
assert response['count'] == 4
|
||||||
|
@ -191,7 +191,7 @@ class MergeMixin(ViewSetMixin): # TODO update Units to use merge API
|
|||||||
if isTree:
|
if isTree:
|
||||||
children = source.get_children().exclude(id=target.id)
|
children = source.get_children().exclude(id=target.id)
|
||||||
for c in children:
|
for c in children:
|
||||||
c.move(target, 'sorted-child')
|
c.move(target, 'last-child')
|
||||||
content = {'msg': _(f'{source.name} was merged successfully with {target.name}')}
|
content = {'msg': _(f'{source.name} was merged successfully with {target.name}')}
|
||||||
source.delete()
|
source.delete()
|
||||||
return Response(content, status=status.HTTP_200_OK)
|
return Response(content, status=status.HTTP_200_OK)
|
||||||
@ -226,7 +226,7 @@ class TreeMixin(MergeMixin, FuzzyFilterMixin):
|
|||||||
self.queryset = self.model.objects.none()
|
self.queryset = self.model.objects.none()
|
||||||
else:
|
else:
|
||||||
return super().get_queryset()
|
return super().get_queryset()
|
||||||
return self.queryset.filter(space=self.request.space)
|
return self.queryset.filter(space=self.request.space).order_by('name')
|
||||||
|
|
||||||
@decorators.action(detail=True, url_path='move/(?P<parent>[^/.]+)', methods=['PUT'], )
|
@decorators.action(detail=True, url_path='move/(?P<parent>[^/.]+)', methods=['PUT'], )
|
||||||
@decorators.renderer_classes((TemplateHTMLRenderer, JSONRenderer))
|
@decorators.renderer_classes((TemplateHTMLRenderer, JSONRenderer))
|
||||||
@ -244,7 +244,7 @@ class TreeMixin(MergeMixin, FuzzyFilterMixin):
|
|||||||
if parent == 0:
|
if parent == 0:
|
||||||
try:
|
try:
|
||||||
with scopes_disabled():
|
with scopes_disabled():
|
||||||
child.move(self.model.get_first_root_node(), 'sorted-sibling')
|
child.move(self.model.get_first_root_node(), 'last-sibling')
|
||||||
content = {'msg': _(f'{child.name} was moved successfully to the root.')}
|
content = {'msg': _(f'{child.name} was moved successfully to the root.')}
|
||||||
return Response(content, status=status.HTTP_200_OK)
|
return Response(content, status=status.HTTP_200_OK)
|
||||||
except (PathOverflow, InvalidMoveToDescendant, InvalidPosition):
|
except (PathOverflow, InvalidMoveToDescendant, InvalidPosition):
|
||||||
@ -262,7 +262,7 @@ class TreeMixin(MergeMixin, FuzzyFilterMixin):
|
|||||||
|
|
||||||
try:
|
try:
|
||||||
with scopes_disabled():
|
with scopes_disabled():
|
||||||
child.move(parent, 'sorted-child')
|
child.move(parent, 'last-child')
|
||||||
content = {'msg': _(f'{child.name} was moved successfully to parent {parent.name}')}
|
content = {'msg': _(f'{child.name} was moved successfully to parent {parent.name}')}
|
||||||
return Response(content, status=status.HTTP_200_OK)
|
return Response(content, status=status.HTTP_200_OK)
|
||||||
except (PathOverflow, InvalidMoveToDescendant, InvalidPosition):
|
except (PathOverflow, InvalidMoveToDescendant, InvalidPosition):
|
||||||
|
Loading…
Reference in New Issue
Block a user