Start api v1.2

This commit is contained in:
michigg 2018-03-28 15:18:54 +02:00
parent e2e2e0b0bf
commit 4fd22aed1d
7 changed files with 326 additions and 181 deletions

View File

View File

@ -14,7 +14,7 @@ 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.conf.urls import url from django.conf.urls import url
from apps.food.api import views as api_views from apps.food.api.v1_1 import views as api_views
from apps.food.models import Menu from apps.food.models import Menu
urlpatterns = [ urlpatterns = [

View File

@ -4,11 +4,11 @@ from __future__ import unicode_literals
from datetime import datetime from datetime import datetime
from datetime import timedelta from datetime import timedelta
from apps.food.api.serializers import MenuSerializer, HappyHourSerializer from apps.food.api.v1_1.serializers import MenuSerializer, HappyHourSerializer
from apps.food.models import Menu, HappyHour from apps.food.models import Menu, HappyHour
from rest_framework import viewsets from rest_framework import viewsets
from rest_framework.decorators import api_view, permission_classes from rest_framework.decorators import permission_classes
from rest_framework.permissions import AllowAny from rest_framework.permissions import AllowAny

View File

View File

@ -1,18 +1,36 @@
from rest_framework import serializers from rest_framework import serializers
from apps.food.models import Menu, SingleFood, HappyHour, Allergene, UserFoodImage, FoodImage 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 UserFoodImageSerializer(serializers.HyperlinkedModelSerializer): class DefaultFoodImageSerializer(serializers.Serializer):
class Meta: """Your data serializer, define your fields here."""
model = UserFoodImage
fields = ('id', 'image_image', 'image_thumb') def create(self, validated_data):
pass
def update(self, instance, validated_data):
pass
image = serializers.CharField()
class FoodImageSerializer(serializers.HyperlinkedModelSerializer): class MenusLocationsSerializer(serializers.Serializer):
class Meta: """Your data serializer, define your fields here."""
model = FoodImage
fields = ('id', 'image', 'thumb') def create(self, validated_data):
pass
def update(self, instance, validated_data):
pass
id = serializers.CharField()
short = serializers.CharField()
name = serializers.CharField()
class AllergensSerializer(serializers.HyperlinkedModelSerializer): class AllergensSerializer(serializers.HyperlinkedModelSerializer):
@ -21,18 +39,44 @@ class AllergensSerializer(serializers.HyperlinkedModelSerializer):
fields = ('id', 'name') fields = ('id', 'name')
class SingleFoodSerializer(serializers.HyperlinkedModelSerializer): class OverviewFoodImageSerializer(serializers.HyperlinkedModelSerializer):
allergens = AllergensSerializer(many=True, read_only=True) class Meta:
image = FoodImageSerializer(many=False, read_only=True) model = FoodImage
fields = ('id', 'thumb')
class DetailedFoodImageSerializer(serializers.HyperlinkedModelSerializer):
class Meta:
model = FoodImage
fields = ('id', 'image', 'thumb')
class OverviewSingleFoodSerializer(serializers.HyperlinkedModelSerializer):
image = OverviewFoodImageSerializer(many=False, read_only=True)
class Meta: class Meta:
model = SingleFood model = SingleFood
fields = ('name', 'rating', 'price_student', 'price_employee', 'price_guest', 'allergens', 'image') fields = ('id', 'name', 'rating', 'price_student', 'image')
class MenuSerializer(serializers.HyperlinkedModelSerializer): class MinimalSingleFoodSerializer(serializers.HyperlinkedModelSerializer):
class Meta:
model = SingleFood
fields = ('id', 'name')
class DetailedSingleFoosdSerializer(serializers.HyperlinkedModelSerializer):
allergens = AllergensSerializer(many=True, read_only=True)
image = DetailedFoodImageSerializer(many=False, read_only=True)
class Meta:
model = SingleFood
fields = ('id', 'name', 'rating', 'price_student', 'price_employee', 'price_guest', 'allergens', 'image')
class OverviewMenuSerializer(serializers.HyperlinkedModelSerializer):
date = serializers.DateField(format='iso-8601') date = serializers.DateField(format='iso-8601')
menu = SingleFoodSerializer(many=True, read_only=True) menu = OverviewSingleFoodSerializer(many=True, read_only=True)
location = serializers.ChoiceField(choices=Menu.LOCATION_CHOICES) location = serializers.ChoiceField(choices=Menu.LOCATION_CHOICES)
class Meta: class Meta:
@ -40,6 +84,17 @@ class MenuSerializer(serializers.HyperlinkedModelSerializer):
fields = ('id', 'date', 'location', 'menu') fields = ('id', 'date', 'location', 'menu')
class DetailMenuSerializer(serializers.HyperlinkedModelSerializer):
date = serializers.DateField(format='iso-8601')
menu = DetailedSingleFoosdSerializer(many=True, read_only=True)
location = serializers.ChoiceField(choices=Menu.LOCATION_CHOICES)
class Meta:
model = Menu
fields = ('id', 'date', 'location', 'menu')
# -------------------------- Happy Hour ------------------------------------
class HappyHourSerializer(serializers.HyperlinkedModelSerializer): class HappyHourSerializer(serializers.HyperlinkedModelSerializer):
date = serializers.DateField(format='iso-8601') date = serializers.DateField(format='iso-8601')
starttime = serializers.TimeField() starttime = serializers.TimeField()
@ -48,3 +103,53 @@ class HappyHourSerializer(serializers.HyperlinkedModelSerializer):
class Meta: class Meta:
model = HappyHour model = HappyHour
fields = ('id', 'date', 'starttime', 'endtime', 'location', 'description') fields = ('id', 'date', 'starttime', 'endtime', 'location', 'description')
class HappyHourLocationSerializer(serializers.HyperlinkedModelSerializer):
class Meta:
model = HappyHourLocation
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

View File

@ -13,21 +13,25 @@ Including another URLconf
1. Import the include() function: from django.conf.urls import url, include 1. Import the include() function: from django.conf.urls import url, include
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.conf.urls import url from django.urls import path
from apps.food.api.v1_1 import views as api_views from apps.food.api.v1_2 import views as api_views
from apps.food.models import Menu
urlpatterns = [ urlpatterns = [
# API Version 1.1 # API Version 1.2
url(r'^food/$', api_views.FoodViewSetV1_1.as_view({'get': 'list'}), name='api-v1_1-food-all'), path('food/menus/', api_views.ApiMenus.as_view(), name='menus'),
url(r'^food/(?P<location>' + Menu.FEKI + '|' + Menu.MARKUSPLATZ + '|' + Menu.ERBA + '|' + Menu.AUSTRASSE + ')/$', path('food/menus/<int:pk>/', api_views.ApiMenu.as_view(), name='menu'),
api_views.FoodViewSetV1_1.as_view({'get': 'list'}), name='api-v1_1-food-location'), path('food/menus/locations', api_views.ApiMenusLocations.as_view(), name='menus-locations'),
url(r'food/(?P<year>[0-9]{4})/(?P<month>[0-9]{2})/(?P<day>[0-9]{2})/$',
api_views.FoodViewSetV1_1.as_view({'get': 'list'}), name='api-v1_1-food-date'), path('food/meals/', api_views.ApiMeals.as_view(), name='meals'),
url( path('food/meals/<int:pk>', api_views.ApiMeal.as_view(), name='meal'),
r'food/(?P<location>' + Menu.FEKI + '|' + Menu.MARKUSPLATZ + '|' + Menu.ERBA + '|' + Menu.AUSTRASSE + ')/(?P<year>[0-9]{4})/(?P<month>[0-9]{2})/(?P<day>[0-9]{2})/$', path('food/allergens/', api_views.ApiAllergens.as_view(), name='allergens'),
api_views.FoodViewSetV1_1.as_view({'get': 'list'}), name='api-v1_1-food-location-date'), path('food/meals/images/', api_views.ApiFoodImages.as_view(), name='images'),
url(r'food/today/$', api_views.FoodViewSetV1_1.as_view({'get': 'list'}), name='api-v1_1-food-today'), path('food/meals/images/default', api_views.ApiFoodImagesDefault.as_view(), name='images-default'),
url(r'food/week/$', api_views.FoodViewSetV1_1.as_view({'get': 'list'}), name='api-v1_1-food-week'), path('food/meals/<int:pk>/rating', api_views.ApiFoodRatingUpload.as_view(), name='meals-rating-upload'),
url(r'happy-hour', api_views.HappyHourViewSet.as_view({'get': 'list'}), name='api-v1_1-happy-hour-all'), # path('food/meals/<int:pk>/image', api_views.ApiFoodImagesDefault.as_view(), name='meals-image-upload'),
# 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/<int:pk>', api_views.ApiHappyHours.as_view(), name='happy-hours'),
path('food/happy-hours/locations', api_views.ApiHappyHoursLocations.as_view(), name='happy-hours-locations'),
] ]

View File

@ -1,190 +1,226 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
from __future__ import unicode_literals from __future__ import unicode_literals
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_1.serializers import MenuSerializer, HappyHourSerializer from apps.food.api.v1_2.serializers import OverviewMenuSerializer, DetailMenuSerializer, MenusLocationsSerializer
from apps.food.models import Menu, HappyHour from apps.food.api.v1_2.serializers import OverviewSingleFoodSerializer, DetailedSingleFoosdSerializer, \
from rest_framework import viewsets AllergensSerializer, DetailedFoodImageSerializer, DefaultFoodImageSerializer, MinimalSingleFoodSerializer
from apps.food.api.v1_2.serializers import HappyHourSerializer, HappyHourLocationSerializer
from rest_framework.decorators import permission_classes from apps.food.api.v1_2.serializers import UserFoodRatingSerializer
from rest_framework.permissions import AllowAny from apps.food.models import Menu, SingleFood, Allergene, HappyHour, HappyHourLocation, FoodImage, UserFoodRating
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 import views, status
from rest_framework.response import Response
from rest_framework.authentication import TokenAuthentication
from rest_framework.exceptions import ValidationError
# @api_view(['GET'])
@permission_classes((AllowAny,)) @permission_classes((AllowAny,))
class FoodViewSet(viewsets.ModelViewSet, ): class ApiMenus(generics.ListAPIView):
""" serializer_class = OverviewMenuSerializer
API endpoint that allows users to be viewed or edited.
"""
# queryset = Menu.objects.all()
serializer_class = MenuSerializer
def get_queryset(self): def get_queryset(self):
queryset = Menu.objects.all() queryset = Menu.objects.all()
location = self.request.query_params.get('location') location = self.request.query_params.get('location')
date = self.request.query_params.get('date') start_date = self.request.query_params.get('startdate')
print(str(location).upper() == Menu.ERBA.upper()) end_date = self.request.query_params.get('enddate')
if location: if location:
print(str(location).upper() == Menu.ERBA.upper()) if str(location).upper() == Menu.ERBA.upper():
if str(location).upper() is Menu.ERBA.upper(): queryset = queryset.filter(location__contains=Menu.ERBA)
queryset = queryset.filter(location_contains='Erba') elif str(location).upper() == Menu.FEKI.upper():
elif str(location).upper() is Menu.FEKI.upper(): queryset = queryset.filter(location__contains=Menu.FEKI)
queryset = queryset.filter(location=Menu.FEKI) elif str(location).upper() == Menu.AUSTRASSE.upper():
elif str(location).upper() is Menu.AUSTRASSE.upper(): queryset = queryset.filter(location__contains=Menu.AUSTRASSE)
queryset = queryset.filter(location=Menu.AUSTRASSE) elif str(location).upper() == Menu.MARKUSPLATZ.upper():
elif str(location).upper() is Menu.MARKUSPLATZ.upper(): queryset = queryset.filter(location__contains=Menu.MARKUSPLATZ)
queryset = queryset.filter(location=Menu.MARKUSPLATZ)
if date:
if date == "week":
today = datetime.now()
weekday = today.weekday()
monday = today - timedelta(weekday)
sunday = today + (timedelta(6 - weekday))
print("Monday: " + str(monday))
print("Sunday: " + str(sunday))
queryset = queryset.filter(date__gte=monday, date__lte=sunday)
else: else:
queryset = queryset.filter(date=datetime.strptime(date, "%Y-%m-%d")) queryset = []
if start_date:
try:
queryset = queryset.filter(date__gte=datetime.strptime(start_date, '%Y-%m-%d'))
except ValueError as e:
# TODO: return Exception
return []
print("LOCATION: %s" % str(location)) if end_date:
print("DATE: " + str(date)) try:
print(str(queryset)) queryset = queryset.filter(date__lte=datetime.strptime(end_date, '%Y-%m-%d'))
except ValueError as e:
# TODO: return Exception
return []
return queryset return queryset
# @api_view(['GET'])
@permission_classes((AllowAny,)) @permission_classes((AllowAny,))
class FoodViewSetV1_1(viewsets.ModelViewSet, ): class ApiMenu(generics.RetrieveAPIView):
""" serializer_class = DetailMenuSerializer
API endpoint that allows users to be viewed or edited. queryset = Menu.objects.all()
"""
# queryset = Menu.objects.all()
serializer_class = MenuSerializer @permission_classes((AllowAny,))
class ApiMeals(generics.ListAPIView):
serializer_class = OverviewSingleFoodSerializer
def get_queryset(self): def get_queryset(self):
queryset = Menu.objects.all() queryset = SingleFood.objects.all()
location = None rating = self.request.query_params.get('rating')
if 'location' in self.kwargs: max_rating = self.request.query_params.get('max-rating')
location = self.kwargs['location'] min_rating = self.request.query_params.get('min-rating')
year = None price = self.request.query_params.get('price')
if 'year' in self.kwargs: max_price = self.request.query_params.get('max-price')
year = self.kwargs['year'] min_price = self.request.query_params.get('min-price')
month = None
if 'month' in self.kwargs:
month = self.kwargs['month']
day = None
if 'day' in self.kwargs:
day = self.kwargs['day']
if location: allergens = self.request.query_params.get('allergens')
if str(location).upper() == Menu.ERBA.upper():
queryset = queryset.filter(location__contains=Menu.ERBA)
elif str(location).upper() == Menu.FEKI.upper():
queryset = queryset.filter(location__contains=Menu.FEKI)
elif str(location).upper() == Menu.AUSTRASSE.upper():
print("Before: " + str(queryset))
queryset = queryset.filter(location__contains=Menu.AUSTRASSE)
elif str(location).upper() == Menu.MARKUSPLATZ.upper():
queryset = queryset.filter(location__contains=Menu.MARKUSPLATZ)
print(queryset)
if year and month and day:
date = '%s-%s-%s' % (year, month, day)
queryset = queryset.filter(date=datetime.strptime(date, '%Y-%m-%d'))
# if date == "week": if rating:
# today = datetime.now() queryset = queryset.filter(rating=rating)
# weekday = today.weekday()
# monday = today - timedelta(weekday)
# sunday = today + (timedelta(6 - weekday))
# print("Monday: " + str(monday))
# print("Sunday: " + str(sunday))
# queryset = queryset.filter(date__gte=monday, date__lte=sunday)
# else:
# queryset = queryset.filter(date=datetime.strptime(date, "%Y-%m-%d"))
print("LOCATION: %s" % str(location)) if max_rating:
print(str(queryset)) queryset = queryset.filter(rating__lte=max_rating)
if min_rating:
queryset = queryset.filter(rating__gte=min_rating)
# TODO: Change price model to Floatfield
# if price:
# pass
#
# if max_price:
# pass
#
# if min_price:
# pass
if allergens:
allergens = [allergen for allergen in str(allergens).strip('[]').split(',')]
queryset = queryset.filter(allergens__id__in=allergens)
return queryset return queryset
# @api_view(['GET'])
@permission_classes((AllowAny,)) @permission_classes((AllowAny,))
class FoodViewSetV1_1(viewsets.ModelViewSet, ): class ApiMeal(generics.RetrieveAPIView):
""" serializer_class = DetailedSingleFoosdSerializer
API endpoint that allows users to be viewed or edited. queryset = SingleFood.objects.all()
"""
# queryset = Menu.objects.all()
serializer_class = MenuSerializer
def get_queryset(self):
queryset = Menu.objects.all()
location = None
if 'location' in self.kwargs:
location = self.kwargs['location']
year = None
if 'year' in self.kwargs:
year = self.kwargs['year']
month = None
if 'month' in self.kwargs:
month = self.kwargs['month']
day = None
if 'day' in self.kwargs:
day = self.kwargs['day']
if location:
if str(location).upper() == Menu.ERBA.upper():
queryset = queryset.filter(location__contains=Menu.ERBA)
elif str(location).upper() == Menu.FEKI.upper():
queryset = queryset.filter(location__contains=Menu.FEKI)
elif str(location).upper() == Menu.AUSTRASSE.upper():
print("Before: " + str(queryset))
queryset = queryset.filter(location__contains=Menu.AUSTRASSE)
elif str(location).upper() == Menu.MARKUSPLATZ.upper():
queryset = queryset.filter(location__contains=Menu.MARKUSPLATZ)
print(queryset)
if year and month and day:
date = '%s-%s-%s' % (year, month, day)
queryset = queryset.filter(date=datetime.strptime(date, '%Y-%m-%d'))
# if date == "week":
# today = datetime.now()
# weekday = today.weekday()
# monday = today - timedelta(weekday)
# sunday = today + (timedelta(6 - weekday))
# print("Monday: " + str(monday))
# print("Sunday: " + str(sunday))
# queryset = queryset.filter(date__gte=monday, date__lte=sunday)
# else:
# queryset = queryset.filter(date=datetime.strptime(date, "%Y-%m-%d"))
print("LOCATION: %s" % str(location))
print(str(queryset))
return queryset
# @api_view(['GET'])
@permission_classes((AllowAny,)) @permission_classes((AllowAny,))
class HappyHourViewSet(viewsets.ModelViewSet): class ApiAllergens(generics.ListAPIView):
""" serializer_class = AllergensSerializer
API endpoint that allows users to be viewed or edited. queryset = Allergene.objects.all()
"""
queryset = HappyHour.objects.all()
@permission_classes((AllowAny,))
class ApiMenusLocations(views.APIView):
def get(self, request):
locations = Menu.API_LOCATIONS
results = MenusLocationsSerializer(locations, many=True).data
return Response(results, status=status.HTTP_200_OK)
@permission_classes((AllowAny,))
class ApiHappyHours(generics.ListAPIView):
serializer_class = HappyHourSerializer serializer_class = HappyHourSerializer
def get_queryset(self): def get_queryset(self):
queryset = HappyHour.objects.all() queryset = HappyHour.objects.all()
type = self.request.query_params.get('type') date = self.request.query_params.get('date')
start_date = self.request.query_params.get('startdate')
end_date = self.request.query_params.get('enddate')
# if type == "food": start_time = self.request.query_params.get('starttime')
# queryset = HappyHour.filter(location__contains="Austraße") end_time = self.request.query_params.get('endtime')
# elif type == "drinks":
# queryset = HappyHour.filter(location__contains="Austraße") location = self.request.query_params.get('location')
if date:
try:
queryset = queryset.filter(date=datetime.strptime(date, '%Y-%m-%d'))
except ValueError as e:
# TODO: return Exception
return []
if start_date:
try:
queryset = queryset.filter(date__gte=datetime.strptime(start_date, '%Y-%m-%d'))
except ValueError as e:
# TODO: return Exception
return []
if end_date:
try:
queryset = queryset.filter(date__lte=datetime.strptime(start_date, '%Y-%m-%d'))
except ValueError as e:
# TODO: return Exception
return []
if start_time:
try:
queryset = queryset.filter(date__lte=datetime.strptime(start_time, '%H'))
except ValueError as e:
# TODO: return Exception
return []
if end_time:
try:
queryset = queryset.filter(date__lte=datetime.strptime(end_time, '%H'))
except ValueError as e:
# TODO: return Exception
return []
if location:
queryset = queryset.filter(location__id=location)
return queryset return queryset
@permission_classes((AllowAny,))
class ApiHappyHoursLocations(generics.RetrieveAPIView):
serializer_class = HappyHourSerializer
queryset = HappyHour.objects.all()
@permission_classes((AllowAny,))
class ApiHappyHoursLocations(generics.ListAPIView):
serializer_class = HappyHourLocationSerializer
queryset = HappyHourLocation.objects.all()
@permission_classes((AllowAny,))
class ApiFoodImages(generics.ListAPIView):
serializer_class = DetailedFoodImageSerializer
queryset = FoodImage.objects.all()
@permission_classes((AllowAny,))
class ApiFoodImagesDefault(views.APIView):
def get(self, request):
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
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