refactored detail and list view of products
This commit is contained in:
parent
7fcba802c1
commit
46662398e4
|
|
@ -0,0 +1,4 @@
|
||||||
|
from .mobile import *
|
||||||
|
from .back import *
|
||||||
|
from .web import *
|
||||||
|
from .common import *
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
"""Common serializers for app comment."""
|
"""Common serializers for app comment."""
|
||||||
from rest_framework import serializers
|
from rest_framework import serializers
|
||||||
|
|
||||||
from comment import models
|
from comment.models import Comment
|
||||||
|
|
||||||
|
|
||||||
class CommentSerializer(serializers.ModelSerializer):
|
class CommentSerializer(serializers.ModelSerializer):
|
||||||
|
|
@ -14,7 +14,7 @@ class CommentSerializer(serializers.ModelSerializer):
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
"""Serializer for model Comment"""
|
"""Serializer for model Comment"""
|
||||||
model = models.Comment
|
model = Comment
|
||||||
fields = [
|
fields = [
|
||||||
'id',
|
'id',
|
||||||
'user_id',
|
'user_id',
|
||||||
|
|
@ -25,3 +25,17 @@ class CommentSerializer(serializers.ModelSerializer):
|
||||||
'nickname',
|
'nickname',
|
||||||
'profile_pic'
|
'profile_pic'
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
|
class CommentRUDSerializer(CommentSerializer):
|
||||||
|
"""Retrieve/Update/Destroy comment serializer."""
|
||||||
|
class Meta(CommentSerializer.Meta):
|
||||||
|
"""Meta class."""
|
||||||
|
fields = [
|
||||||
|
'id',
|
||||||
|
'created',
|
||||||
|
'text',
|
||||||
|
'mark',
|
||||||
|
'nickname',
|
||||||
|
'profile_pic',
|
||||||
|
]
|
||||||
|
|
|
||||||
|
|
@ -5,14 +5,14 @@ from rest_framework import serializers
|
||||||
from comment import models as comment_models
|
from comment import models as comment_models
|
||||||
from comment.serializers import common as comment_serializers
|
from comment.serializers import common as comment_serializers
|
||||||
from establishment import models
|
from establishment import models
|
||||||
from location.serializers import AddressBaseSerializer
|
from location.serializers import AddressBaseSerializer, CitySerializer
|
||||||
from main.serializers import AwardSerializer, CurrencySerializer
|
from main.serializers import AwardSerializer, CurrencySerializer
|
||||||
from review import models as review_models
|
|
||||||
from tag.serializers import TagBaseSerializer
|
from tag.serializers import TagBaseSerializer
|
||||||
from timetable.serialziers import ScheduleRUDSerializer
|
from timetable.serialziers import ScheduleRUDSerializer
|
||||||
from utils import exceptions as utils_exceptions
|
from utils import exceptions as utils_exceptions
|
||||||
from utils.serializers import (ProjectModelSerializer, TranslatedField,
|
from utils.serializers import (ProjectModelSerializer, TranslatedField,
|
||||||
FavoritesCreateSerializer)
|
FavoritesCreateSerializer)
|
||||||
|
from review.serializers import ReviewShortSerializer
|
||||||
|
|
||||||
|
|
||||||
class ContactPhonesSerializer(serializers.ModelSerializer):
|
class ContactPhonesSerializer(serializers.ModelSerializer):
|
||||||
|
|
@ -87,18 +87,6 @@ class MenuRUDSerializers(ProjectModelSerializer):
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
class ReviewSerializer(serializers.ModelSerializer):
|
|
||||||
"""Serializer for model Review."""
|
|
||||||
text_translated = serializers.CharField(read_only=True)
|
|
||||||
|
|
||||||
class Meta:
|
|
||||||
"""Meta class."""
|
|
||||||
model = review_models.Review
|
|
||||||
fields = (
|
|
||||||
'text_translated',
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
class EstablishmentTypeBaseSerializer(serializers.ModelSerializer):
|
class EstablishmentTypeBaseSerializer(serializers.ModelSerializer):
|
||||||
"""Serializer for EstablishmentType model."""
|
"""Serializer for EstablishmentType model."""
|
||||||
name_translated = TranslatedField()
|
name_translated = TranslatedField()
|
||||||
|
|
@ -117,6 +105,7 @@ class EstablishmentTypeBaseSerializer(serializers.ModelSerializer):
|
||||||
'use_subtypes': {'write_only': True},
|
'use_subtypes': {'write_only': True},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
class EstablishmentTypeGeoSerializer(EstablishmentTypeBaseSerializer):
|
class EstablishmentTypeGeoSerializer(EstablishmentTypeBaseSerializer):
|
||||||
"""Serializer for EstablishmentType model w/ index_name."""
|
"""Serializer for EstablishmentType model w/ index_name."""
|
||||||
|
|
||||||
|
|
@ -180,6 +169,33 @@ class EstablishmentEmployeeSerializer(serializers.ModelSerializer):
|
||||||
fields = ('id', 'name', 'position_translated', 'awards', 'priority', 'position_index_name')
|
fields = ('id', 'name', 'position_translated', 'awards', 'priority', 'position_index_name')
|
||||||
|
|
||||||
|
|
||||||
|
class EstablishmentShortSerializer(serializers.ModelSerializer):
|
||||||
|
"""Short serializer for establishment."""
|
||||||
|
city = CitySerializer(source='address.city', allow_null=True)
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
"""Meta class."""
|
||||||
|
model = models.Establishment
|
||||||
|
fields = [
|
||||||
|
'id',
|
||||||
|
'name',
|
||||||
|
'slug',
|
||||||
|
'city',
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
class EstablishmentProductSerializer(EstablishmentShortSerializer):
|
||||||
|
"""Serializer for displaying info about an establishment on product page."""
|
||||||
|
|
||||||
|
address = AddressBaseSerializer()
|
||||||
|
|
||||||
|
class Meta(EstablishmentShortSerializer.Meta):
|
||||||
|
"""Meta class."""
|
||||||
|
fields = EstablishmentShortSerializer.Meta.fields + [
|
||||||
|
'address',
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
class EstablishmentBaseSerializer(ProjectModelSerializer):
|
class EstablishmentBaseSerializer(ProjectModelSerializer):
|
||||||
"""Base serializer for Establishment model."""
|
"""Base serializer for Establishment model."""
|
||||||
|
|
||||||
|
|
@ -241,7 +257,7 @@ class EstablishmentDetailSerializer(EstablishmentBaseSerializer):
|
||||||
schedule = ScheduleRUDSerializer(many=True, allow_null=True)
|
schedule = ScheduleRUDSerializer(many=True, allow_null=True)
|
||||||
phones = ContactPhonesSerializer(read_only=True, many=True)
|
phones = ContactPhonesSerializer(read_only=True, many=True)
|
||||||
emails = ContactEmailsSerializer(read_only=True, many=True)
|
emails = ContactEmailsSerializer(read_only=True, many=True)
|
||||||
review = ReviewSerializer(source='last_published_review', allow_null=True)
|
review = ReviewShortSerializer(source='last_published_review', allow_null=True)
|
||||||
employees = EstablishmentEmployeeSerializer(source='actual_establishment_employees',
|
employees = EstablishmentEmployeeSerializer(source='actual_establishment_employees',
|
||||||
many=True)
|
many=True)
|
||||||
menu = MenuSerializers(source='menu_set', many=True, read_only=True)
|
menu = MenuSerializers(source='menu_set', many=True, read_only=True)
|
||||||
|
|
@ -315,21 +331,6 @@ class EstablishmentCommentCreateSerializer(comment_serializers.CommentSerializer
|
||||||
return super().create(validated_data)
|
return super().create(validated_data)
|
||||||
|
|
||||||
|
|
||||||
class EstablishmentCommentRUDSerializer(comment_serializers.CommentSerializer):
|
|
||||||
"""Retrieve/Update/Destroy comment serializer."""
|
|
||||||
class Meta:
|
|
||||||
"""Meta class."""
|
|
||||||
model = comment_models.Comment
|
|
||||||
fields = [
|
|
||||||
'id',
|
|
||||||
'created',
|
|
||||||
'text',
|
|
||||||
'mark',
|
|
||||||
'nickname',
|
|
||||||
'profile_pic',
|
|
||||||
]
|
|
||||||
|
|
||||||
|
|
||||||
class EstablishmentFavoritesCreateSerializer(FavoritesCreateSerializer):
|
class EstablishmentFavoritesCreateSerializer(FavoritesCreateSerializer):
|
||||||
"""Serializer to favorite object w/ model Establishment."""
|
"""Serializer to favorite object w/ model Establishment."""
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,7 @@ from establishment import models, serializers
|
||||||
from main import methods
|
from main import methods
|
||||||
from utils.pagination import EstablishmentPortionPagination
|
from utils.pagination import EstablishmentPortionPagination
|
||||||
from utils.permissions import IsCountryAdmin
|
from utils.permissions import IsCountryAdmin
|
||||||
|
from comment.serializers import CommentRUDSerializer
|
||||||
|
|
||||||
|
|
||||||
class EstablishmentMixinView:
|
class EstablishmentMixinView:
|
||||||
|
|
@ -109,7 +110,7 @@ class EstablishmentCommentListView(generics.ListAPIView):
|
||||||
|
|
||||||
class EstablishmentCommentRUDView(generics.RetrieveUpdateDestroyAPIView):
|
class EstablishmentCommentRUDView(generics.RetrieveUpdateDestroyAPIView):
|
||||||
"""View for retrieve/update/destroy establishment comment."""
|
"""View for retrieve/update/destroy establishment comment."""
|
||||||
serializer_class = serializers.EstablishmentCommentRUDSerializer
|
serializer_class = CommentRUDSerializer
|
||||||
queryset = models.Establishment.objects.all()
|
queryset = models.Establishment.objects.all()
|
||||||
|
|
||||||
def get_object(self):
|
def get_object(self):
|
||||||
|
|
|
||||||
|
|
@ -198,8 +198,8 @@ class WineSubRegion(models.Model):
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
"""Meta class."""
|
"""Meta class."""
|
||||||
verbose_name_plural = _('wine regions')
|
verbose_name_plural = _('wine sub regions')
|
||||||
verbose_name = _('wine region')
|
verbose_name = _('wine sub region')
|
||||||
|
|
||||||
|
|
||||||
class WineVillageQuerySet(models.QuerySet):
|
class WineVillageQuerySet(models.QuerySet):
|
||||||
|
|
|
||||||
|
|
@ -9,8 +9,7 @@ from utils.serializers import TranslatedField
|
||||||
class CountrySerializer(serializers.ModelSerializer):
|
class CountrySerializer(serializers.ModelSerializer):
|
||||||
"""Country serializer."""
|
"""Country serializer."""
|
||||||
|
|
||||||
name_trans = serializers.CharField(source='name_translated', read_only=True,
|
name_translated = TranslatedField()
|
||||||
allow_null=True)
|
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = models.Country
|
model = models.Country
|
||||||
|
|
@ -18,7 +17,7 @@ class CountrySerializer(serializers.ModelSerializer):
|
||||||
'id',
|
'id',
|
||||||
'code',
|
'code',
|
||||||
'svg_image',
|
'svg_image',
|
||||||
'name_trans',
|
'name_translated',
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -154,7 +153,6 @@ class AddressDetailSerializer(AddressBaseSerializer):
|
||||||
|
|
||||||
class WineRegionBaseSerializer(serializers.ModelSerializer):
|
class WineRegionBaseSerializer(serializers.ModelSerializer):
|
||||||
"""Wine region serializer."""
|
"""Wine region serializer."""
|
||||||
name_translated = TranslatedField()
|
|
||||||
country = CountrySerializer()
|
country = CountrySerializer()
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
|
|
@ -162,6 +160,18 @@ class WineRegionBaseSerializer(serializers.ModelSerializer):
|
||||||
model = models.WineRegion
|
model = models.WineRegion
|
||||||
fields = [
|
fields = [
|
||||||
'id',
|
'id',
|
||||||
'name_translated',
|
'name',
|
||||||
'country',
|
'country',
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
|
class WineSubRegionBaseSerializer(serializers.ModelSerializer):
|
||||||
|
"""Wine sub region serializer."""
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
"""Meta class."""
|
||||||
|
model = models.WineSubRegion
|
||||||
|
fields = [
|
||||||
|
'id',
|
||||||
|
'name',
|
||||||
|
]
|
||||||
|
|
|
||||||
|
|
@ -181,10 +181,10 @@ def update_flags():
|
||||||
|
|
||||||
data_types = {
|
data_types = {
|
||||||
"dictionaries": [
|
"dictionaries": [
|
||||||
transfer_countries,
|
# transfer_countries,
|
||||||
transfer_regions,
|
# transfer_regions,
|
||||||
transfer_cities,
|
# transfer_cities,
|
||||||
transfer_addresses,
|
# transfer_addresses,
|
||||||
transfer_wine_region,
|
transfer_wine_region,
|
||||||
transfer_wine_sub_region,
|
transfer_wine_sub_region,
|
||||||
transfer_wine_village,
|
transfer_wine_village,
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
"""Product admin conf."""
|
"""Product admin conf."""
|
||||||
from django.contrib import admin
|
from django.contrib import admin
|
||||||
from utils.admin import BaseModelAdminMixin
|
from utils.admin import BaseModelAdminMixin
|
||||||
from .models import Product, ProductType, ProductSubType, Unit
|
from .models import Product, ProductType, ProductSubType, ProductGallery, Unit
|
||||||
|
|
||||||
|
|
||||||
@admin.register(Product)
|
@admin.register(Product)
|
||||||
|
|
@ -14,6 +14,12 @@ class ProductAdmin(BaseModelAdminMixin, admin.ModelAdmin):
|
||||||
'tags', 'gallery')
|
'tags', 'gallery')
|
||||||
|
|
||||||
|
|
||||||
|
@admin.register(ProductGallery)
|
||||||
|
class ProductGalleryAdmin(admin.ModelAdmin):
|
||||||
|
"""Admin page for model ProductGallery."""
|
||||||
|
raw_id_fields = ('product', 'image', )
|
||||||
|
|
||||||
|
|
||||||
@admin.register(ProductType)
|
@admin.register(ProductType)
|
||||||
class ProductTypeAdmin(admin.ModelAdmin):
|
class ProductTypeAdmin(admin.ModelAdmin):
|
||||||
"""Admin page for model ProductType."""
|
"""Admin page for model ProductType."""
|
||||||
|
|
|
||||||
|
|
@ -194,6 +194,8 @@ class Product(TranslatedFieldsMixin, BaseAttributes):
|
||||||
MaxValueValidator(LATEST_VINTAGE_YEAR)])
|
MaxValueValidator(LATEST_VINTAGE_YEAR)])
|
||||||
gallery = models.ManyToManyField('gallery.Image', through='ProductGallery')
|
gallery = models.ManyToManyField('gallery.Image', through='ProductGallery')
|
||||||
reviews = generic.GenericRelation(to='review.Review')
|
reviews = generic.GenericRelation(to='review.Review')
|
||||||
|
comments = generic.GenericRelation(to='comment.Comment')
|
||||||
|
awards = generic.GenericRelation(to='main.Award', related_query_name='product')
|
||||||
|
|
||||||
objects = ProductManager.from_queryset(ProductQuerySet)()
|
objects = ProductManager.from_queryset(ProductQuerySet)()
|
||||||
|
|
||||||
|
|
@ -217,6 +219,34 @@ class Product(TranslatedFieldsMixin, BaseAttributes):
|
||||||
# self.wine_appellation not in self.wine_region.appellations.all():
|
# self.wine_appellation not in self.wine_region.appellations.all():
|
||||||
# raise ValidationError(_('Wine appellation not exists in wine region.'))
|
# raise ValidationError(_('Wine appellation not exists in wine region.'))
|
||||||
|
|
||||||
|
@property
|
||||||
|
def product_type_translated_name(self):
|
||||||
|
"""Get translated name of product type."""
|
||||||
|
return self.product_type.name_translated if self.product_type else None
|
||||||
|
|
||||||
|
@property
|
||||||
|
def last_published_review(self):
|
||||||
|
"""Return last published review"""
|
||||||
|
return self.reviews.published().order_by('-published_at').first()
|
||||||
|
|
||||||
|
@property
|
||||||
|
def sugar_contents(self):
|
||||||
|
return self.tags.filter(category__index_name='sugar-content')
|
||||||
|
|
||||||
|
@property
|
||||||
|
def wine_colors(self):
|
||||||
|
return self.tags.filter(category__index_name='wine-color')
|
||||||
|
|
||||||
|
@property
|
||||||
|
def bottles_produced(self):
|
||||||
|
return self.tags.filter(category__index_name='bottles-produced')
|
||||||
|
|
||||||
|
@property
|
||||||
|
def main_image(self):
|
||||||
|
qs = ProductGallery.objects.filter(product=self, is_main=True)
|
||||||
|
if qs.exists():
|
||||||
|
return qs.first().image.image
|
||||||
|
|
||||||
|
|
||||||
class OnlineProductManager(ProductManager):
|
class OnlineProductManager(ProductManager):
|
||||||
"""Extended manger for OnlineProduct model."""
|
"""Extended manger for OnlineProduct model."""
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,18 @@
|
||||||
"""Product app serializers."""
|
"""Product app serializers."""
|
||||||
from rest_framework import serializers
|
|
||||||
from utils.serializers import TranslatedField, FavoritesCreateSerializer
|
|
||||||
from product.models import Product, ProductSubType, ProductType
|
|
||||||
from utils import exceptions as utils_exceptions
|
|
||||||
from django.utils.translation import gettext_lazy as _
|
from django.utils.translation import gettext_lazy as _
|
||||||
from location.serializers import WineRegionBaseSerializer, CountrySimpleSerializer
|
from rest_framework import serializers
|
||||||
|
|
||||||
|
from comment.models import Comment
|
||||||
|
from comment.serializers import CommentSerializer
|
||||||
|
from establishment.serializers import EstablishmentShortSerializer, EstablishmentProductSerializer
|
||||||
from gallery.models import Image
|
from gallery.models import Image
|
||||||
|
from product import models
|
||||||
|
from review.serializers import ReviewShortSerializer
|
||||||
|
from utils import exceptions as utils_exceptions
|
||||||
|
from utils.serializers import TranslatedField, FavoritesCreateSerializer
|
||||||
|
from main.serializers import AwardSerializer
|
||||||
|
from location.serializers import WineRegionBaseSerializer, WineSubRegionBaseSerializer
|
||||||
|
from tag.serializers import TagBaseSerializer
|
||||||
|
|
||||||
|
|
||||||
class ProductSubTypeBaseSerializer(serializers.ModelSerializer):
|
class ProductSubTypeBaseSerializer(serializers.ModelSerializer):
|
||||||
|
|
@ -14,7 +21,7 @@ class ProductSubTypeBaseSerializer(serializers.ModelSerializer):
|
||||||
index_name_display = serializers.CharField(source='get_index_name_display')
|
index_name_display = serializers.CharField(source='get_index_name_display')
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = ProductSubType
|
model = models.ProductSubType
|
||||||
fields = [
|
fields = [
|
||||||
'id',
|
'id',
|
||||||
'name_translated',
|
'name_translated',
|
||||||
|
|
@ -28,7 +35,7 @@ class ProductTypeBaseSerializer(serializers.ModelSerializer):
|
||||||
index_name_display = serializers.CharField(source='get_index_name_display')
|
index_name_display = serializers.CharField(source='get_index_name_display')
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = ProductType
|
model = models.ProductType
|
||||||
fields = [
|
fields = [
|
||||||
'id',
|
'id',
|
||||||
'name_translated',
|
'name_translated',
|
||||||
|
|
@ -36,32 +43,82 @@ class ProductTypeBaseSerializer(serializers.ModelSerializer):
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
class ProductBaseSerializer(serializers.ModelSerializer):
|
class ProductClassificationBaseSerializer(serializers.ModelSerializer):
|
||||||
"""Product base serializer."""
|
"""Serializer for model ProductClassification."""
|
||||||
name_translated = TranslatedField()
|
|
||||||
description_translated = TranslatedField()
|
name = serializers.CharField(source='classification_type.name')
|
||||||
category_display = serializers.CharField(source='get_category_display')
|
|
||||||
product_type = ProductTypeBaseSerializer()
|
|
||||||
subtypes = ProductSubTypeBaseSerializer(many=True)
|
|
||||||
wine_region = WineRegionBaseSerializer(allow_null=True)
|
|
||||||
available_countries = CountrySimpleSerializer(source='country', many=True)
|
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
"""Meta class."""
|
"""Meta class."""
|
||||||
model = Product
|
model = models.ProductClassification
|
||||||
|
fields = (
|
||||||
|
'name',
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class ProductStandardBaseSerializer(serializers.ModelSerializer):
|
||||||
|
"""Serializer for model ProductStandard."""
|
||||||
|
|
||||||
|
standard_type = serializers.CharField(source='get_standard_type_display')
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
"""Meta class."""
|
||||||
|
model = models.ProductStandard
|
||||||
|
fields = (
|
||||||
|
'name',
|
||||||
|
'standard_type',
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class ProductBaseSerializer(serializers.ModelSerializer):
|
||||||
|
"""Product base serializer."""
|
||||||
|
product_type = serializers.CharField(source='product_type_translated_name')
|
||||||
|
subtypes = ProductSubTypeBaseSerializer(many=True)
|
||||||
|
establishment = EstablishmentShortSerializer()
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
"""Meta class."""
|
||||||
|
model = models.Product
|
||||||
fields = [
|
fields = [
|
||||||
'id',
|
'id',
|
||||||
'slug',
|
'slug',
|
||||||
'name_translated',
|
'name',
|
||||||
'category_display',
|
|
||||||
'description_translated',
|
|
||||||
'available',
|
|
||||||
'product_type',
|
'product_type',
|
||||||
'subtypes',
|
'subtypes',
|
||||||
'public_mark',
|
'public_mark',
|
||||||
'wine_region',
|
'establishment',
|
||||||
|
'vintage',
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
class ProductDetailSerializer(ProductBaseSerializer):
|
||||||
|
"""Product detail serializer."""
|
||||||
|
description_translated = TranslatedField()
|
||||||
|
review = ReviewShortSerializer(source='last_published_review')
|
||||||
|
awards = AwardSerializer(many=True)
|
||||||
|
establishment = EstablishmentProductSerializer()
|
||||||
|
classifications = ProductClassificationBaseSerializer(many=True)
|
||||||
|
standards = ProductStandardBaseSerializer(many=True)
|
||||||
|
wine_region = WineRegionBaseSerializer()
|
||||||
|
wine_sub_region = WineSubRegionBaseSerializer()
|
||||||
|
wine_colors = TagBaseSerializer(many=True)
|
||||||
|
bottles_produced = TagBaseSerializer(many=True)
|
||||||
|
sugar_contents = TagBaseSerializer(many=True)
|
||||||
|
main_image = serializers.ImageField(allow_null=True)
|
||||||
|
|
||||||
|
class Meta(ProductBaseSerializer.Meta):
|
||||||
|
fields = ProductBaseSerializer.Meta.fields + [
|
||||||
|
'description_translated',
|
||||||
|
'review',
|
||||||
|
'awards',
|
||||||
|
'classifications',
|
||||||
'standards',
|
'standards',
|
||||||
'available_countries',
|
'wine_region',
|
||||||
|
'wine_sub_region',
|
||||||
|
'wine_colors',
|
||||||
|
'bottles_produced',
|
||||||
|
'sugar_contents',
|
||||||
|
'main_image',
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -70,10 +127,10 @@ class ProductFavoritesCreateSerializer(FavoritesCreateSerializer):
|
||||||
|
|
||||||
def validate(self, attrs):
|
def validate(self, attrs):
|
||||||
"""Overridden validate method"""
|
"""Overridden validate method"""
|
||||||
# Check establishment object
|
# Check product object
|
||||||
product_qs = Product.objects.filter(slug=self.slug)
|
product_qs = models.Product.objects.filter(slug=self.slug)
|
||||||
|
|
||||||
# Check establishment obj by slug from lookup_kwarg
|
# Check product obj by slug from lookup_kwarg
|
||||||
if not product_qs.exists():
|
if not product_qs.exists():
|
||||||
raise serializers.ValidationError({'detail': _('Object not found.')})
|
raise serializers.ValidationError({'detail': _('Object not found.')})
|
||||||
else:
|
else:
|
||||||
|
|
@ -165,3 +222,38 @@ class ProductImageSerializer(serializers.ModelSerializer):
|
||||||
extra_kwargs = {
|
extra_kwargs = {
|
||||||
'orientation': {'write_only': True}
|
'orientation': {'write_only': True}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
class ProductCommentCreateSerializer(CommentSerializer):
|
||||||
|
"""Create comment serializer"""
|
||||||
|
mark = serializers.IntegerField()
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
"""Serializer for model Comment"""
|
||||||
|
model = Comment
|
||||||
|
fields = [
|
||||||
|
'id',
|
||||||
|
'created',
|
||||||
|
'text',
|
||||||
|
'mark',
|
||||||
|
'nickname',
|
||||||
|
'profile_pic',
|
||||||
|
]
|
||||||
|
|
||||||
|
def validate(self, attrs):
|
||||||
|
"""Override validate method"""
|
||||||
|
# Check product object
|
||||||
|
product_slug = self.context.get('request').parser_context.get('kwargs').get('slug')
|
||||||
|
product_qs = models.Product.objects.filter(slug=product_slug)
|
||||||
|
if not product_qs.exists():
|
||||||
|
raise serializers.ValidationError({'detail': _('Product not found.')})
|
||||||
|
attrs['product'] = product_qs.first()
|
||||||
|
return attrs
|
||||||
|
|
||||||
|
def create(self, validated_data, *args, **kwargs):
|
||||||
|
"""Override create method"""
|
||||||
|
validated_data.update({
|
||||||
|
'user': self.context.get('request').user,
|
||||||
|
'content_object': validated_data.pop('product')
|
||||||
|
})
|
||||||
|
return super().create(validated_data)
|
||||||
|
|
@ -151,7 +151,7 @@ data_types = {
|
||||||
],
|
],
|
||||||
"product": [
|
"product": [
|
||||||
transfer_product,
|
transfer_product,
|
||||||
transfer_plate,
|
# transfer_plate,
|
||||||
transfer_plate_image,
|
# transfer_plate_image,
|
||||||
],
|
],
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,14 @@ app_name = 'product'
|
||||||
|
|
||||||
urlpatterns = [
|
urlpatterns = [
|
||||||
path('', views.ProductListView.as_view(), name='list'),
|
path('', views.ProductListView.as_view(), name='list'),
|
||||||
path('slug/<slug:slug>', views.ProductDetailView.as_view(), name='detail'),
|
path('slug/<slug:slug>/', views.ProductDetailView.as_view(), name='detail'),
|
||||||
path('slug/<slug:slug>/favorites/', views.CreateFavoriteProductView.as_view(),
|
path('slug/<slug:slug>/favorites/', views.CreateFavoriteProductView.as_view(),
|
||||||
name='create-destroy-favorites')
|
name='create-destroy-favorites'),
|
||||||
|
path('slug/<slug:slug>/comments/', views.ProductCommentListView.as_view(),
|
||||||
|
name='list-comments'),
|
||||||
|
path('slug/<slug:slug>/comments/create/', views.ProductCommentCreateView.as_view(),
|
||||||
|
name='create-comment'),
|
||||||
|
path('slug/<slug:slug>/comments/<int:comment_id>/', views.ProductCommentRUDView.as_view(),
|
||||||
|
name='rud-comment'),
|
||||||
|
|
||||||
]
|
]
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,7 @@
|
||||||
|
"""Product mobile url patterns."""
|
||||||
|
from product.urls.common import urlpatterns as common_urlpatterns
|
||||||
|
|
||||||
|
urlpatterns = [
|
||||||
|
]
|
||||||
|
|
||||||
|
urlpatterns.extend(common_urlpatterns)
|
||||||
|
|
@ -2,8 +2,10 @@
|
||||||
from rest_framework import generics, permissions
|
from rest_framework import generics, permissions
|
||||||
from django.shortcuts import get_object_or_404
|
from django.shortcuts import get_object_or_404
|
||||||
from product.models import Product
|
from product.models import Product
|
||||||
|
from comment.models import Comment
|
||||||
from product import serializers
|
from product import serializers
|
||||||
from product import filters
|
from product import filters
|
||||||
|
from comment.serializers import CommentRUDSerializer
|
||||||
|
|
||||||
|
|
||||||
class ProductBaseView(generics.GenericAPIView):
|
class ProductBaseView(generics.GenericAPIView):
|
||||||
|
|
@ -24,7 +26,7 @@ class ProductListView(ProductBaseView, generics.ListAPIView):
|
||||||
class ProductDetailView(ProductBaseView, generics.RetrieveAPIView):
|
class ProductDetailView(ProductBaseView, generics.RetrieveAPIView):
|
||||||
"""Detail view fro model Product."""
|
"""Detail view fro model Product."""
|
||||||
lookup_field = 'slug'
|
lookup_field = 'slug'
|
||||||
serializer_class = serializers.ProductBaseSerializer
|
serializer_class = serializers.ProductDetailSerializer
|
||||||
|
|
||||||
|
|
||||||
class CreateFavoriteProductView(generics.CreateAPIView,
|
class CreateFavoriteProductView(generics.CreateAPIView,
|
||||||
|
|
@ -43,3 +45,45 @@ class CreateFavoriteProductView(generics.CreateAPIView,
|
||||||
# May raise a permission denied
|
# May raise a permission denied
|
||||||
self.check_object_permissions(self.request, favorites)
|
self.check_object_permissions(self.request, favorites)
|
||||||
return favorites
|
return favorites
|
||||||
|
|
||||||
|
|
||||||
|
class ProductCommentCreateView(generics.CreateAPIView):
|
||||||
|
"""View for create new comment."""
|
||||||
|
lookup_field = 'slug'
|
||||||
|
serializer_class = serializers.ProductCommentCreateSerializer
|
||||||
|
queryset = Comment.objects.all()
|
||||||
|
|
||||||
|
|
||||||
|
class ProductCommentListView(generics.ListAPIView):
|
||||||
|
"""View for return list of product comments."""
|
||||||
|
|
||||||
|
permission_classes = (permissions.AllowAny,)
|
||||||
|
serializer_class = serializers.ProductCommentCreateSerializer
|
||||||
|
|
||||||
|
def get_queryset(self):
|
||||||
|
"""Override get_queryset method"""
|
||||||
|
product = get_object_or_404(Product, slug=self.kwargs['slug'])
|
||||||
|
return Comment.objects.by_content_type(app_label='product',
|
||||||
|
model='product')\
|
||||||
|
.by_object_id(object_id=product.pk)\
|
||||||
|
.order_by('-created')
|
||||||
|
|
||||||
|
|
||||||
|
class ProductCommentRUDView(generics.RetrieveUpdateDestroyAPIView):
|
||||||
|
"""View for retrieve/update/destroy product comment."""
|
||||||
|
serializer_class = CommentRUDSerializer
|
||||||
|
queryset = Product.objects.all()
|
||||||
|
|
||||||
|
def get_object(self):
|
||||||
|
"""Returns the object the view is displaying."""
|
||||||
|
queryset = self.filter_queryset(self.get_queryset())
|
||||||
|
|
||||||
|
product_obj = get_object_or_404(queryset,
|
||||||
|
slug=self.kwargs['slug'])
|
||||||
|
comment_obj = get_object_or_404(product_obj.comments.by_user(self.request.user),
|
||||||
|
pk=self.kwargs['comment_id'])
|
||||||
|
|
||||||
|
# May raise a permission denied
|
||||||
|
self.check_object_permissions(self.request, comment_obj)
|
||||||
|
|
||||||
|
return comment_obj
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,4 @@
|
||||||
|
from .back import *
|
||||||
|
from .common import *
|
||||||
|
from .mobile import *
|
||||||
|
from .web import *
|
||||||
|
|
@ -1,18 +1,3 @@
|
||||||
"""Review app common serializers."""
|
"""Review app back serializers."""
|
||||||
from review import models
|
from review import models
|
||||||
from rest_framework import serializers
|
from rest_framework import serializers
|
||||||
|
|
||||||
|
|
||||||
class ReviewBaseSerializer(serializers.ModelSerializer):
|
|
||||||
class Meta:
|
|
||||||
model = models.Review
|
|
||||||
fields = ('id',
|
|
||||||
'reviewer',
|
|
||||||
'text',
|
|
||||||
'language',
|
|
||||||
'status',
|
|
||||||
'child',
|
|
||||||
'published_at',
|
|
||||||
'vintage',
|
|
||||||
'country'
|
|
||||||
)
|
|
||||||
|
|
@ -0,0 +1,29 @@
|
||||||
|
from rest_framework import serializers
|
||||||
|
from review.models import Review
|
||||||
|
|
||||||
|
|
||||||
|
class ReviewBaseSerializer(serializers.ModelSerializer):
|
||||||
|
class Meta:
|
||||||
|
model = Review
|
||||||
|
fields = (
|
||||||
|
'id',
|
||||||
|
'reviewer',
|
||||||
|
'text',
|
||||||
|
'language',
|
||||||
|
'status',
|
||||||
|
'child',
|
||||||
|
'published_at',
|
||||||
|
'vintage',
|
||||||
|
'country'
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class ReviewShortSerializer(ReviewBaseSerializer):
|
||||||
|
"""Serializer for model Review."""
|
||||||
|
text_translated = serializers.CharField(read_only=True)
|
||||||
|
|
||||||
|
class Meta(ReviewBaseSerializer.Meta):
|
||||||
|
"""Meta class."""
|
||||||
|
fields = (
|
||||||
|
'text_translated',
|
||||||
|
)
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
from rest_framework import generics, permissions
|
from rest_framework import generics, permissions
|
||||||
from review.serializers import back as serializers
|
from review import serializers
|
||||||
from review import models
|
from review import models
|
||||||
from utils.permissions import IsReviewerManager, IsRestaurantReviewer
|
from utils.permissions import IsReviewerManager, IsRestaurantReviewer
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -57,7 +57,7 @@ class ChosenTagSettingsQuerySet(models.QuerySet):
|
||||||
|
|
||||||
|
|
||||||
class ChosenTagSettings(models.Model):
|
class ChosenTagSettings(models.Model):
|
||||||
"""Tag model."""
|
"""Chosen tag model."""
|
||||||
|
|
||||||
tag = models.ForeignKey(Tag, on_delete=models.PROTECT)
|
tag = models.ForeignKey(Tag, on_delete=models.PROTECT)
|
||||||
country = models.ForeignKey(Country, on_delete=models.PROTECT)
|
country = models.ForeignKey(Country, on_delete=models.PROTECT)
|
||||||
|
|
@ -68,8 +68,8 @@ class ChosenTagSettings(models.Model):
|
||||||
class Meta:
|
class Meta:
|
||||||
"""Meta class."""
|
"""Meta class."""
|
||||||
|
|
||||||
verbose_name = _('Tag')
|
verbose_name = _('Chosen tag')
|
||||||
verbose_name_plural = _('Tags')
|
verbose_name_plural = _('Chosen tags')
|
||||||
|
|
||||||
|
|
||||||
class TagCategoryQuerySet(models.QuerySet):
|
class TagCategoryQuerySet(models.QuerySet):
|
||||||
|
|
|
||||||
|
|
@ -417,6 +417,8 @@ class ProductSerializer(TransferSerializerMixin):
|
||||||
category__index_name=category_index_name)
|
category__index_name=category_index_name)
|
||||||
if qs.exists():
|
if qs.exists():
|
||||||
return qs.first()
|
return qs.first()
|
||||||
|
else:
|
||||||
|
import ipdb;ipdb.set_trace()
|
||||||
|
|
||||||
def get_wine_standard(self, standard, standard_type):
|
def get_wine_standard(self, standard, standard_type):
|
||||||
if standard:
|
if standard:
|
||||||
|
|
|
||||||
|
|
@ -28,7 +28,6 @@ class RelatedObjectsCountMixin(models.QuerySet):
|
||||||
def _get_related_objects_names(self):
|
def _get_related_objects_names(self):
|
||||||
"""Get all related objects (with reversed)"""
|
"""Get all related objects (with reversed)"""
|
||||||
related_objects_names = []
|
related_objects_names = []
|
||||||
|
|
||||||
for related_object in self.model._meta.related_objects:
|
for related_object in self.model._meta.related_objects:
|
||||||
if isinstance(related_object, models.ManyToManyRel):
|
if isinstance(related_object, models.ManyToManyRel):
|
||||||
related_objects_names.append(related_object.name)
|
related_objects_names.append(related_object.name)
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user