diff --git a/apps/location/admin.py b/apps/location/admin.py index adb355ac..a52fa14e 100644 --- a/apps/location/admin.py +++ b/apps/location/admin.py @@ -19,9 +19,15 @@ class CityAdmin(admin.ModelAdmin): """City admin.""" +class WineAppellationInline(admin.TabularInline): + model = models.WineAppellation + extra = 0 + + @admin.register(models.WineRegion) class WineRegionAdmin(admin.ModelAdmin): """WineRegion admin.""" + inlines = [WineAppellationInline, ] @admin.register(models.WineAppellation) diff --git a/apps/location/serializers/common.py b/apps/location/serializers/common.py index cfc14355..2a70c3b8 100644 --- a/apps/location/serializers/common.py +++ b/apps/location/serializers/common.py @@ -167,7 +167,6 @@ class WineRegionBaseSerializer(serializers.ModelSerializer): """Wine region serializer.""" name_translated = TranslatedField() country = CountrySerializer() - appellations = WineAppellationBaseSerializer(many=True) class Meta: """Meta class.""" @@ -176,5 +175,4 @@ class WineRegionBaseSerializer(serializers.ModelSerializer): 'id', 'name_translated', 'country', - 'appellations', ] diff --git a/apps/product/models.py b/apps/product/models.py index 2f65c16a..b0b1795e 100644 --- a/apps/product/models.py +++ b/apps/product/models.py @@ -79,8 +79,8 @@ class ProductQuerySet(models.QuerySet): """Product queryset.""" def with_base_related(self): - return self.select_related('country', 'product_type', 'establishment') \ - .prefetch_related('product_type__subtypes') + return self.select_related('product_type', 'establishment') \ + .prefetch_related('product_type__subtypes', 'country') def common(self): return self.filter(category=self.model.COMMON) @@ -120,8 +120,8 @@ class Product(TranslatedFieldsMixin, BaseAttributes): description = TJSONField(_('Description'), null=True, blank=True, default=None, help_text='{"en-GB":"some text"}') characteristics = JSONField(_('Characteristics')) - country = models.ForeignKey('location.Country', on_delete=models.PROTECT, - verbose_name=_('Country')) + country = models.ManyToManyField('location.Country', + verbose_name=_('Country')) available = models.BooleanField(_('Available'), default=True) product_type = models.ForeignKey(ProductType, on_delete=models.PROTECT, related_name='products', verbose_name=_('Type')) @@ -138,6 +138,9 @@ class Product(TranslatedFieldsMixin, BaseAttributes): related_name='wines', blank=True, null=True, verbose_name=_('wine region')) + wine_appellation = models.ForeignKey('location.WineAppellation', on_delete=models.PROTECT, + blank=True, null=True, + verbose_name=_('wine appellation')) objects = ProductManager.from_queryset(ProductQuerySet)() @@ -153,6 +156,9 @@ class Product(TranslatedFieldsMixin, BaseAttributes): raise ValidationError(_('wine_region field must be specified.')) if not self.product_type.index_name == ProductType.WINE and self.wine_region: raise ValidationError(_('wine_region field must not be specified.')) + if (self.wine_region and self.wine_appellation) and \ + self.wine_appellation not in self.wine_region.appellations.all(): + raise ValidationError(_('Wine appellation not exists in wine region.')) class OnlineProductManager(ProductManager): diff --git a/apps/product/serializers/common.py b/apps/product/serializers/common.py index c0a8c6ed..fb2f7aeb 100644 --- a/apps/product/serializers/common.py +++ b/apps/product/serializers/common.py @@ -2,7 +2,8 @@ from rest_framework import serializers from utils.serializers import TranslatedField from product.models import Product, ProductSubType, ProductType -from location.serializers import WineRegionBaseSerializer +from location.serializers import (WineRegionBaseSerializer, WineAppellationBaseSerializer, + CountrySimpleSerializer) class ProductSubTypeBaseSerializer(serializers.ModelSerializer): @@ -41,6 +42,8 @@ class ProductBaseSerializer(serializers.ModelSerializer): product_type = ProductTypeBaseSerializer() subtypes = ProductSubTypeBaseSerializer(many=True) wine_region = WineRegionBaseSerializer(allow_null=True) + wine_appellation = WineAppellationBaseSerializer(allow_null=True) + available_countries = CountrySimpleSerializer(source='country', many=True) class Meta: """Meta class.""" @@ -55,4 +58,6 @@ class ProductBaseSerializer(serializers.ModelSerializer): 'subtypes', 'public_mark', 'wine_region', + 'wine_appellation', + 'available_countries', ] diff --git a/apps/utils/models.py b/apps/utils/models.py index fb1de17c..03330eb4 100644 --- a/apps/utils/models.py +++ b/apps/utils/models.py @@ -44,18 +44,19 @@ class TJSONField(JSONField): def to_locale(language): """Turn a language name (en-us) into a locale name (en_US).""" - language, _, country = language.lower().partition('-') - if not country: - return language - # A language with > 2 characters after the dash only has its first - # character after the dash capitalized; e.g. sr-latn becomes sr-Latn. - # A language with 2 characters after the dash has both characters - # capitalized; e.g. en-us becomes en-US. - country, _, tail = country.partition('-') - country = country.title() if len(country) > 2 else country.upper() - if tail: - country += '-' + tail - return language + '-' + country + if language: + language, _, country = language.lower().partition('-') + if not country: + return language + # A language with > 2 characters after the dash only has its first + # character after the dash capitalized; e.g. sr-latn becomes sr-Latn. + # A language with 2 characters after the dash has both characters + # capitalized; e.g. en-us becomes en-US. + country, _, tail = country.partition('-') + country = country.title() if len(country) > 2 else country.upper() + if tail: + country += '-' + tail + return language + '-' + country def translate_field(self, field_name):