Recipe list&detail api-endpoints
This commit is contained in:
parent
297f5daba8
commit
cace6a7d3b
44
apps/recipe/migrations/0001_initial.py
Normal file
44
apps/recipe/migrations/0001_initial.py
Normal file
|
|
@ -0,0 +1,44 @@
|
||||||
|
# Generated by Django 2.2.4 on 2019-09-19 11:07
|
||||||
|
|
||||||
|
from django.conf import settings
|
||||||
|
from django.db import migrations, models
|
||||||
|
import django.db.models.deletion
|
||||||
|
import django.utils.timezone
|
||||||
|
import easy_thumbnails.fields
|
||||||
|
import utils.methods
|
||||||
|
import utils.models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
initial = True
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.CreateModel(
|
||||||
|
name='Recipe',
|
||||||
|
fields=[
|
||||||
|
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||||
|
('created', models.DateTimeField(default=django.utils.timezone.now, editable=False, verbose_name='Date created')),
|
||||||
|
('modified', models.DateTimeField(auto_now=True, verbose_name='Date updated')),
|
||||||
|
('image', easy_thumbnails.fields.ThumbnailerImageField(blank=True, default=None, null=True, upload_to=utils.methods.image_path, verbose_name='Image')),
|
||||||
|
('title', utils.models.TJSONField(blank=True, default=None, help_text='{"en-GB": "some text"}', null=True, verbose_name='Title')),
|
||||||
|
('subtitle', utils.models.TJSONField(blank=True, default=None, help_text='{"en-GB": "some text"}', null=True, verbose_name='Subtitle')),
|
||||||
|
('description', utils.models.TJSONField(blank=True, default=None, help_text='{"en-GB": "some text"}', null=True, verbose_name='Description')),
|
||||||
|
('state', models.PositiveSmallIntegerField(choices=[(0, 'Waiting'), (1, 'Hidden'), (2, 'Published'), (3, 'Published exclusive')], default=0, verbose_name='State')),
|
||||||
|
('author', models.CharField(blank=True, default=None, max_length=255, null=True, verbose_name='Author')),
|
||||||
|
('published_at', models.DateTimeField(blank=True, default=None, help_text='Published at', null=True, verbose_name='Published at')),
|
||||||
|
('published_scheduled_at', models.DateTimeField(blank=True, default=None, help_text='Published scheduled at', null=True, verbose_name='Published scheduled at')),
|
||||||
|
('created_by', models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='recipe_records_created', to=settings.AUTH_USER_MODEL, verbose_name='created by')),
|
||||||
|
('modified_by', models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='recipe_records_modified', to=settings.AUTH_USER_MODEL, verbose_name='modified by')),
|
||||||
|
],
|
||||||
|
options={
|
||||||
|
'verbose_name': 'Recipe',
|
||||||
|
'verbose_name_plural': 'Recipes',
|
||||||
|
},
|
||||||
|
bases=(utils.models.TranslatedFieldsMixin, models.Model),
|
||||||
|
),
|
||||||
|
]
|
||||||
|
|
@ -5,6 +5,15 @@ from utils.models import (TranslatedFieldsMixin, ImageMixin, BaseAttributes,
|
||||||
TJSONField)
|
TJSONField)
|
||||||
|
|
||||||
|
|
||||||
|
class RecipeQuerySet(models.QuerySet):
|
||||||
|
"""Extended queryset for Recipe model."""
|
||||||
|
|
||||||
|
# todo: what records are considered published?
|
||||||
|
def published(self):
|
||||||
|
return self.filter(state__in=[self.model.PUBLISHED,
|
||||||
|
self.model.PUBLISHED_EXCLUSIVE])
|
||||||
|
|
||||||
|
|
||||||
class Recipe(TranslatedFieldsMixin, ImageMixin, BaseAttributes):
|
class Recipe(TranslatedFieldsMixin, ImageMixin, BaseAttributes):
|
||||||
"""Recipe model."""
|
"""Recipe model."""
|
||||||
|
|
||||||
|
|
@ -30,6 +39,8 @@ class Recipe(TranslatedFieldsMixin, ImageMixin, BaseAttributes):
|
||||||
help_text='{"en-GB": "some text"}')
|
help_text='{"en-GB": "some text"}')
|
||||||
state = models.PositiveSmallIntegerField(default=WAITING, choices=STATE_CHOICES,
|
state = models.PositiveSmallIntegerField(default=WAITING, choices=STATE_CHOICES,
|
||||||
verbose_name=_('State'))
|
verbose_name=_('State'))
|
||||||
|
author = models.CharField(max_length=255, blank=True, null=True, default=None,
|
||||||
|
verbose_name=_('Author'))
|
||||||
published_at = models.DateTimeField(verbose_name=_('Published at'),
|
published_at = models.DateTimeField(verbose_name=_('Published at'),
|
||||||
blank=True, default=None, null=True,
|
blank=True, default=None, null=True,
|
||||||
help_text=_('Published at'))
|
help_text=_('Published at'))
|
||||||
|
|
@ -37,6 +48,8 @@ class Recipe(TranslatedFieldsMixin, ImageMixin, BaseAttributes):
|
||||||
blank=True, default=None, null=True,
|
blank=True, default=None, null=True,
|
||||||
help_text=_('Published scheduled at'))
|
help_text=_('Published scheduled at'))
|
||||||
|
|
||||||
|
objects = RecipeQuerySet.as_manager()
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
"""Meta class."""
|
"""Meta class."""
|
||||||
|
|
||||||
|
|
|
||||||
0
apps/recipe/serializers/__init__.py
Normal file
0
apps/recipe/serializers/__init__.py
Normal file
29
apps/recipe/serializers/common.py
Normal file
29
apps/recipe/serializers/common.py
Normal file
|
|
@ -0,0 +1,29 @@
|
||||||
|
"""Recipe app common serializers."""
|
||||||
|
from rest_framework import serializers
|
||||||
|
from recipe import models
|
||||||
|
|
||||||
|
|
||||||
|
class RecipeListSerializer(serializers.ModelSerializer):
|
||||||
|
"""Serializer for list of recipes."""
|
||||||
|
|
||||||
|
title_translated = serializers.CharField(allow_null=True, read_only=True)
|
||||||
|
subtitle_translated = serializers.CharField(allow_null=True, read_only=True)
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
"""Meta class."""
|
||||||
|
|
||||||
|
model = models.Recipe
|
||||||
|
fields = ('id', 'title_translated', 'subtitle_translated', 'author',
|
||||||
|
'published_at')
|
||||||
|
read_only_fields = fields
|
||||||
|
|
||||||
|
|
||||||
|
class RecipeDetailSerializer(RecipeListSerializer):
|
||||||
|
"""Serializer for more information about the recipe."""
|
||||||
|
|
||||||
|
description_translated = serializers.CharField(allow_null=True, read_only=True)
|
||||||
|
|
||||||
|
class Meta(RecipeListSerializer.Meta):
|
||||||
|
"""Meta class."""
|
||||||
|
|
||||||
|
fields = RecipeListSerializer.Meta.fields + ('description_translated',)
|
||||||
0
apps/recipe/urls/__init__.py
Normal file
0
apps/recipe/urls/__init__.py
Normal file
10
apps/recipe/urls/common.py
Normal file
10
apps/recipe/urls/common.py
Normal file
|
|
@ -0,0 +1,10 @@
|
||||||
|
"""Recipe app common urlpatterns."""
|
||||||
|
from django.urls import path
|
||||||
|
from recipe.views import common as views
|
||||||
|
|
||||||
|
|
||||||
|
app_name = 'recipe'
|
||||||
|
urlpatterns = [
|
||||||
|
path('', views.RecipeListView.as_view(), name='list'),
|
||||||
|
path('<int:pk>/', views.RecipeDetailView.as_view(), name='detail'),
|
||||||
|
]
|
||||||
6
apps/recipe/urls/web.py
Normal file
6
apps/recipe/urls/web.py
Normal file
|
|
@ -0,0 +1,6 @@
|
||||||
|
"""Recipe app web urlconf."""
|
||||||
|
from recipe.urls.common import urlpatterns as common_urlpatterns
|
||||||
|
|
||||||
|
|
||||||
|
urlpatterns = []
|
||||||
|
urlpatterns.extend(common_urlpatterns)
|
||||||
0
apps/recipe/views/__init__.py
Normal file
0
apps/recipe/views/__init__.py
Normal file
21
apps/recipe/views/common.py
Normal file
21
apps/recipe/views/common.py
Normal file
|
|
@ -0,0 +1,21 @@
|
||||||
|
"""Recipe app common views."""
|
||||||
|
from rest_framework import generics, permissions
|
||||||
|
from recipe import models
|
||||||
|
from recipe.serializers import common as serializers
|
||||||
|
|
||||||
|
|
||||||
|
class RecipeListView(generics.ListAPIView):
|
||||||
|
"""Resource for obtaining a list of recipes."""
|
||||||
|
|
||||||
|
pagination_class = None
|
||||||
|
permission_classes = (permissions.AllowAny,)
|
||||||
|
queryset = models.Recipe.objects.published()
|
||||||
|
serializer_class = serializers.RecipeListSerializer
|
||||||
|
|
||||||
|
|
||||||
|
class RecipeDetailView(generics.RetrieveAPIView):
|
||||||
|
"""Resource for detailed recipe information."""
|
||||||
|
|
||||||
|
permission_classes = (permissions.AllowAny,)
|
||||||
|
queryset = models.Recipe.objects.published()
|
||||||
|
serializer_class = serializers.RecipeDetailSerializer
|
||||||
|
|
@ -27,6 +27,7 @@ urlpatterns = [
|
||||||
path('partner/', include('partner.urls.web')),
|
path('partner/', include('partner.urls.web')),
|
||||||
path('location/', include('location.urls.web')),
|
path('location/', include('location.urls.web')),
|
||||||
path('main/', include('main.urls')),
|
path('main/', include('main.urls')),
|
||||||
|
path('recipes/', include('recipe.urls.web')),
|
||||||
path('translation/', include('translation.urls')),
|
path('translation/', include('translation.urls')),
|
||||||
path('comments/', include('comment.urls.web')),
|
path('comments/', include('comment.urls.web')),
|
||||||
path('favorites/', include('favorites.urls')),
|
path('favorites/', include('favorites.urls')),
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user