Added menu upload files
This commit is contained in:
parent
2b0663b702
commit
e067e8e793
|
|
@ -30,10 +30,13 @@ from main.models import Award, Currency
|
|||
from review.models import Review
|
||||
from tag.models import Tag
|
||||
from utils.methods import transform_into_readable_str
|
||||
from utils.models import (ProjectBaseMixin, TJSONField, URLImageMixin,
|
||||
TranslatedFieldsMixin, BaseAttributes, GalleryMixin,
|
||||
IntermediateGalleryModelMixin, HasTagsMixin,
|
||||
FavoritesMixin, TypeDefaultImageMixin)
|
||||
from utils.models import (
|
||||
ProjectBaseMixin, TJSONField, URLImageMixin,
|
||||
TranslatedFieldsMixin, BaseAttributes, GalleryMixin,
|
||||
IntermediateGalleryModelMixin, HasTagsMixin,
|
||||
FavoritesMixin, TypeDefaultImageMixin, FileMixin,
|
||||
ImageMixin,
|
||||
)
|
||||
|
||||
|
||||
# todo: establishment type&subtypes check
|
||||
|
|
@ -1272,6 +1275,7 @@ class Menu(GalleryMixin, TranslatedFieldsMixin, BaseAttributes):
|
|||
|
||||
STR_FIELD_NAME = 'category'
|
||||
|
||||
name = models.CharField(_('name'), max_length=255, default='')
|
||||
category = TJSONField(
|
||||
blank=True, null=True, default=None, verbose_name=_('category'),
|
||||
help_text='{"en-GB":"some text"}')
|
||||
|
|
@ -1282,9 +1286,14 @@ class Menu(GalleryMixin, TranslatedFieldsMixin, BaseAttributes):
|
|||
schedule = models.ManyToManyField(
|
||||
to='timetable.Timetable',
|
||||
blank=True,
|
||||
verbose_name=_('Establishment schedule'),
|
||||
related_name='menus',
|
||||
verbose_name=_('Menu schedule'),
|
||||
)
|
||||
uploads = models.ManyToManyField(
|
||||
to='MenuFiles',
|
||||
blank=True,
|
||||
verbose_name=_('Menu files'),
|
||||
)
|
||||
|
||||
old_id = models.PositiveIntegerField(_('old id'), blank=True, null=True, default=None)
|
||||
|
||||
objects = MenuQuerySet.as_manager()
|
||||
|
|
@ -1295,43 +1304,11 @@ class Menu(GalleryMixin, TranslatedFieldsMixin, BaseAttributes):
|
|||
ordering = ('-created',)
|
||||
|
||||
|
||||
class MenuGallery(IntermediateGalleryModelMixin):
|
||||
menu = models.ForeignKey(
|
||||
Menu,
|
||||
null=True,
|
||||
related_name='menu_gallery',
|
||||
on_delete=models.CASCADE,
|
||||
verbose_name=_('menu'),
|
||||
)
|
||||
image = models.ForeignKey(
|
||||
'gallery.Image',
|
||||
null=True,
|
||||
related_name='menu_gallery',
|
||||
on_delete=models.CASCADE,
|
||||
verbose_name=_('image'),
|
||||
)
|
||||
|
||||
class Meta:
|
||||
"""Meta class."""
|
||||
verbose_name = _('menu gallery')
|
||||
verbose_name_plural = _('menu galleries')
|
||||
unique_together = (('menu', 'is_main'), ('menu', 'image'))
|
||||
|
||||
|
||||
class MenuUploads(BaseAttributes):
|
||||
class MenuFiles(FileMixin, BaseAttributes):
|
||||
"""Menu files"""
|
||||
|
||||
menu = models.ForeignKey(
|
||||
Menu,
|
||||
verbose_name=_('menu'),
|
||||
on_delete=models.CASCADE,
|
||||
related_name='menu_uploads',
|
||||
)
|
||||
title = models.CharField(_('title'), max_length=255, default='')
|
||||
file = models.FileField(
|
||||
_('File'),
|
||||
validators=[FileExtensionValidator(allowed_extensions=('doc', 'docx', 'pdf')), ],
|
||||
)
|
||||
name = models.CharField(_('name'), max_length=255, default='')
|
||||
type = models.CharField(_('type'), max_length=65, default='')
|
||||
|
||||
class Meta:
|
||||
verbose_name = _('menu upload')
|
||||
|
|
|
|||
|
|
@ -639,50 +639,50 @@ class MenuDishesRUDSerializers(ProjectModelSerializer):
|
|||
]
|
||||
|
||||
|
||||
class MenuGallerySerializer(serializers.ModelSerializer):
|
||||
"""Serializer class for model MenuGallery."""
|
||||
|
||||
class Meta:
|
||||
"""Meta class"""
|
||||
|
||||
model = models.MenuGallery
|
||||
fields = [
|
||||
'id',
|
||||
'is_main',
|
||||
]
|
||||
|
||||
@property
|
||||
def request_kwargs(self):
|
||||
"""Get url kwargs from request."""
|
||||
return self.context.get('request').parser_context.get('kwargs')
|
||||
|
||||
def create(self, validated_data):
|
||||
menu_pk = self.request_kwargs.get('pk')
|
||||
image_id = self.request_kwargs.get('image_id')
|
||||
qs = models.MenuGallery.objects.filter(image_id=image_id, menu_id=menu_pk)
|
||||
instance = qs.first()
|
||||
if instance:
|
||||
qs.update(**validated_data)
|
||||
return instance
|
||||
return super().create(validated_data)
|
||||
|
||||
def validate(self, attrs):
|
||||
"""Override validate method."""
|
||||
menu_pk = self.request_kwargs.get('pk')
|
||||
image_id = self.request_kwargs.get('image_id')
|
||||
|
||||
menu_qs = models.Menu.objects.filter(pk=menu_pk)
|
||||
image_qs = Image.objects.filter(id=image_id)
|
||||
|
||||
if not menu_qs.exists():
|
||||
raise serializers.ValidationError({'detail': _('Menu not found')})
|
||||
if not image_qs.exists():
|
||||
raise serializers.ValidationError({'detail': _('Image not found')})
|
||||
|
||||
menu = menu_qs.first()
|
||||
image = image_qs.first()
|
||||
|
||||
attrs['menu'] = menu
|
||||
attrs['image'] = image
|
||||
|
||||
return attrs
|
||||
# class MenuGallerySerializer(serializers.ModelSerializer):
|
||||
# """Serializer class for model MenuGallery."""
|
||||
#
|
||||
# class Meta:
|
||||
# """Meta class"""
|
||||
#
|
||||
# model = models.MenuGallery
|
||||
# fields = [
|
||||
# 'id',
|
||||
# 'is_main',
|
||||
# ]
|
||||
#
|
||||
# @property
|
||||
# def request_kwargs(self):
|
||||
# """Get url kwargs from request."""
|
||||
# return self.context.get('request').parser_context.get('kwargs')
|
||||
#
|
||||
# def create(self, validated_data):
|
||||
# menu_pk = self.request_kwargs.get('pk')
|
||||
# image_id = self.request_kwargs.get('image_id')
|
||||
# qs = models.MenuGallery.objects.filter(image_id=image_id, menu_id=menu_pk)
|
||||
# instance = qs.first()
|
||||
# if instance:
|
||||
# qs.update(**validated_data)
|
||||
# return instance
|
||||
# return super().create(validated_data)
|
||||
#
|
||||
# def validate(self, attrs):
|
||||
# """Override validate method."""
|
||||
# menu_pk = self.request_kwargs.get('pk')
|
||||
# image_id = self.request_kwargs.get('image_id')
|
||||
#
|
||||
# menu_qs = models.Menu.objects.filter(pk=menu_pk)
|
||||
# image_qs = Image.objects.filter(id=image_id)
|
||||
#
|
||||
# if not menu_qs.exists():
|
||||
# raise serializers.ValidationError({'detail': _('Menu not found')})
|
||||
# if not image_qs.exists():
|
||||
# raise serializers.ValidationError({'detail': _('Image not found')})
|
||||
#
|
||||
# menu = menu_qs.first()
|
||||
# image = image_qs.first()
|
||||
#
|
||||
# attrs['menu'] = menu
|
||||
# attrs['image'] = image
|
||||
#
|
||||
# return attrs
|
||||
|
|
|
|||
|
|
@ -9,18 +9,25 @@ from rest_framework import serializers
|
|||
from comment import models as comment_models
|
||||
from comment.serializers import common as comment_serializers
|
||||
from establishment import models
|
||||
from location.serializers import AddressBaseSerializer, CityBaseSerializer, AddressDetailSerializer, \
|
||||
CityShortSerializer
|
||||
from location.serializers import EstablishmentWineRegionBaseSerializer, \
|
||||
EstablishmentWineOriginBaseSerializer
|
||||
from establishment.models import Establishment
|
||||
from location.serializers import (
|
||||
AddressBaseSerializer, CityBaseSerializer, AddressDetailSerializer,
|
||||
CityShortSerializer,
|
||||
)
|
||||
from location.serializers import (
|
||||
EstablishmentWineRegionBaseSerializer,
|
||||
EstablishmentWineOriginBaseSerializer,
|
||||
)
|
||||
from main.serializers import AwardSerializer, CurrencySerializer
|
||||
from review.serializers import ReviewShortSerializer
|
||||
from tag.serializers import TagBaseSerializer
|
||||
from timetable.serialziers import ScheduleRUDSerializer
|
||||
from utils import exceptions as utils_exceptions
|
||||
from utils.serializers import ImageBaseSerializer, CarouselCreateSerializer
|
||||
from utils.serializers import (ProjectModelSerializer, TranslatedField,
|
||||
FavoritesCreateSerializer)
|
||||
from utils.serializers import (
|
||||
ProjectModelSerializer, TranslatedField,
|
||||
FavoritesCreateSerializer,
|
||||
)
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
|
@ -71,19 +78,50 @@ class PlateSerializer(ProjectModelSerializer):
|
|||
|
||||
|
||||
class MenuSerializers(ProjectModelSerializer):
|
||||
plates = PlateSerializer(read_only=True, many=True, source='plate_set')
|
||||
name = serializers.CharField()
|
||||
establishment_id = serializers.PrimaryKeyRelatedField(queryset=models.Establishment.objects.all())
|
||||
establishment_slug = serializers.CharField(read_only=True, source='establishment.slug')
|
||||
price = serializers.IntegerField(read_only=True, source='establishment.price_level', required=False)
|
||||
drinks_included = serializers.BooleanField(source='is_drinks_included', required=FavoritesCreateSerializer)
|
||||
schedules = ScheduleRUDSerializer(many=True, allow_null=True, required=False)
|
||||
uploads = serializers.FileField(allow_null=True, required=False)
|
||||
category_translated = serializers.CharField(read_only=True)
|
||||
|
||||
class Meta:
|
||||
model = models.Menu
|
||||
fields = [
|
||||
'id',
|
||||
'name',
|
||||
'establishment',
|
||||
'establishment_id',
|
||||
'establishment_slug',
|
||||
'price',
|
||||
'drinks_included',
|
||||
'schedules',
|
||||
'uploads',
|
||||
'category',
|
||||
'category_translated',
|
||||
'plates',
|
||||
'establishment'
|
||||
]
|
||||
|
||||
def create(self, validated_data):
|
||||
print(validated_data, '\n\n\n\n\n')
|
||||
establishment = models.Establishment.objects.get(pk=validated_data.pop('establishment'))
|
||||
validated_data['establishment'] = establishment['id']
|
||||
instance = models.Menu.objects.create(**validated_data)
|
||||
return instance
|
||||
|
||||
'''
|
||||
{
|
||||
"name": "Menu test",
|
||||
"establishment_id": 1,
|
||||
"price": 1,
|
||||
"drinks_included": true,
|
||||
"schedules": [],
|
||||
"uploads": null,
|
||||
"category": null
|
||||
}
|
||||
'''
|
||||
|
||||
|
||||
class MenuRUDSerializers(ProjectModelSerializer):
|
||||
plates = PlateSerializer(read_only=True, many=True, source='plate_set')
|
||||
|
|
|
|||
|
|
@ -32,9 +32,9 @@ urlpatterns = [
|
|||
name='establishment-admin-list'),
|
||||
path('menus/dishes/', views.MenuDishesListCreateView.as_view(), name='menu-dishes-list'),
|
||||
path('menus/dishes/<int:pk>/', views.MenuDishesRUDView.as_view(), name='menu-dishes-rud'),
|
||||
path('menus/dishes/<int:pk>/gallery/', views.MenuGalleryListView.as_view(), name='menu-dishes-gallery-list'),
|
||||
path('menus/dishes/<int:pk>/gallery/<int:image_id>/', views.MenuGalleryCreateDestroyView.as_view(),
|
||||
name='menu-dishes-gallery-create-destroy'),
|
||||
# path('menus/dishes/<int:pk>/gallery/', views.MenuGalleryListView.as_view(), name='menu-dishes-gallery-list'),
|
||||
# path('menus/dishes/<int:pk>/gallery/<int:image_id>/', views.MenuGalleryCreateDestroyView.as_view(),
|
||||
# name='menu-dishes-gallery-create-destroy'),
|
||||
path('menus/', views.MenuListCreateView.as_view(), name='menu-list'),
|
||||
path('menus/<int:pk>/', views.MenuRUDView.as_view(), name='menu-rud'),
|
||||
path('plates/', views.PlateListCreateView.as_view(), name='plates'),
|
||||
|
|
|
|||
|
|
@ -125,6 +125,9 @@ class MenuListCreateView(generics.ListCreateAPIView):
|
|||
'establishment__slug',
|
||||
)
|
||||
|
||||
def get_queryset(self):
|
||||
return super().get_queryset().prefetch_related('establishment')
|
||||
|
||||
|
||||
class MenuRUDView(generics.RetrieveUpdateDestroyAPIView):
|
||||
"""Menu RUD view."""
|
||||
|
|
@ -464,54 +467,54 @@ class MenuDishesRUDView(generics.RetrieveUpdateDestroyAPIView):
|
|||
permission_classes = [IsWineryReviewer | IsEstablishmentManager]
|
||||
|
||||
|
||||
class MenuGalleryListView(generics.ListAPIView):
|
||||
"""Resource for returning gallery for menu for back-office users."""
|
||||
serializer_class = serializers.ImageBaseSerializer
|
||||
permission_classes = [IsWineryReviewer | IsEstablishmentManager]
|
||||
queryset = models.Menu.objects.with_schedule_plates_establishment().with_gallery().dishes()
|
||||
|
||||
def get_object(self):
|
||||
"""Override get_object method."""
|
||||
qs = super(MenuGalleryListView, self).get_queryset()
|
||||
menu = get_object_or_404(qs, pk=self.kwargs.get('pk'))
|
||||
|
||||
# May raise a permission denied
|
||||
# self.check_object_permissions(self.request, menu)
|
||||
|
||||
return menu
|
||||
|
||||
def get_queryset(self):
|
||||
"""Override get_queryset method."""
|
||||
return self.get_object().crop_gallery
|
||||
|
||||
|
||||
class MenuGalleryCreateDestroyView(CreateDestroyGalleryViewMixin):
|
||||
"""Resource for a create gallery for menu for back-office users."""
|
||||
serializer_class = serializers.MenuGallerySerializer
|
||||
permission_classes = [IsWineryReviewer | IsEstablishmentManager]
|
||||
|
||||
def get_queryset(self):
|
||||
"""Override get_queryset method."""
|
||||
qs = models.Menu.objects.with_schedule_plates_establishment().with_gallery().dishes()
|
||||
return qs
|
||||
|
||||
def create(self, request, *args, **kwargs):
|
||||
_ = super().create(request, *args, **kwargs)
|
||||
news_qs = self.filter_queryset(self.get_queryset())
|
||||
return response.Response(
|
||||
data=serializers.MenuDishesRUDSerializers(get_object_or_404(news_qs, pk=kwargs.get('pk'))).data
|
||||
)
|
||||
|
||||
def get_object(self):
|
||||
"""
|
||||
Returns the object the view is displaying.
|
||||
"""
|
||||
menu_qs = self.filter_queryset(self.get_queryset())
|
||||
|
||||
menu = get_object_or_404(menu_qs, pk=self.kwargs.get('pk'))
|
||||
gallery = get_object_or_404(menu.menu_gallery, image_id=self.kwargs.get('image_id'))
|
||||
|
||||
# May raise a permission denied
|
||||
self.check_object_permissions(self.request, gallery)
|
||||
|
||||
return gallery
|
||||
# class MenuGalleryListView(generics.ListAPIView):
|
||||
# """Resource for returning gallery for menu for back-office users."""
|
||||
# serializer_class = serializers.ImageBaseSerializer
|
||||
# permission_classes = [IsWineryReviewer | IsEstablishmentManager]
|
||||
# queryset = models.Menu.objects.with_schedule_plates_establishment().with_gallery().dishes()
|
||||
#
|
||||
# def get_object(self):
|
||||
# """Override get_object method."""
|
||||
# qs = super(MenuGalleryListView, self).get_queryset()
|
||||
# menu = get_object_or_404(qs, pk=self.kwargs.get('pk'))
|
||||
#
|
||||
# # May raise a permission denied
|
||||
# # self.check_object_permissions(self.request, menu)
|
||||
#
|
||||
# return menu
|
||||
#
|
||||
# def get_queryset(self):
|
||||
# """Override get_queryset method."""
|
||||
# return self.get_object().crop_gallery
|
||||
#
|
||||
#
|
||||
# class MenuGalleryCreateDestroyView(CreateDestroyGalleryViewMixin):
|
||||
# """Resource for a create gallery for menu for back-office users."""
|
||||
# serializer_class = serializers.MenuGallerySerializer
|
||||
# permission_classes = [IsWineryReviewer | IsEstablishmentManager]
|
||||
#
|
||||
# def get_queryset(self):
|
||||
# """Override get_queryset method."""
|
||||
# qs = models.Menu.objects.with_schedule_plates_establishment().with_gallery().dishes()
|
||||
# return qs
|
||||
#
|
||||
# def create(self, request, *args, **kwargs):
|
||||
# _ = super().create(request, *args, **kwargs)
|
||||
# news_qs = self.filter_queryset(self.get_queryset())
|
||||
# return response.Response(
|
||||
# data=serializers.MenuDishesRUDSerializers(get_object_or_404(news_qs, pk=kwargs.get('pk'))).data
|
||||
# )
|
||||
#
|
||||
# def get_object(self):
|
||||
# """
|
||||
# Returns the object the view is displaying.
|
||||
# """
|
||||
# menu_qs = self.filter_queryset(self.get_queryset())
|
||||
#
|
||||
# menu = get_object_or_404(menu_qs, pk=self.kwargs.get('pk'))
|
||||
# gallery = get_object_or_404(menu.menu_gallery, image_id=self.kwargs.get('image_id'))
|
||||
#
|
||||
# # May raise a permission denied
|
||||
# self.check_object_permissions(self.request, gallery)
|
||||
#
|
||||
# return gallery
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ import string
|
|||
from collections import namedtuple
|
||||
from functools import reduce
|
||||
from io import BytesIO
|
||||
|
||||
import pathlib
|
||||
import requests
|
||||
from django.conf import settings
|
||||
from django.contrib.contenttypes.models import ContentType
|
||||
|
|
@ -69,6 +69,15 @@ def username_random():
|
|||
)
|
||||
|
||||
|
||||
def file_path(instance, filename):
|
||||
"""Determine file path method."""
|
||||
filename = '%s.%s' % (generate_code(), pathlib.Path(filename).suffix.lstrip('.'))
|
||||
return 'files/%s/%s/%s' % (
|
||||
instance._meta.model_name,
|
||||
datetime.now().strftime(settings.REST_DATE_FORMAT),
|
||||
filename)
|
||||
|
||||
|
||||
def image_path(instance, filename):
|
||||
"""Determine avatar path method."""
|
||||
filename = '%s.jpeg' % generate_code()
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ from django.contrib.gis.db import models
|
|||
from django.contrib.postgres.aggregates import ArrayAgg
|
||||
from django.contrib.postgres.fields import JSONField
|
||||
from django.contrib.postgres.fields.jsonb import KeyTextTransform
|
||||
from django.core.validators import FileExtensionValidator
|
||||
from django.utils import timezone
|
||||
from django.utils.html import mark_safe
|
||||
from django.utils.translation import ugettext_lazy as _, get_language
|
||||
|
|
@ -16,7 +17,7 @@ from sorl.thumbnail import get_thumbnail
|
|||
from sorl.thumbnail.fields import ImageField as SORLImageField
|
||||
|
||||
from configuration.models import TranslationSettings
|
||||
from utils.methods import image_path, svg_image_path
|
||||
from utils.methods import image_path, svg_image_path, file_path
|
||||
from utils.validators import svg_image_validator
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
|
@ -86,6 +87,7 @@ def translate_field(self, field_name, toggle_field_name=None):
|
|||
return None
|
||||
return value
|
||||
return None
|
||||
|
||||
return translate
|
||||
|
||||
|
||||
|
|
@ -159,6 +161,33 @@ class BaseAttributes(ProjectBaseMixin):
|
|||
abstract = True
|
||||
|
||||
|
||||
class FileMixin(models.Model):
|
||||
"""File model."""
|
||||
|
||||
file = models.FileField(upload_to=file_path,
|
||||
blank=True, null=True, default=None,
|
||||
verbose_name=_('File'),
|
||||
validators=[FileExtensionValidator(
|
||||
allowed_extensions=('jpg', 'jpeg', 'png', 'doc', 'docx', 'pdf')
|
||||
)])
|
||||
|
||||
class Meta:
|
||||
"""Meta class."""
|
||||
|
||||
abstract = True
|
||||
|
||||
def get_file_url(self):
|
||||
"""Get file url."""
|
||||
return self.file.url if self.file else None
|
||||
|
||||
def get_full_file_url(self, request):
|
||||
"""Get full file url"""
|
||||
if self.file and exists(self.file.path):
|
||||
return request.build_absolute_uri(self.file.url)
|
||||
else:
|
||||
return None
|
||||
|
||||
|
||||
class ImageMixin(models.Model):
|
||||
"""Avatar model."""
|
||||
|
||||
|
|
@ -230,7 +259,7 @@ class SORLImageMixin(models.Model):
|
|||
else:
|
||||
return None
|
||||
|
||||
def get_cropped_image(self, geometry: str, quality: int, cropbox:str) -> dict:
|
||||
def get_cropped_image(self, geometry: str, quality: int, cropbox: str) -> dict:
|
||||
cropped_image = get_thumbnail(self.image,
|
||||
geometry_string=geometry,
|
||||
# crop=crop,
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user