basic space stuff

This commit is contained in:
vabene1111
2021-02-19 11:53:30 +01:00
parent b6b505c361
commit c42266b82c
7 changed files with 249 additions and 175 deletions

View File

@ -3,11 +3,12 @@ from django.conf import settings
from django.contrib.postgres.search import TrigramSimilarity
from django.db.models import Q
from django.utils.translation import gettext as _
from django_scopes import scopes_disabled
from cookbook.forms import MultiSelectWidget
from cookbook.models import Food, Keyword, Recipe, ShoppingList
with scopes_disabled():
class RecipeFilter(django_filters.FilterSet):
name = django_filters.CharFilter(method='filter_name')
keywords = django_filters.ModelMultipleChoiceFilter(

View File

@ -1,6 +1,7 @@
from django import forms
from django.forms import widgets
from django.utils.translation import gettext_lazy as _
from django_scopes.forms import SafeModelChoiceField, SafeModelMultipleChoiceField
from emoji_picker.widgets import EmojiPickerTextInput
from .models import (Comment, Food, InviteLink, Keyword, MealPlan, Recipe,
@ -74,18 +75,13 @@ class UserNameForm(forms.ModelForm):
class ExternalRecipeForm(forms.ModelForm):
file_path = forms.CharField(disabled=True, required=False)
storage = forms.ModelChoiceField(
queryset=Storage.objects.all(),
disabled=True,
required=False
)
file_uid = forms.CharField(disabled=True, required=False)
class Meta:
model = Recipe
fields = (
'name', 'keywords', 'description', 'servings', 'working_time', 'waiting_time',
'file_path', 'storage', 'file_uid'
'name', 'description', 'servings', 'working_time', 'waiting_time',
'file_path', 'file_uid'
)
labels = {
@ -96,39 +92,7 @@ class ExternalRecipeForm(forms.ModelForm):
'file_path': _('Path'),
'file_uid': _('Storage UID'),
}
widgets = {'keywords': MultiSelectWidget}
class InternalRecipeForm(forms.ModelForm):
ingredients = forms.CharField(widget=forms.HiddenInput(), required=False)
class Meta:
model = Recipe
fields = (
'name', 'image', 'working_time',
'waiting_time', 'servings', 'keywords'
)
labels = {
'name': _('Name'),
'keywords': _('Keywords'),
'working_time': _('Preparation time in minutes'),
'waiting_time': _('Waiting time (cooking/baking) in minutes'),
'servings': _('Number of servings'),
}
widgets = {'keywords': MultiSelectWidget}
class ShoppingForm(forms.Form):
recipe = forms.ModelMultipleChoiceField(
queryset=Recipe.objects.filter(internal=True).all(),
widget=MultiSelectWidget
)
markdown_format = forms.BooleanField(
help_text=_('Include <code>- [ ]</code> in list for easier usage in markdown based documents.'), # noqa: E501
required=False,
initial=False
)
# widgets = {'keywords': MultiSelectWidget}
class ImportExportBase(forms.Form):
@ -150,37 +114,44 @@ class ImportForm(ImportExportBase):
class ExportForm(ImportExportBase):
recipes = forms.ModelMultipleChoiceField(queryset=Recipe.objects.filter(internal=True).all(), widget=MultiSelectWidget)
recipes = forms.ModelMultipleChoiceField(widget=MultiSelectWidget, queryset=None)
def __init__(self, *args, **kwargs):
super().__init__()
user = kwargs.pop('user')
self.fields['recipes'].queryset = Recipe.objects.filter(internal=True).filter(space=user.userpreference.space).all()
class UnitMergeForm(forms.Form):
prefix = 'unit'
new_unit = forms.ModelChoiceField(
queryset=Unit.objects.all(),
new_unit = SafeModelChoiceField(
queryset=Unit.objects.none(),
widget=SelectWidget,
label=_('New Unit'),
help_text=_('New unit that other gets replaced by.'),
)
old_unit = forms.ModelChoiceField(
queryset=Unit.objects.all(),
old_unit = SafeModelChoiceField(
queryset=Unit.objects.none(),
widget=SelectWidget,
label=_('Old Unit'),
help_text=_('Unit that should be replaced.'),
)
# todo spaces form here on
class FoodMergeForm(forms.Form):
prefix = 'food'
new_food = forms.ModelChoiceField(
queryset=Food.objects.all(),
new_food = SafeModelChoiceField(
queryset=Food.objects.none(),
widget=SelectWidget,
label=_('New Food'),
help_text=_('New food that other gets replaced by.'),
)
old_food = forms.ModelChoiceField(
queryset=Food.objects.all(),
old_food = SafeModelChoiceField(
queryset=Food.objects.none(),
widget=SelectWidget,
label=_('Old Food'),
help_text=_('Food that should be replaced.'),
@ -215,6 +186,11 @@ class FoodForm(forms.ModelForm):
fields = ('name', 'description', 'ignore_shopping', 'recipe', 'supermarket_category')
widgets = {'recipe': SelectWidget}
field_classes = {
'recipe': SafeModelChoiceField,
'supermarket_category': SafeModelChoiceField,
}
class StorageForm(forms.ModelForm):
username = forms.CharField(
@ -252,17 +228,25 @@ class RecipeBookEntryForm(forms.ModelForm):
model = RecipeBookEntry
fields = ('book',)
field_classes = {
'book': SafeModelChoiceField,
}
class SyncForm(forms.ModelForm):
class Meta:
model = Sync
fields = ('storage', 'path', 'active')
field_classes = {
'storage': SafeModelChoiceField,
}
class BatchEditForm(forms.Form):
search = forms.CharField(label=_('Search String'))
keywords = forms.ModelMultipleChoiceField(
queryset=Keyword.objects.all().order_by('id'),
queryset=Keyword.objects.none().order_by('id'),
required=False,
widget=MultiSelectWidget
)
@ -280,6 +264,9 @@ class ImportRecipeForm(forms.ModelForm):
'file_uid': _('File ID'),
}
widgets = {'keywords': MultiSelectWidget}
field_classes = {
'keywords': SafeModelChoiceField,
}
class RecipeBookForm(forms.ModelForm):
@ -287,6 +274,9 @@ class RecipeBookForm(forms.ModelForm):
model = RecipeBook
fields = ('name', 'icon', 'description', 'shared')
widgets = {'icon': EmojiPickerTextInput, 'shared': MultiSelectWidget}
field_classes = {
'shared': SafeModelMultipleChoiceField,
}
class MealPlanForm(forms.ModelForm):
@ -318,6 +308,11 @@ class MealPlanForm(forms.ModelForm):
'date': DateWidget,
'shared': MultiSelectWidget
}
field_classes = {
'recipe': SafeModelChoiceField,
'meal_type': SafeModelChoiceField,
'shared': SafeModelMultipleChoiceField,
}
class InviteLinkForm(forms.ModelForm):

View File

@ -10,6 +10,7 @@ from django.db import models
from django.utils import timezone
from django.utils.translation import gettext as _
from django_random_queryset import RandomManager
from django_scopes import ScopedManager
from recipes.settings import (COMMENT_PREF_DEFAULT, FRACTION_PREF_DEFAULT,
STICKY_NAV_PREF_DEFAULT)
@ -107,6 +108,9 @@ class UserPreference(models.Model):
shopping_auto_sync = models.IntegerField(default=5)
sticky_navbar = models.BooleanField(default=STICKY_NAV_PREF_DEFAULT)
space = models.ForeignKey(Space, blank=True, on_delete=models.CASCADE)
objects = ScopedManager(space='space')
def __str__(self):
return str(self.user)
@ -128,6 +132,9 @@ class Storage(models.Model):
path = models.CharField(blank=True, default='', max_length=256)
created_by = models.ForeignKey(User, on_delete=models.PROTECT)
space = models.ForeignKey(Space, blank=True, on_delete=models.CASCADE)
objects = ScopedManager(space='space')
def __str__(self):
return self.name
@ -140,6 +147,9 @@ class Sync(models.Model):
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
space = models.ForeignKey(Space, blank=True, on_delete=models.CASCADE)
objects = ScopedManager(space='space')
def __str__(self):
return self.path
@ -148,6 +158,9 @@ class SupermarketCategory(models.Model):
name = models.CharField(unique=True, max_length=128, validators=[MinLengthValidator(1)])
description = models.TextField(blank=True, null=True)
space = models.ForeignKey(Space, blank=True, on_delete=models.CASCADE)
objects = ScopedManager(space='space')
def __str__(self):
return self.name
@ -157,6 +170,9 @@ class Supermarket(models.Model):
description = models.TextField(blank=True, null=True)
categories = models.ManyToManyField(SupermarketCategory, through='SupermarketCategoryRelation')
space = models.ForeignKey(Space, blank=True, on_delete=models.CASCADE)
objects = ScopedManager(space='space')
def __str__(self):
return self.name
@ -166,6 +182,8 @@ class SupermarketCategoryRelation(models.Model):
category = models.ForeignKey(SupermarketCategory, on_delete=models.CASCADE, related_name='category_to_supermarket')
order = models.IntegerField(default=0)
objects = ScopedManager(space='supermarket__space')
class Meta:
ordering = ('order',)
@ -176,6 +194,9 @@ class SyncLog(models.Model):
msg = models.TextField(default="")
created_at = models.DateTimeField(auto_now_add=True)
space = models.ForeignKey(Space, blank=True, on_delete=models.CASCADE)
objects = ScopedManager(space='space')
def __str__(self):
return f"{self.created_at}:{self.sync} - {self.status}"
@ -187,6 +208,9 @@ class Keyword(models.Model):
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
space = models.ForeignKey(Space, blank=True, on_delete=models.CASCADE)
objects = ScopedManager(space='space')
def __str__(self):
if self.icon:
return f"{self.icon} {self.name}"
@ -198,6 +222,9 @@ class Unit(models.Model):
name = models.CharField(unique=True, max_length=128, validators=[MinLengthValidator(1)])
description = models.TextField(blank=True, null=True)
space = models.ForeignKey(Space, blank=True, on_delete=models.CASCADE)
objects = ScopedManager(space='space')
def __str__(self):
return self.name
@ -209,6 +236,9 @@ class Food(models.Model):
ignore_shopping = models.BooleanField(default=False)
description = models.TextField(default='', blank=True)
space = models.ForeignKey(Space, blank=True, on_delete=models.CASCADE)
objects = ScopedManager(space='space')
def __str__(self):
return self.name
@ -226,6 +256,8 @@ class Ingredient(models.Model):
no_amount = models.BooleanField(default=False)
order = models.IntegerField(default=0)
objects = ScopedManager(space='step__recipe__space')
def __str__(self):
return str(self.amount) + ' ' + str(self.unit) + ' ' + str(self.food)
@ -249,6 +281,8 @@ class Step(models.Model):
order = models.IntegerField(default=0)
show_as_header = models.BooleanField(default=True)
objects = ScopedManager(space='recipe__space')
def get_instruction_render(self):
from cookbook.helper.template_helper import render_instructions
return render_instructions(self)
@ -268,6 +302,8 @@ class NutritionInformation(models.Model):
max_length=512, default="", null=True, blank=True
)
objects = ScopedManager(space='recipe__space')
def __str__(self):
return 'Nutrition'
@ -297,7 +333,8 @@ class Recipe(models.Model):
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
objects = RandomManager()
space = models.ForeignKey(Space, blank=True, on_delete=models.CASCADE)
objects = ScopedManager(space='space')
def __str__(self):
return self.name
@ -310,6 +347,8 @@ class Comment(models.Model):
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
objects = ScopedManager(space='recipe__space')
def __str__(self):
return self.text
@ -321,6 +360,9 @@ class RecipeImport(models.Model):
file_path = models.CharField(max_length=512, default="")
created_at = models.DateTimeField(auto_now_add=True)
space = models.ForeignKey(Space, blank=True, on_delete=models.CASCADE)
objects = ScopedManager(space='space')
def __str__(self):
return self.name
@ -334,6 +376,9 @@ class RecipeBook(models.Model):
)
created_by = models.ForeignKey(User, on_delete=models.CASCADE)
space = models.ForeignKey(Space, blank=True, on_delete=models.CASCADE)
objects = ScopedManager(space='space')
def __str__(self):
return self.name
@ -342,6 +387,9 @@ class RecipeBookEntry(models.Model):
recipe = models.ForeignKey(Recipe, on_delete=models.CASCADE)
book = models.ForeignKey(RecipeBook, on_delete=models.CASCADE)
space = models.ForeignKey(Space, blank=True, on_delete=models.CASCADE)
objects = ScopedManager(space='space')
def __str__(self):
return self.recipe.name
@ -360,6 +408,9 @@ class MealType(models.Model):
order = models.IntegerField(default=0)
created_by = models.ForeignKey(User, on_delete=models.CASCADE)
space = models.ForeignKey(Space, blank=True, on_delete=models.CASCADE)
objects = ScopedManager(space='space')
def __str__(self):
return self.name
@ -378,6 +429,9 @@ class MealPlan(models.Model):
note = models.TextField(blank=True)
date = models.DateField()
space = models.ForeignKey(Space, blank=True, on_delete=models.CASCADE)
objects = ScopedManager(space='space')
def get_label(self):
if self.title:
return self.title
@ -396,6 +450,9 @@ class ShoppingListRecipe(models.Model):
)
servings = models.DecimalField(default=1, max_digits=8, decimal_places=4)
space = models.ForeignKey(Space, blank=True, on_delete=models.CASCADE)
objects = ScopedManager(space='space')
def __str__(self):
return f'Shopping list recipe {self.id} - {self.recipe}'
@ -414,6 +471,9 @@ class ShoppingListEntry(models.Model):
order = models.IntegerField(default=0)
checked = models.BooleanField(default=False)
space = models.ForeignKey(Space, blank=True, on_delete=models.CASCADE)
objects = ScopedManager(space='space')
def __str__(self):
return f'Shopping list entry {self.id}'
@ -435,6 +495,9 @@ class ShoppingList(models.Model):
created_by = models.ForeignKey(User, on_delete=models.CASCADE)
created_at = models.DateTimeField(auto_now_add=True)
space = models.ForeignKey(Space, blank=True, on_delete=models.CASCADE)
objects = ScopedManager(space='space')
def __str__(self):
return f'Shopping list {self.id}'
@ -445,6 +508,9 @@ class ShareLink(models.Model):
created_by = models.ForeignKey(User, on_delete=models.CASCADE)
created_at = models.DateTimeField(auto_now_add=True)
space = models.ForeignKey(Space, blank=True, on_delete=models.CASCADE)
objects = ScopedManager(space='space')
def __str__(self):
return f'{self.recipe} - {self.uuid}'
@ -464,6 +530,9 @@ class InviteLink(models.Model):
created_by = models.ForeignKey(User, on_delete=models.CASCADE)
created_at = models.DateTimeField(auto_now_add=True)
space = models.ForeignKey(Space, blank=True, on_delete=models.CASCADE)
objects = ScopedManager(space='space')
def __str__(self):
return f'{self.uuid}'
@ -475,6 +544,9 @@ class CookLog(models.Model):
rating = models.IntegerField(null=True)
servings = models.IntegerField(default=0)
space = models.ForeignKey(Space, blank=True, on_delete=models.CASCADE)
objects = ScopedManager(space='space')
def __str__(self):
return self.recipe.name
@ -484,5 +556,8 @@ class ViewLog(models.Model):
created_by = models.ForeignKey(User, on_delete=models.CASCADE)
created_at = models.DateTimeField(auto_now_add=True)
space = models.ForeignKey(Space, blank=True, on_delete=models.CASCADE)
objects = ScopedManager(space='space')
def __str__(self):
return self.recipe.name

View File

@ -89,7 +89,6 @@ urlpatterns = [
path('api/log_cooking/<int:recipe_id>/', api.log_cooking, name='api_log_cooking'),
path('api/plan-ical/<slug:from_date>/<slug:to_date>/', api.get_plan_ical, name='api_get_plan_ical'),
path('api/recipe-from-url/', api.recipe_from_url, name='api_recipe_from_url'),
path('api/backup/', api.get_backup, name='api_backup'),
path('api/ingredient-from-string/', api.ingredient_from_string, name='api_ingredient_from_string'),
path('dal/keyword/', dal.KeywordAutocomplete.as_view(), name='dal_keyword'),

View File

@ -59,7 +59,7 @@ from recipes.settings import DEMO
class StandardFilterMixin(ViewSetMixin):
def get_queryset(self):
queryset = self.queryset
queryset = self.queryset.filter(userpreference__space=self.request.user.userpreference.space)
query = self.request.query_params.get('query', None)
if query is not None:
queryset = queryset.filter(name__icontains=query)
@ -90,13 +90,13 @@ class UserNameViewSet(viewsets.ReadOnlyModelViewSet):
- **filter_list**: array of user id's to get names for
"""
queryset = User.objects.all()
queryset = User.objects
serializer_class = UserNameSerializer
permission_classes = [CustomIsGuest]
http_method_names = ['get']
def get_queryset(self):
queryset = self.queryset
queryset = self.queryset.filter(userpreference__space=self.request.user.userpreference.space)
try:
filter_list = self.request.query_params.get('filter_list', None)
if filter_list is not None:
@ -110,7 +110,7 @@ class UserNameViewSet(viewsets.ReadOnlyModelViewSet):
class UserPreferenceViewSet(viewsets.ModelViewSet):
queryset = UserPreference.objects.all()
queryset = UserPreference.objects
serializer_class = UserPreferenceSerializer
permission_classes = [CustomIsOwner, ]
@ -120,35 +120,45 @@ class UserPreferenceViewSet(viewsets.ModelViewSet):
serializer.save(user=self.request.user)
def get_queryset(self):
if self.request.user.is_superuser:
return self.queryset
return self.queryset.filter(user=self.request.user)
class StorageViewSet(viewsets.ModelViewSet):
# TODO handle delete protect error and adjust test
queryset = Storage.objects.all()
queryset = Storage.objects
serializer_class = StorageSerializer
permission_classes = [CustomIsAdmin, ]
def get_queryset(self):
return self.queryset.filter(space=self.request.user.userpreference.space)
class SyncViewSet(viewsets.ModelViewSet):
queryset = Sync.objects.all()
queryset = Sync.objects
serializer_class = SyncSerializer
permission_classes = [CustomIsAdmin, ]
def get_queryset(self):
return self.queryset.filter(space=self.request.user.userpreference.space)
class SyncLogViewSet(viewsets.ReadOnlyModelViewSet):
queryset = SyncLog.objects.all()
queryset = SyncLog.objects
serializer_class = SyncLogSerializer
permission_classes = [CustomIsAdmin, ]
def get_queryset(self):
return self.queryset.filter(space=self.request.user.userpreference.space)
class SupermarketViewSet(viewsets.ModelViewSet, StandardFilterMixin):
queryset = Supermarket.objects.all()
queryset = Supermarket.objects
serializer_class = SupermarketSerializer
permission_classes = [CustomIsUser]
def get_queryset(self):
return self.queryset.filter(space=self.request.user.userpreference.space)
class KeywordViewSet(viewsets.ModelViewSet, StandardFilterMixin):
"""
@ -159,44 +169,48 @@ class KeywordViewSet(viewsets.ModelViewSet, StandardFilterMixin):
in the keyword name (case in-sensitive)
- **limit**: limits the amount of returned results
"""
queryset = Keyword.objects.all()
queryset = Keyword.objects
serializer_class = KeywordSerializer
permission_classes = [CustomIsUser]
def get_queryset(self):
return self.queryset.filter(space=self.request.user.userpreference.space)
class UnitViewSet(viewsets.ModelViewSet, StandardFilterMixin):
queryset = Unit.objects.all()
queryset = Unit.objects
serializer_class = UnitSerializer
permission_classes = [CustomIsUser]
def get_queryset(self):
return self.queryset.filter(space=self.request.user.userpreference.space)
class FoodViewSet(viewsets.ModelViewSet, StandardFilterMixin):
queryset = Food.objects.all()
queryset = Food.objects
serializer_class = FoodSerializer
permission_classes = [CustomIsUser]
def get_queryset(self):
return self.queryset.filter(space=self.request.user.userpreference.space)
class RecipeBookViewSet(viewsets.ModelViewSet, StandardFilterMixin):
queryset = RecipeBook.objects.all()
queryset = RecipeBook.objects
serializer_class = RecipeBookSerializer
permission_classes = [CustomIsOwner]
def get_queryset(self):
self.queryset = super(RecipeBookViewSet, self).get_queryset()
if self.request.user.is_superuser:
return self.queryset
return self.queryset.filter(created_by=self.request.user)
return self.queryset.filter(created_by=self.request.user).filter(space=self.request.user.userpreference.space)
class RecipeBookEntryViewSet(viewsets.ModelViewSet, viewsets.GenericViewSet):
queryset = RecipeBookEntry.objects.all()
queryset = RecipeBookEntry.objects
serializer_class = RecipeBookEntrySerializer
permission_classes = [CustomIsOwner]
def get_queryset(self):
if self.request.user.is_superuser:
return self.queryset
return self.queryset.filter(created_by=self.request.user)
return self.queryset.filter(created_by=self.request.user).filter(space=self.request.user.userpreference.space)
class MealPlanViewSet(viewsets.ModelViewSet):
@ -208,15 +222,15 @@ class MealPlanViewSet(viewsets.ModelViewSet):
- **to_date**: filter upward to (inclusive) certain date
"""
queryset = MealPlan.objects.all()
queryset = MealPlan.objects
serializer_class = MealPlanSerializer
permission_classes = [CustomIsOwner]
def get_queryset(self):
queryset = MealPlan.objects.filter(
queryset = self.queryset.filter(
Q(created_by=self.request.user) |
Q(shared=self.request.user)
).distinct().all()
).filter(space=self.request.user.userpreference.space).distinct().all()
from_date = self.request.query_params.get('from_date', None)
if from_date is not None:
@ -233,26 +247,32 @@ class MealTypeViewSet(viewsets.ModelViewSet):
returns list of meal types created by the
requesting user ordered by the order field.
"""
queryset = MealType.objects.order_by('order').all()
queryset = MealType.objects
serializer_class = MealTypeSerializer
permission_classes = [CustomIsOwner]
def get_queryset(self):
queryset = MealType.objects.order_by('order', 'id').filter(created_by=self.request.user).all()
queryset = self.queryset.order_by('order', 'id').filter(created_by=self.request.user).filter(space=self.request.user.userpreference.space).all()
return queryset
class IngredientViewSet(viewsets.ModelViewSet):
queryset = Ingredient.objects.all()
queryset = Ingredient.objects
serializer_class = IngredientSerializer
permission_classes = [CustomIsUser]
def get_queryset(self):
return self.queryset.filter(step__recipe__space=self.request.user.userpreference.space)
class StepViewSet(viewsets.ModelViewSet):
queryset = Step.objects.all()
queryset = Step.objects
serializer_class = StepSerializer
permission_classes = [CustomIsUser]
def get_queryset(self):
return self.queryset.filter(recipe__space=self.request.user.userpreference.space)
class RecipeViewSet(viewsets.ModelViewSet, StandardFilterMixin):
"""
@ -263,18 +283,19 @@ class RecipeViewSet(viewsets.ModelViewSet, StandardFilterMixin):
in the recipe name (case in-sensitive)
- **limit**: limits the amount of returned results
"""
queryset = Recipe.objects.all()
queryset = Recipe.objects
serializer_class = RecipeSerializer
# TODO split read and write permission for meal plan guest
permission_classes = [CustomIsShare | CustomIsGuest]
def get_queryset(self):
queryset = self.queryset.filter(space=self.request.user.userpreference.space)
internal = self.request.query_params.get('internal', None)
if internal:
self.queryset = self.queryset.filter(internal=True)
queryset = queryset.filter(internal=True)
return super().get_queryset()
return queryset
# TODO write extensive tests for permissions
@ -317,34 +338,32 @@ class RecipeViewSet(viewsets.ModelViewSet, StandardFilterMixin):
class ShoppingListRecipeViewSet(viewsets.ModelViewSet):
queryset = ShoppingListRecipe.objects.all()
queryset = ShoppingListRecipe.objects
serializer_class = ShoppingListRecipeSerializer
permission_classes = [CustomIsOwner, ]
def get_queryset(self):
return self.queryset.filter(shoppinglist__created_by=self.request.user).all()
return self.queryset.filter(shoppinglist__created_by=self.request.user).filter(space=self.request.user.userpreference.space).all()
class ShoppingListEntryViewSet(viewsets.ModelViewSet):
queryset = ShoppingListEntry.objects.all()
queryset = ShoppingListEntry.objects
serializer_class = ShoppingListEntrySerializer
permission_classes = [CustomIsOwner, ]
def get_queryset(self):
return self.queryset.filter(shoppinglist__created_by=self.request.user).all()
return self.queryset.filter(shoppinglist__created_by=self.request.user).filter(space=self.request.user.userpreference.space).all()
class ShoppingListViewSet(viewsets.ModelViewSet):
queryset = ShoppingList.objects.all()
queryset = ShoppingList.objects
serializer_class = ShoppingListSerializer
permission_classes = [CustomIsOwner | CustomIsShared]
def get_queryset(self):
if self.request.user.is_superuser:
return self.queryset
return self.queryset.filter(
Q(created_by=self.request.user) | Q(shared=self.request.user)
).all()
).filter(space=self.request.user.userpreference.space).all()
def get_serializer_class(self):
autosync = self.request.query_params.get('autosync', None)
@ -354,21 +373,21 @@ class ShoppingListViewSet(viewsets.ModelViewSet):
class ViewLogViewSet(viewsets.ModelViewSet):
queryset = ViewLog.objects.all()
queryset = ViewLog.objects
serializer_class = ViewLogSerializer
permission_classes = [CustomIsOwner]
def get_queryset(self):
return CookLog.objects.filter(created_by=self.request.user).all()[:5]
return CookLog.objects.filter(created_by=self.request.user).filter(space=self.request.user.userpreference.space).all()[:5]
class CookLogViewSet(viewsets.ModelViewSet):
queryset = CookLog.objects.all()
queryset = CookLog.objects
serializer_class = CookLogSerializer
permission_classes = [CustomIsOwner]
def get_queryset(self):
queryset = CookLog.objects.filter(created_by=self.request.user).all()[:5]
queryset = CookLog.objects.filter(created_by=self.request.user).filter(space=self.request.user.userpreference.space).all()[:5]
return queryset
@ -395,7 +414,7 @@ def update_recipe_links(recipe):
@group_required('user')
def get_external_file_link(request, recipe_id):
recipe = Recipe.objects.get(id=recipe_id)
recipe = Recipe.objects.filter(space=request.user.userpreference.space).get(id=recipe_id)
if not recipe.link:
update_recipe_links(recipe)
@ -404,7 +423,7 @@ def get_external_file_link(request, recipe_id):
@group_required('guest')
def get_recipe_file(request, recipe_id):
recipe = Recipe.objects.get(id=recipe_id)
recipe = Recipe.objects.filter(space=request.user.userpreference.space).get(id=recipe_id)
if recipe.storage:
return FileResponse(get_recipe_provider(recipe).get_file(recipe))
else:
@ -419,7 +438,7 @@ def sync_all(request):
)
return redirect('index')
monitors = Sync.objects.filter(active=True)
monitors = Sync.objects.filter(active=True).filter(space=request.user.userpreference.space)
error = False
for monitor in monitors:
@ -471,7 +490,7 @@ def log_cooking(request, recipe_id):
def get_plan_ical(request, from_date, to_date):
queryset = MealPlan.objects.filter(
Q(created_by=request.user) | Q(shared=request.user)
).distinct().all()
).filter(space=request.user.userpreference.space).distinct().all()
if from_date is not None:
queryset = queryset.filter(date__gte=from_date)
@ -525,22 +544,6 @@ def recipe_from_url(request):
return get_from_html(response.text, url)
@group_required('admin')
def get_backup(request):
if not request.user.is_superuser:
return HttpResponse('', status=403)
buf = io.StringIO()
management.call_command(
'dumpdata', exclude=['contenttypes', 'auth'], stdout=buf
)
response = FileResponse(buf.getvalue())
response["Content-Disposition"] = f'attachment; filename=backup{date_format(timezone.now(), format="SHORT_DATETIME_FORMAT", use_l10n=True)}.json' # noqa: E501
return response
@group_required('user')
def ingredient_from_string(request):
text = request.POST['text']

View File

@ -49,7 +49,7 @@ def import_recipe(request):
@group_required('user')
def export_recipe(request):
if request.method == "POST":
form = ExportForm(request.POST)
form = ExportForm(request.POST, user=request.user)
if form.is_valid():
try:
integration = get_integration(request, form.cleaned_data['type'])
@ -58,11 +58,11 @@ def export_recipe(request):
messages.add_message(request, messages.ERROR, _('Exporting is not implemented for this provider'))
else:
form = ExportForm()
form = ExportForm(user=request.user)
recipe = request.GET.get('r')
if recipe:
if re.match(r'^([0-9])+$', recipe):
if recipe := Recipe.objects.filter(pk=int(recipe)).first():
form = ExportForm(initial={'recipes': recipe})
form = ExportForm(initial={'recipes': recipe}, user=request.user)
return render(request, 'export.html', {'form': form})

View File

@ -31,3 +31,4 @@ Jinja2==2.11.3
django-webpack-loader==0.7.0
django-js-reverse==0.9.1
django-allauth==0.44.0
django-scopes==1.2.0