Update food api, fix query proplems
This commit is contained in:
parent
9b5d294703
commit
f4dd21440f
@ -2,7 +2,7 @@
|
|||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
from django.contrib import admin
|
from django.contrib import admin
|
||||||
from apps.food.models import SingleFood, Menu, HappyHour, UserFoodRating, UserFoodImage, FoodImage
|
from apps.food.models import SingleFood, Menu, HappyHour, UserFoodRating, UserFoodImage, FoodImage, UserFoodComment
|
||||||
|
|
||||||
|
|
||||||
class SingleFoodInline(admin.TabularInline):
|
class SingleFoodInline(admin.TabularInline):
|
||||||
@ -24,5 +24,6 @@ admin.site.register(SingleFood)
|
|||||||
admin.site.register(HappyHour)
|
admin.site.register(HappyHour)
|
||||||
admin.site.register(UserFoodRating)
|
admin.site.register(UserFoodRating)
|
||||||
admin.site.register(UserFoodImage)
|
admin.site.register(UserFoodImage)
|
||||||
|
admin.site.register(UserFoodComment)
|
||||||
admin.site.register(Menu, MenuAdmin)
|
admin.site.register(Menu, MenuAdmin)
|
||||||
admin.site.register(FoodImage)
|
admin.site.register(FoodImage)
|
||||||
|
|||||||
0
ofu_app/apps/food/api/v1_2/serializers/__init__.py
Normal file
0
ofu_app/apps/food/api/v1_2/serializers/__init__.py
Normal file
@ -1,11 +1,6 @@
|
|||||||
|
from apps.food.models import Menu, SingleFood, HappyHour, Allergene, FoodImage, HappyHourLocation, UserFoodComment
|
||||||
from rest_framework import serializers
|
from rest_framework import serializers
|
||||||
|
|
||||||
from apps.food.models import Menu, SingleFood, HappyHour, Allergene, FoodImage, HappyHourLocation
|
|
||||||
from apps.food.models import UserFoodRating, UserFoodImage
|
|
||||||
from django.contrib.auth.models import User
|
|
||||||
from rest_framework import serializers
|
|
||||||
from rest_framework import validators
|
|
||||||
|
|
||||||
|
|
||||||
class DefaultFoodImageSerializer(serializers.Serializer):
|
class DefaultFoodImageSerializer(serializers.Serializer):
|
||||||
"""Your data serializer, define your fields here."""
|
"""Your data serializer, define your fields here."""
|
||||||
@ -33,6 +28,12 @@ class MenusLocationsSerializer(serializers.Serializer):
|
|||||||
name = serializers.CharField()
|
name = serializers.CharField()
|
||||||
|
|
||||||
|
|
||||||
|
class UserFoodCommentSerializer(serializers.HyperlinkedModelSerializer):
|
||||||
|
class Meta:
|
||||||
|
model = UserFoodComment
|
||||||
|
fields = ('id', 'description', 'title')
|
||||||
|
|
||||||
|
|
||||||
class AllergensSerializer(serializers.HyperlinkedModelSerializer):
|
class AllergensSerializer(serializers.HyperlinkedModelSerializer):
|
||||||
class Meta:
|
class Meta:
|
||||||
model = Allergene
|
model = Allergene
|
||||||
@ -68,10 +69,12 @@ class MinimalSingleFoodSerializer(serializers.HyperlinkedModelSerializer):
|
|||||||
class DetailedSingleFoosdSerializer(serializers.HyperlinkedModelSerializer):
|
class DetailedSingleFoosdSerializer(serializers.HyperlinkedModelSerializer):
|
||||||
allergens = AllergensSerializer(many=True, read_only=True)
|
allergens = AllergensSerializer(many=True, read_only=True)
|
||||||
image = DetailedFoodImageSerializer(many=False, read_only=True)
|
image = DetailedFoodImageSerializer(many=False, read_only=True)
|
||||||
|
comments = UserFoodCommentSerializer(many=True, read_only=True)
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = SingleFood
|
model = SingleFood
|
||||||
fields = ('id', 'name', 'rating', 'price_student', 'price_employee', 'price_guest', 'allergens', 'image')
|
fields = (
|
||||||
|
'id', 'name', 'rating', 'price_student', 'price_employee', 'price_guest', 'allergens', 'image', 'comments')
|
||||||
|
|
||||||
|
|
||||||
class OverviewMenuSerializer(serializers.HyperlinkedModelSerializer):
|
class OverviewMenuSerializer(serializers.HyperlinkedModelSerializer):
|
||||||
@ -109,47 +112,3 @@ class HappyHourLocationSerializer(serializers.HyperlinkedModelSerializer):
|
|||||||
class Meta:
|
class Meta:
|
||||||
model = HappyHourLocation
|
model = HappyHourLocation
|
||||||
fields = ('id', 'name')
|
fields = ('id', 'name')
|
||||||
|
|
||||||
|
|
||||||
# --------------------------- User --------------------------------------------
|
|
||||||
class UserFoodImageSerializer(serializers.HyperlinkedModelSerializer):
|
|
||||||
class Meta:
|
|
||||||
model = UserFoodImage
|
|
||||||
fields = ('id', 'image_image', 'image_thumb')
|
|
||||||
|
|
||||||
|
|
||||||
class UserFoodRatingSerializer(serializers.ModelSerializer):
|
|
||||||
# food = MinimalSingleFoodSerializer(many=False, read_only=False)
|
|
||||||
|
|
||||||
class Meta:
|
|
||||||
model = UserFoodRating
|
|
||||||
fields = ('id', 'rating')
|
|
||||||
|
|
||||||
def run_validators(self, value):
|
|
||||||
for validator in self.validators:
|
|
||||||
if isinstance(validator, validators.UniqueTogetherValidator):
|
|
||||||
self.validators.remove(validator)
|
|
||||||
super(UserFoodRatingSerializer, self).run_validators(value)
|
|
||||||
|
|
||||||
def create(self, validated_data):
|
|
||||||
# TODO: Custom exception handler
|
|
||||||
rating = validated_data.pop('rating')
|
|
||||||
if rating >= 1 or rating <= 5:
|
|
||||||
food_id = self.context.get('food_id')
|
|
||||||
# user = self.context['request'].user
|
|
||||||
user = User.objects.get(id=1)
|
|
||||||
food = SingleFood.objects.get(id=food_id)
|
|
||||||
user_rating, _ = UserFoodRating.objects.get_or_create(food=food, user=user)
|
|
||||||
user_rating.rating = rating
|
|
||||||
user_rating.save()
|
|
||||||
|
|
||||||
food_user_ratings = UserFoodRating.objects.all().filter(food=food)
|
|
||||||
sum = 0
|
|
||||||
for food_user_rating in food_user_ratings:
|
|
||||||
sum += food_user_rating.rating
|
|
||||||
|
|
||||||
food.rating = sum / food_user_ratings.count()
|
|
||||||
food.save()
|
|
||||||
return user_rating
|
|
||||||
else:
|
|
||||||
raise ValueError
|
|
||||||
100
ofu_app/apps/food/api/v1_2/serializers/user_serializers.py
Normal file
100
ofu_app/apps/food/api/v1_2/serializers/user_serializers.py
Normal file
@ -0,0 +1,100 @@
|
|||||||
|
from apps.food.models import Menu, SingleFood
|
||||||
|
from apps.food.models import UserFoodRating, UserFoodImage, UserFoodComment, FoodImage
|
||||||
|
from django.contrib.auth.models import User
|
||||||
|
from rest_framework import validators
|
||||||
|
from rest_framework import serializers
|
||||||
|
from django.db.utils import IntegrityError
|
||||||
|
|
||||||
|
|
||||||
|
class UserFoodImageSerializer(serializers.HyperlinkedModelSerializer):
|
||||||
|
class Meta:
|
||||||
|
model = UserFoodImage
|
||||||
|
fields = ('id', 'image_image', 'image_thumb')
|
||||||
|
|
||||||
|
|
||||||
|
class UserFoodCommentSerializer(serializers.ModelSerializer):
|
||||||
|
class Meta:
|
||||||
|
model = UserFoodComment
|
||||||
|
fields = ('id', 'title', 'description')
|
||||||
|
|
||||||
|
def run_validators(self, value):
|
||||||
|
for validator in self.validators:
|
||||||
|
if isinstance(validator, validators.UniqueTogetherValidator):
|
||||||
|
self.validators.remove(validator)
|
||||||
|
super(UserFoodCommentSerializer, self).run_validators(value)
|
||||||
|
|
||||||
|
def create(self, validated_data):
|
||||||
|
comment_title = validated_data.pop('title')
|
||||||
|
comment_description = validated_data.pop('description')
|
||||||
|
food_id = self.context.get('food_id')
|
||||||
|
user = self.context['request'].user
|
||||||
|
food = SingleFood.objects.get(id=food_id)
|
||||||
|
|
||||||
|
user_comment, _ = UserFoodComment.objects.get_or_create(food=food, user=user)
|
||||||
|
user_comment.title = comment_title
|
||||||
|
user_comment.description = comment_description
|
||||||
|
user_comment.save()
|
||||||
|
return user_comment
|
||||||
|
|
||||||
|
|
||||||
|
class UserFoodRatingSerializer(serializers.ModelSerializer):
|
||||||
|
class Meta:
|
||||||
|
model = UserFoodRating
|
||||||
|
fields = ('id', 'rating')
|
||||||
|
|
||||||
|
def run_validators(self, value):
|
||||||
|
for validator in self.validators:
|
||||||
|
if isinstance(validator, validators.UniqueTogetherValidator):
|
||||||
|
self.validators.remove(validator)
|
||||||
|
super(UserFoodRatingSerializer, self).run_validators(value)
|
||||||
|
|
||||||
|
def create(self, validated_data):
|
||||||
|
# TODO: Custom exception handler
|
||||||
|
rating = validated_data.pop('rating')
|
||||||
|
if rating >= 1 or rating <= 5:
|
||||||
|
food_id = self.context.get('food_id')
|
||||||
|
user = self.context['request'].user
|
||||||
|
food = SingleFood.objects.get(id=food_id)
|
||||||
|
user_rating, _ = UserFoodRating.objects.get_or_create(food=food, user=user)
|
||||||
|
user_rating.rating = rating
|
||||||
|
user_rating.save()
|
||||||
|
|
||||||
|
food_user_ratings = UserFoodRating.objects.all().filter(food=food)
|
||||||
|
sum = 0
|
||||||
|
for food_user_rating in food_user_ratings:
|
||||||
|
sum += food_user_rating.rating
|
||||||
|
|
||||||
|
food.rating = sum / food_user_ratings.count()
|
||||||
|
food.save()
|
||||||
|
return user_rating
|
||||||
|
else:
|
||||||
|
raise ValueError
|
||||||
|
|
||||||
|
|
||||||
|
class UserFoodImageSerializer(serializers.ModelSerializer):
|
||||||
|
class Meta:
|
||||||
|
model = FoodImage
|
||||||
|
fields = ('id', 'image')
|
||||||
|
|
||||||
|
def run_validators(self, value):
|
||||||
|
for validator in self.validators:
|
||||||
|
if isinstance(validator, validators.UniqueTogetherValidator):
|
||||||
|
self.validators.remove(validator)
|
||||||
|
super(UserFoodImageSerializer, self).run_validators(value)
|
||||||
|
|
||||||
|
def create(self, validated_data):
|
||||||
|
# TODO: Custom exception handler
|
||||||
|
food_id = self.context.get('food_id')
|
||||||
|
food = SingleFood.objects.get(id=food_id)
|
||||||
|
user = self.context['request'].user
|
||||||
|
image = validated_data.pop('image')
|
||||||
|
food_image = FoodImage.objects.create(image=image)
|
||||||
|
food_image.save()
|
||||||
|
try:
|
||||||
|
user_food_image = UserFoodImage.objects.create(user=user, food=food, image=food_image)
|
||||||
|
user_food_image.save()
|
||||||
|
except IntegrityError as err:
|
||||||
|
user_food_image = UserFoodImage.objects.get(user=user, food=food)
|
||||||
|
user_food_image.image = food_image
|
||||||
|
user_food_image.save()
|
||||||
|
return food_image
|
||||||
@ -14,7 +14,8 @@ Including another URLconf
|
|||||||
2. Add a URL to urlpatterns: url(r'^blog/', include('blog.urls'))
|
2. Add a URL to urlpatterns: url(r'^blog/', include('blog.urls'))
|
||||||
"""
|
"""
|
||||||
from django.urls import path
|
from django.urls import path
|
||||||
from apps.food.api.v1_2 import views as api_views
|
from apps.food.api.v1_2.views import main_views as api_views
|
||||||
|
from apps.food.api.v1_2.views import user_views as user_api_views
|
||||||
|
|
||||||
urlpatterns = [
|
urlpatterns = [
|
||||||
# API Version 1.2
|
# API Version 1.2
|
||||||
@ -24,12 +25,17 @@ urlpatterns = [
|
|||||||
|
|
||||||
path('food/meals/', api_views.ApiMeals.as_view(), name='meals'),
|
path('food/meals/', api_views.ApiMeals.as_view(), name='meals'),
|
||||||
path('food/meals/<int:pk>', api_views.ApiMeal.as_view(), name='meal'),
|
path('food/meals/<int:pk>', api_views.ApiMeal.as_view(), name='meal'),
|
||||||
path('food/allergens/', api_views.ApiAllergens.as_view(), name='allergens'),
|
path('food/meals/<int:pk>/comments', api_views.ApiMealComments.as_view(), name='meal-comments'),
|
||||||
|
|
||||||
|
path('food/meals/<int:pk>/comment', user_api_views.ApiUserFoodCommentUpload.as_view(), name='meals-comment-upload'),
|
||||||
|
path('food/meals/<int:pk>/rating', user_api_views.ApiFoodRatingUpload.as_view(), name='meals-rating-upload'),
|
||||||
|
path('food/meals/<int:pk>/image', user_api_views.ApiFoodImageUpload.as_view(), name='meals-image-upload'),
|
||||||
|
path('food/meals/image', user_api_views.ApiFoodImageUpload.as_view(), name='meals-image-upload'),
|
||||||
|
|
||||||
path('food/meals/images/', api_views.ApiFoodImages.as_view(), name='images'),
|
path('food/meals/images/', api_views.ApiFoodImages.as_view(), name='images'),
|
||||||
path('food/meals/images/default', api_views.ApiFoodImagesDefault.as_view(), name='images-default'),
|
path('food/meals/images/default', api_views.ApiFoodImagesDefault.as_view(), name='images-default'),
|
||||||
path('food/meals/<int:pk>/rating', api_views.ApiFoodRatingUpload.as_view(), name='meals-rating-upload'),
|
|
||||||
# path('food/meals/<int:pk>/image', api_views.ApiFoodImagesDefault.as_view(), name='meals-image-upload'),
|
path('food/allergens/', api_views.ApiAllergens.as_view(), name='allergens'),
|
||||||
# path('food/meals/<int:pk>/comment', api_views.ApiFoodImagesDefault.as_view(), name='meals-comment-upload'),
|
|
||||||
|
|
||||||
path('food/happy-hours/', api_views.ApiHappyHours.as_view(), name='happy-hours'),
|
path('food/happy-hours/', api_views.ApiHappyHours.as_view(), name='happy-hours'),
|
||||||
path('food/happy-hours/<int:pk>', api_views.ApiHappyHours.as_view(), name='happy-hours'),
|
path('food/happy-hours/<int:pk>', api_views.ApiHappyHours.as_view(), name='happy-hours'),
|
||||||
|
|||||||
0
ofu_app/apps/food/api/v1_2/views/__init__.py
Normal file
0
ofu_app/apps/food/api/v1_2/views/__init__.py
Normal file
@ -6,18 +6,19 @@ from django.templatetags.static import static
|
|||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
from datetime import timedelta
|
from datetime import timedelta
|
||||||
|
|
||||||
from apps.food.api.v1_2.serializers import OverviewMenuSerializer, DetailMenuSerializer, MenusLocationsSerializer
|
from apps.food.api.v1_2.serializers.main_serializers import OverviewMenuSerializer, DetailMenuSerializer, \
|
||||||
from apps.food.api.v1_2.serializers import OverviewSingleFoodSerializer, DetailedSingleFoosdSerializer, \
|
MenusLocationsSerializer
|
||||||
AllergensSerializer, DetailedFoodImageSerializer, DefaultFoodImageSerializer, MinimalSingleFoodSerializer
|
from apps.food.api.v1_2.serializers.main_serializers import OverviewSingleFoodSerializer, DetailedSingleFoosdSerializer, \
|
||||||
from apps.food.api.v1_2.serializers import HappyHourSerializer, HappyHourLocationSerializer
|
AllergensSerializer, DetailedFoodImageSerializer, DefaultFoodImageSerializer, MinimalSingleFoodSerializer, \
|
||||||
from apps.food.api.v1_2.serializers import UserFoodRatingSerializer
|
UserFoodCommentSerializer
|
||||||
from apps.food.models import Menu, SingleFood, Allergene, HappyHour, HappyHourLocation, FoodImage, UserFoodRating
|
from apps.food.api.v1_2.serializers.main_serializers import HappyHourSerializer, HappyHourLocationSerializer
|
||||||
|
from apps.food.models import Menu, SingleFood, Allergene, HappyHour, HappyHourLocation, FoodImage, UserFoodRating, \
|
||||||
|
UserFoodComment
|
||||||
from rest_framework import generics
|
from rest_framework import generics
|
||||||
from rest_framework.decorators import permission_classes, api_view, authentication_classes
|
from rest_framework.decorators import permission_classes, api_view, authentication_classes
|
||||||
from rest_framework.permissions import IsAuthenticated, AllowAny
|
from rest_framework.permissions import IsAuthenticated, AllowAny
|
||||||
from rest_framework import views, status
|
from rest_framework import views, status
|
||||||
from rest_framework.response import Response
|
from rest_framework.response import Response
|
||||||
from rest_framework.authentication import TokenAuthentication
|
|
||||||
from rest_framework.exceptions import ValidationError
|
from rest_framework.exceptions import ValidationError
|
||||||
|
|
||||||
|
|
||||||
@ -128,6 +129,15 @@ class ApiMenusLocations(views.APIView):
|
|||||||
return Response(results, status=status.HTTP_200_OK)
|
return Response(results, status=status.HTTP_200_OK)
|
||||||
|
|
||||||
|
|
||||||
|
@permission_classes((AllowAny,))
|
||||||
|
class ApiMealComments(generics.ListAPIView):
|
||||||
|
serializer_class = UserFoodCommentSerializer
|
||||||
|
|
||||||
|
def get_queryset(self):
|
||||||
|
food_id = self.kwargs['pk']
|
||||||
|
return UserFoodComment.objects.filter(food_id=food_id)
|
||||||
|
|
||||||
|
|
||||||
@permission_classes((AllowAny,))
|
@permission_classes((AllowAny,))
|
||||||
class ApiHappyHours(generics.ListAPIView):
|
class ApiHappyHours(generics.ListAPIView):
|
||||||
serializer_class = HappyHourSerializer
|
serializer_class = HappyHourSerializer
|
||||||
@ -209,18 +219,3 @@ class ApiFoodImagesDefault(views.APIView):
|
|||||||
default_image = {'image': request.build_absolute_uri(static('img/food/default.jpg'))}
|
default_image = {'image': request.build_absolute_uri(static('img/food/default.jpg'))}
|
||||||
results = DefaultFoodImageSerializer(default_image, many=False).data
|
results = DefaultFoodImageSerializer(default_image, many=False).data
|
||||||
return Response(results, status=status.HTTP_200_OK)
|
return Response(results, status=status.HTTP_200_OK)
|
||||||
|
|
||||||
|
|
||||||
@authentication_classes((TokenAuthentication,))
|
|
||||||
@permission_classes((IsAuthenticated,))
|
|
||||||
class ApiFoodRatingUpload(generics.CreateAPIView):
|
|
||||||
serializer_class = UserFoodRatingSerializer
|
|
||||||
queryset = UserFoodRating.objects.all()
|
|
||||||
|
|
||||||
def get_serializer_context(self):
|
|
||||||
context = super(ApiFoodRatingUpload, self).get_serializer_context()
|
|
||||||
context.update({
|
|
||||||
"food_id": self.kwargs['pk'],
|
|
||||||
# extra data
|
|
||||||
})
|
|
||||||
return context
|
|
||||||
59
ofu_app/apps/food/api/v1_2/views/user_views.py
Normal file
59
ofu_app/apps/food/api/v1_2/views/user_views.py
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
from rest_framework import generics
|
||||||
|
from rest_framework.decorators import permission_classes, api_view, authentication_classes
|
||||||
|
from rest_framework.permissions import IsAuthenticated, AllowAny
|
||||||
|
from rest_framework.authentication import TokenAuthentication, SessionAuthentication
|
||||||
|
from rest_framework.parsers import FormParser, MultiPartParser
|
||||||
|
|
||||||
|
from apps.food.models import UserFoodRating, UserFoodImage, UserFoodComment, FoodImage
|
||||||
|
from apps.food.api.v1_2.serializers.user_serializers import UserFoodRatingSerializer, UserFoodImageSerializer, \
|
||||||
|
UserFoodCommentSerializer
|
||||||
|
|
||||||
|
|
||||||
|
@authentication_classes((TokenAuthentication, SessionAuthentication))
|
||||||
|
@permission_classes((IsAuthenticated,))
|
||||||
|
class ApiFoodRatingUpload(generics.CreateAPIView):
|
||||||
|
serializer_class = UserFoodRatingSerializer
|
||||||
|
queryset = UserFoodRating.objects.all()
|
||||||
|
|
||||||
|
def get_serializer_context(self):
|
||||||
|
context = super(ApiFoodRatingUpload, self).get_serializer_context()
|
||||||
|
context.update({
|
||||||
|
"food_id": self.kwargs['pk'],
|
||||||
|
})
|
||||||
|
return context
|
||||||
|
|
||||||
|
|
||||||
|
@authentication_classes((TokenAuthentication, SessionAuthentication))
|
||||||
|
@permission_classes((IsAuthenticated,))
|
||||||
|
class ApiUserFoodCommentUpload(generics.CreateAPIView):
|
||||||
|
serializer_class = UserFoodCommentSerializer
|
||||||
|
queryset = UserFoodComment.objects.all()
|
||||||
|
|
||||||
|
def get_serializer_context(self):
|
||||||
|
context = super(ApiUserFoodCommentUpload, self).get_serializer_context()
|
||||||
|
context.update({
|
||||||
|
"food_id": self.kwargs['pk'],
|
||||||
|
})
|
||||||
|
return context
|
||||||
|
|
||||||
|
|
||||||
|
@authentication_classes((TokenAuthentication, SessionAuthentication))
|
||||||
|
@permission_classes((IsAuthenticated,))
|
||||||
|
class ApiFoodImageUpload(generics.CreateAPIView):
|
||||||
|
serializer_class = UserFoodImageSerializer
|
||||||
|
queryset = FoodImage.objects.all()
|
||||||
|
|
||||||
|
def get_serializer_context(self):
|
||||||
|
context = super(ApiFoodImageUpload, self).get_serializer_context()
|
||||||
|
context.update({
|
||||||
|
"food_id": self.kwargs['pk'],
|
||||||
|
})
|
||||||
|
return context
|
||||||
|
#
|
||||||
|
# @authentication_classes((TokenAuthentication,))
|
||||||
|
# @permission_classes((IsAuthenticated,))
|
||||||
|
# class ApiFoodImageUpload(generics.CreateAPIView):
|
||||||
|
# serializer_class = UserFoodImageSerializer
|
||||||
|
# queryset = UserFoodImage.objects.all()
|
||||||
|
#
|
||||||
|
#
|
||||||
24
ofu_app/apps/food/migrations/0013_auto_20180330_1045.py
Normal file
24
ofu_app/apps/food/migrations/0013_auto_20180330_1045.py
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
# Generated by Django 2.0.1 on 2018-03-30 10:45
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('food', '0012_auto_20180326_2343'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.RenameField(
|
||||||
|
model_name='userfoodcomment',
|
||||||
|
old_name='comment',
|
||||||
|
new_name='description',
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='userfoodcomment',
|
||||||
|
name='title',
|
||||||
|
field=models.CharField(default='Test', max_length=128),
|
||||||
|
preserve_default=False,
|
||||||
|
),
|
||||||
|
]
|
||||||
18
ofu_app/apps/food/migrations/0014_singlefood_comments.py
Normal file
18
ofu_app/apps/food/migrations/0014_singlefood_comments.py
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
# Generated by Django 2.0.1 on 2018-03-30 11:33
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('food', '0013_auto_20180330_1045'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='singlefood',
|
||||||
|
name='comments',
|
||||||
|
field=models.ManyToManyField(blank=True, to='food.UserFoodComment'),
|
||||||
|
),
|
||||||
|
]
|
||||||
23
ofu_app/apps/food/migrations/0015_auto_20180331_1427.py
Normal file
23
ofu_app/apps/food/migrations/0015_auto_20180331_1427.py
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
# Generated by Django 2.0.1 on 2018-03-31 14:27
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('food', '0014_singlefood_comments'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.RemoveField(
|
||||||
|
model_name='foodimage',
|
||||||
|
name='thumb',
|
||||||
|
),
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='foodimage',
|
||||||
|
name='image',
|
||||||
|
field=models.ImageField(default='NULL', upload_to='food/originals/%Y/%m/%W'),
|
||||||
|
preserve_default=False,
|
||||||
|
),
|
||||||
|
]
|
||||||
25
ofu_app/apps/food/migrations/0016_auto_20180331_1446.py
Normal file
25
ofu_app/apps/food/migrations/0016_auto_20180331_1446.py
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
# Generated by Django 2.0.1 on 2018-03-31 14:46
|
||||||
|
|
||||||
|
import apps.food.models
|
||||||
|
from django.db import migrations, models
|
||||||
|
import django.db.models.deletion
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('food', '0015_auto_20180331_1427'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='foodimage',
|
||||||
|
name='image',
|
||||||
|
field=models.ImageField(upload_to=apps.food.models.image_path),
|
||||||
|
),
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='singlefood',
|
||||||
|
name='image',
|
||||||
|
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='food.FoodImage'),
|
||||||
|
),
|
||||||
|
]
|
||||||
18
ofu_app/apps/food/migrations/0017_foodimage_thumb.py
Normal file
18
ofu_app/apps/food/migrations/0017_foodimage_thumb.py
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
# Generated by Django 2.0.1 on 2018-03-31 15:05
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('food', '0016_auto_20180331_1446'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='foodimage',
|
||||||
|
name='thumb',
|
||||||
|
field=models.ImageField(blank=True, null=True, upload_to='food/thumbs/%Y/%m/%W'),
|
||||||
|
),
|
||||||
|
]
|
||||||
17
ofu_app/apps/food/migrations/0018_remove_foodimage_thumb.py
Normal file
17
ofu_app/apps/food/migrations/0018_remove_foodimage_thumb.py
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
# Generated by Django 2.0.1 on 2018-03-31 15:53
|
||||||
|
|
||||||
|
from django.db import migrations
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('food', '0017_foodimage_thumb'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.RemoveField(
|
||||||
|
model_name='foodimage',
|
||||||
|
name='thumb',
|
||||||
|
),
|
||||||
|
]
|
||||||
19
ofu_app/apps/food/migrations/0019_foodimage_thumb.py
Normal file
19
ofu_app/apps/food/migrations/0019_foodimage_thumb.py
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
# Generated by Django 2.0.1 on 2018-03-31 16:09
|
||||||
|
|
||||||
|
import apps.food.models
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('food', '0018_remove_foodimage_thumb'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='foodimage',
|
||||||
|
name='thumb',
|
||||||
|
field=models.ImageField(blank=True, null=True, upload_to=apps.food.models.thumb_path),
|
||||||
|
),
|
||||||
|
]
|
||||||
@ -3,6 +3,8 @@ from __future__ import unicode_literals
|
|||||||
|
|
||||||
import os
|
import os
|
||||||
from io import BytesIO
|
from io import BytesIO
|
||||||
|
import uuid
|
||||||
|
from _datetime import datetime
|
||||||
|
|
||||||
from PIL import Image
|
from PIL import Image
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
@ -19,9 +21,22 @@ MAX_FOOD_PRICE_LENGTH = 10
|
|||||||
MAX_FOOD_ALLERGENNAME_LENGTH = 256
|
MAX_FOOD_ALLERGENNAME_LENGTH = 256
|
||||||
MAX_HAPPY_HOUR_LOCATION_LENGTH = 256
|
MAX_HAPPY_HOUR_LOCATION_LENGTH = 256
|
||||||
MAX_HAPPY_HOUR_DESCRIPTION_LENGTH = 1024
|
MAX_HAPPY_HOUR_DESCRIPTION_LENGTH = 1024
|
||||||
|
MAX_FOOD_COMMENT_TITLE_LENGTH = 128
|
||||||
MAX_FOOD_COMMENT_LENGTH = 2048
|
MAX_FOOD_COMMENT_LENGTH = 2048
|
||||||
|
|
||||||
|
|
||||||
|
def image_path(instance, filename):
|
||||||
|
extension = filename.split('.')[-1]
|
||||||
|
date = datetime.now().strftime('%Y/%m/%W')
|
||||||
|
return 'food/originals/{}/{}.{}'.format(date, uuid.uuid4(), extension)
|
||||||
|
|
||||||
|
|
||||||
|
def thumb_path(instance, filename):
|
||||||
|
extension = filename.split('.')[-1]
|
||||||
|
date = datetime.now().strftime('%Y/%m/%W')
|
||||||
|
return 'food/thumbs/{}/{}.{}'.format(date, uuid.uuid4(), 'jpg')
|
||||||
|
|
||||||
|
|
||||||
# Create your models here.
|
# Create your models here.
|
||||||
class Menu(models.Model):
|
class Menu(models.Model):
|
||||||
ERBA = 'ERBA'
|
ERBA = 'ERBA'
|
||||||
@ -56,9 +71,10 @@ class SingleFood(models.Model):
|
|||||||
price_student = models.CharField(max_length=MAX_FOOD_PRICE_LENGTH, blank=True, null=True)
|
price_student = models.CharField(max_length=MAX_FOOD_PRICE_LENGTH, blank=True, null=True)
|
||||||
price_employee = models.CharField(max_length=MAX_FOOD_PRICE_LENGTH, blank=True, null=True)
|
price_employee = models.CharField(max_length=MAX_FOOD_PRICE_LENGTH, blank=True, null=True)
|
||||||
price_guest = models.CharField(max_length=MAX_FOOD_PRICE_LENGTH, blank=True, null=True)
|
price_guest = models.CharField(max_length=MAX_FOOD_PRICE_LENGTH, blank=True, null=True)
|
||||||
image = models.ForeignKey('FoodImage', on_delete=models.PROTECT, blank=True, null=True)
|
image = models.ForeignKey('FoodImage', on_delete=models.SET_NULL, blank=True, null=True)
|
||||||
rating = models.FloatField(default=0)
|
rating = models.FloatField(default=0)
|
||||||
allergens = models.ManyToManyField("Allergene", blank=True)
|
allergens = models.ManyToManyField("Allergene", blank=True)
|
||||||
|
comments = models.ManyToManyField('UserFoodComment', blank=True)
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return "%s - Rating: %f - Student Price: %s" % (self.name, self.rating, self.price_student)
|
return "%s - Rating: %f - Student Price: %s" % (self.name, self.rating, self.price_student)
|
||||||
@ -125,25 +141,27 @@ class UserFoodComment(models.Model):
|
|||||||
id = models.AutoField(primary_key=True)
|
id = models.AutoField(primary_key=True)
|
||||||
user = models.ForeignKey(User, on_delete=models.PROTECT, unique=False)
|
user = models.ForeignKey(User, on_delete=models.PROTECT, unique=False)
|
||||||
food = models.ForeignKey(SingleFood, on_delete=models.PROTECT)
|
food = models.ForeignKey(SingleFood, on_delete=models.PROTECT)
|
||||||
comment = models.CharField(max_length=MAX_FOOD_COMMENT_LENGTH)
|
title = models.CharField(max_length=MAX_FOOD_COMMENT_TITLE_LENGTH, null=False, blank=False)
|
||||||
|
description = models.CharField(max_length=MAX_FOOD_COMMENT_LENGTH, null=False, blank=False)
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
unique_together = ('user', 'food')
|
unique_together = ('user', 'food')
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return "User: %s - Food: %s" % (self.user.username, self.food.name)
|
return "User: %s - Title: %s" % (self.user.username, self.title)
|
||||||
|
|
||||||
|
|
||||||
class FoodImage(models.Model):
|
class FoodImage(models.Model):
|
||||||
id = models.AutoField(primary_key=True)
|
id = models.AutoField(primary_key=True)
|
||||||
image = models.ImageField(upload_to='food/originals/%Y/%m/%W', blank=True, null=True)
|
image = models.ImageField(upload_to=image_path, blank=False, null=False)
|
||||||
thumb = models.ImageField(upload_to='food/thumbs/%Y/%m/%W', blank=True, null=True)
|
thumb = models.ImageField(upload_to=thumb_path, blank=True, null=True)
|
||||||
|
|
||||||
def save(self, force_update=False, force_insert=False, thumb_size=(640, 480)):
|
def save(self, *args, **kwargs):
|
||||||
image = Image.open(self.image)
|
image = Image.open(self.image)
|
||||||
|
|
||||||
if image.mode not in ('L', 'RGB'):
|
if image.mode not in ('L', 'RGB'):
|
||||||
image = image.convert('RGB')
|
image = image.convert('RGB')
|
||||||
|
thumb_size = (128, 128)
|
||||||
image.thumbnail(thumb_size, Image.ANTIALIAS)
|
image.thumbnail(thumb_size, Image.ANTIALIAS)
|
||||||
|
|
||||||
# save the thumbnail to memory
|
# save the thumbnail to memory
|
||||||
@ -156,12 +174,17 @@ class FoodImage(models.Model):
|
|||||||
temp_handle.read(),
|
temp_handle.read(),
|
||||||
content_type='image/jpg')
|
content_type='image/jpg')
|
||||||
|
|
||||||
self.thumb.save('%s_thumbnail.%s' % (self.id, 'jpg'), suf, save=False)
|
# self.thumb.save('%s_thumbnail.%s' % (self.id, 'jpg'), suf, save=False)
|
||||||
# save the image object
|
self.thumb.save(name='', content=suf, save=False)
|
||||||
self.image.name = "%s_original.%s" % (self.id, 'jpg')
|
|
||||||
super(FoodImage, self).save(force_update, force_insert)
|
|
||||||
|
|
||||||
def delete(self, using=None, keep_parents=False):
|
# save the image object
|
||||||
os.remove(os.path.join(settings.MEDIA_ROOT, self.image.name))
|
super(FoodImage, self).save(*args, **kwargs)
|
||||||
os.remove(os.path.join(settings.MEDIA_ROOT, self.thumb.name))
|
|
||||||
super(FoodImage, self).delete()
|
#
|
||||||
|
# def delete(self, using=None, keep_parents=False):
|
||||||
|
# os.remove(os.path.join(settings.MEDIA_ROOT, self.image.name))
|
||||||
|
# os.remove(os.path.join(settings.MEDIA_ROOT, self.thumb.name))
|
||||||
|
# super(FoodImage, self).delete()
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return "Image: %s" % (str(self.image))
|
||||||
|
|||||||
Reference in New Issue
Block a user