Merge branch 'develop' of ssh://gl.id-east.ru:222/gm/gm-backend into develop
This commit is contained in:
commit
15ddbd5a7e
34
apps/location/migrations/0030_auto_20191120_1010.py
Normal file
34
apps/location/migrations/0030_auto_20191120_1010.py
Normal file
|
|
@ -0,0 +1,34 @@
|
||||||
|
# Generated by Django 2.2.7 on 2019-11-20 10:10
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
import django.db.models.deletion
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('gallery', '0006_merge_20191027_1758'),
|
||||||
|
('location', '0029_merge_20191119_1438'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.CreateModel(
|
||||||
|
name='CityGallery',
|
||||||
|
fields=[
|
||||||
|
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||||
|
('is_main', models.BooleanField(default=False, verbose_name='Is the main image')),
|
||||||
|
('city', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='city_gallery', to='location.City', verbose_name='city')),
|
||||||
|
('image', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='city_gallery', to='gallery.Image', verbose_name='image')),
|
||||||
|
],
|
||||||
|
options={
|
||||||
|
'verbose_name': 'city gallery',
|
||||||
|
'verbose_name_plural': 'city galleries',
|
||||||
|
'unique_together': {('city', 'is_main'), ('city', 'image')},
|
||||||
|
},
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='city',
|
||||||
|
name='gallery',
|
||||||
|
field=models.ManyToManyField(through='location.CityGallery', to='gallery.Image'),
|
||||||
|
),
|
||||||
|
]
|
||||||
|
|
@ -8,7 +8,8 @@ from django.utils.translation import gettext_lazy as _
|
||||||
|
|
||||||
from translation.models import Language
|
from translation.models import Language
|
||||||
from utils.models import (ProjectBaseMixin, SVGImageMixin, TJSONField,
|
from utils.models import (ProjectBaseMixin, SVGImageMixin, TJSONField,
|
||||||
TranslatedFieldsMixin, get_current_locale)
|
TranslatedFieldsMixin, get_current_locale,
|
||||||
|
IntermediateGalleryModelMixin, GalleryModelMixin)
|
||||||
|
|
||||||
|
|
||||||
class CountryQuerySet(models.QuerySet):
|
class CountryQuerySet(models.QuerySet):
|
||||||
|
|
@ -96,9 +97,8 @@ class CityQuerySet(models.QuerySet):
|
||||||
return self.filter(country__code=code)
|
return self.filter(country__code=code)
|
||||||
|
|
||||||
|
|
||||||
class City(models.Model):
|
class City(GalleryModelMixin):
|
||||||
"""Region model."""
|
"""Region model."""
|
||||||
|
|
||||||
name = models.CharField(_('name'), max_length=250)
|
name = models.CharField(_('name'), max_length=250)
|
||||||
code = models.CharField(_('code'), max_length=250)
|
code = models.CharField(_('code'), max_length=250)
|
||||||
region = models.ForeignKey(
|
region = models.ForeignKey(
|
||||||
|
|
@ -111,6 +111,8 @@ class City(models.Model):
|
||||||
|
|
||||||
is_island = models.BooleanField(_('is island'), default=False)
|
is_island = models.BooleanField(_('is island'), default=False)
|
||||||
old_id = models.IntegerField(null=True, blank=True, default=None)
|
old_id = models.IntegerField(null=True, blank=True, default=None)
|
||||||
|
gallery = models.ManyToManyField('gallery.Image', through='CityGallery')
|
||||||
|
|
||||||
objects = CityQuerySet.as_manager()
|
objects = CityQuerySet.as_manager()
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
|
|
@ -121,6 +123,24 @@ class City(models.Model):
|
||||||
return self.name
|
return self.name
|
||||||
|
|
||||||
|
|
||||||
|
class CityGallery(IntermediateGalleryModelMixin):
|
||||||
|
"""Gallery for model City."""
|
||||||
|
city = models.ForeignKey(City, null=True,
|
||||||
|
related_name='city_gallery',
|
||||||
|
on_delete=models.CASCADE,
|
||||||
|
verbose_name=_('city'))
|
||||||
|
image = models.ForeignKey('gallery.Image', null=True,
|
||||||
|
related_name='city_gallery',
|
||||||
|
on_delete=models.CASCADE,
|
||||||
|
verbose_name=_('image'))
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
"""CityGallery meta class."""
|
||||||
|
verbose_name = _('city gallery')
|
||||||
|
verbose_name_plural = _('city galleries')
|
||||||
|
unique_together = (('city', 'is_main'), ('city', 'image'))
|
||||||
|
|
||||||
|
|
||||||
class Address(models.Model):
|
class Address(models.Model):
|
||||||
"""Address model."""
|
"""Address model."""
|
||||||
city = models.ForeignKey(City, verbose_name=_('city'), on_delete=models.CASCADE)
|
city = models.ForeignKey(City, verbose_name=_('city'), on_delete=models.CASCADE)
|
||||||
|
|
@ -172,6 +192,10 @@ class WineRegionQuerySet(models.QuerySet):
|
||||||
def with_sub_region_related(self):
|
def with_sub_region_related(self):
|
||||||
return self.prefetch_related('wine_sub_region')
|
return self.prefetch_related('wine_sub_region')
|
||||||
|
|
||||||
|
def having_wines(self, value = True):
|
||||||
|
"""Return qs with regions, which have any wine related to them"""
|
||||||
|
return self.exclude(wines__isnull=value)
|
||||||
|
|
||||||
|
|
||||||
class WineRegion(models.Model, TranslatedFieldsMixin):
|
class WineRegion(models.Model, TranslatedFieldsMixin):
|
||||||
"""Wine region model."""
|
"""Wine region model."""
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,8 @@
|
||||||
from location import models
|
from location import models
|
||||||
from location.serializers import common
|
from location.serializers import common
|
||||||
|
from rest_framework import serializers
|
||||||
|
from gallery.models import Image
|
||||||
|
from django.utils.translation import gettext_lazy as _
|
||||||
|
|
||||||
|
|
||||||
class AddressCreateSerializer(common.AddressDetailSerializer):
|
class AddressCreateSerializer(common.AddressDetailSerializer):
|
||||||
|
|
@ -18,3 +21,45 @@ class CountryBackSerializer(common.CountrySerializer):
|
||||||
'name',
|
'name',
|
||||||
'country_id'
|
'country_id'
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
|
class CityGallerySerializer(serializers.ModelSerializer):
|
||||||
|
"""Serializer class for model CityGallery."""
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
"""Meta class"""
|
||||||
|
|
||||||
|
model = models.CityGallery
|
||||||
|
fields = [
|
||||||
|
'id',
|
||||||
|
'is_main',
|
||||||
|
]
|
||||||
|
|
||||||
|
def get_request_kwargs(self):
|
||||||
|
"""Get url kwargs from request."""
|
||||||
|
return self.context.get('request').parser_context.get('kwargs')
|
||||||
|
|
||||||
|
def validate(self, attrs):
|
||||||
|
"""Override validate method."""
|
||||||
|
city_pk = self.get_request_kwargs().get('pk')
|
||||||
|
image_id = self.get_request_kwargs().get('image_id')
|
||||||
|
|
||||||
|
city_qs = models.City.objects.filter(pk=city_pk)
|
||||||
|
image_qs = Image.objects.filter(id=image_id)
|
||||||
|
|
||||||
|
if not city_qs.exists():
|
||||||
|
raise serializers.ValidationError({'detail': _('City not found')})
|
||||||
|
|
||||||
|
if not image_qs.exists():
|
||||||
|
raise serializers.ValidationError({'detail': _('Image not found')})
|
||||||
|
|
||||||
|
city = city_qs.first()
|
||||||
|
image = image_qs.first()
|
||||||
|
|
||||||
|
if image in city.gallery.all():
|
||||||
|
raise serializers.ValidationError({'detail': _('Image is already added.')})
|
||||||
|
|
||||||
|
attrs['city'] = city
|
||||||
|
attrs['image'] = image
|
||||||
|
|
||||||
|
return attrs
|
||||||
|
|
|
||||||
|
|
@ -11,6 +11,11 @@ urlpatterns = [
|
||||||
|
|
||||||
path('cities/', views.CityListCreateView.as_view(), name='city-list-create'),
|
path('cities/', views.CityListCreateView.as_view(), name='city-list-create'),
|
||||||
path('cities/<int:pk>/', views.CityRUDView.as_view(), name='city-retrieve'),
|
path('cities/<int:pk>/', views.CityRUDView.as_view(), name='city-retrieve'),
|
||||||
|
path('cities/<int:pk>/gallery/', views.CityGalleryListView.as_view(),
|
||||||
|
name='gallery-list'),
|
||||||
|
path('cities/<int:pk>/gallery/<int:image_id>/',
|
||||||
|
views.CityGalleryCreateDestroyView.as_view(),
|
||||||
|
name='gallery-create-destroy'),
|
||||||
|
|
||||||
path('countries/', views.CountryListCreateView.as_view(), name='country-list-create'),
|
path('countries/', views.CountryListCreateView.as_view(), name='country-list-create'),
|
||||||
path('countries/<int:pk>/', views.CountryRUDView.as_view(), name='country-retrieve'),
|
path('countries/<int:pk>/', views.CountryRUDView.as_view(), name='country-retrieve'),
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,11 @@ from rest_framework import generics
|
||||||
from location import models, serializers
|
from location import models, serializers
|
||||||
from location.views import common
|
from location.views import common
|
||||||
from utils.permissions import IsCountryAdmin
|
from utils.permissions import IsCountryAdmin
|
||||||
|
from utils.views import CreateDestroyGalleryViewMixin
|
||||||
from rest_framework.permissions import IsAuthenticatedOrReadOnly
|
from rest_framework.permissions import IsAuthenticatedOrReadOnly
|
||||||
|
from django.shortcuts import get_object_or_404
|
||||||
|
from utils.serializers import ImageBaseSerializer
|
||||||
|
|
||||||
# Address
|
# Address
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -35,6 +39,48 @@ class CityRUDView(common.CityViewMixin, generics.RetrieveUpdateDestroyAPIView):
|
||||||
permission_classes = [IsAuthenticatedOrReadOnly|IsCountryAdmin]
|
permission_classes = [IsAuthenticatedOrReadOnly|IsCountryAdmin]
|
||||||
|
|
||||||
|
|
||||||
|
class CityGalleryCreateDestroyView(common.CityViewMixin,
|
||||||
|
CreateDestroyGalleryViewMixin):
|
||||||
|
"""Resource for a create gallery for product for back-office users."""
|
||||||
|
serializer_class = serializers.CityGallerySerializer
|
||||||
|
permission_classes = [IsAuthenticatedOrReadOnly|IsCountryAdmin]
|
||||||
|
|
||||||
|
def get_object(self):
|
||||||
|
"""
|
||||||
|
Returns the object the view is displaying.
|
||||||
|
"""
|
||||||
|
city_qs = self.filter_queryset(self.get_queryset())
|
||||||
|
|
||||||
|
city = get_object_or_404(city_qs, pk=self.kwargs['pk'])
|
||||||
|
gallery = get_object_or_404(city.city_gallery, image_id=self.kwargs['image_id'])
|
||||||
|
|
||||||
|
# May raise a permission denied
|
||||||
|
self.check_object_permissions(self.request, gallery)
|
||||||
|
|
||||||
|
return gallery
|
||||||
|
|
||||||
|
|
||||||
|
class CityGalleryListView(common.CityViewMixin,
|
||||||
|
generics.ListAPIView):
|
||||||
|
"""Resource for returning gallery for product for back-office users."""
|
||||||
|
serializer_class = ImageBaseSerializer
|
||||||
|
permission_classes = [IsAuthenticatedOrReadOnly|IsCountryAdmin]
|
||||||
|
|
||||||
|
def get_object(self):
|
||||||
|
"""Override get_object method."""
|
||||||
|
qs = super(CityGalleryListView, self).get_queryset()
|
||||||
|
city = get_object_or_404(qs, pk=self.kwargs['pk'])
|
||||||
|
|
||||||
|
# May raise a permission denied
|
||||||
|
self.check_object_permissions(self.request, city)
|
||||||
|
|
||||||
|
return city
|
||||||
|
|
||||||
|
def get_queryset(self):
|
||||||
|
"""Override get_queryset method."""
|
||||||
|
return self.get_object().crop_gallery
|
||||||
|
|
||||||
|
|
||||||
# Region
|
# Region
|
||||||
class RegionListCreateView(common.RegionViewMixin, generics.ListCreateAPIView):
|
class RegionListCreateView(common.RegionViewMixin, generics.ListCreateAPIView):
|
||||||
"""Create view for model Region"""
|
"""Create view for model Region"""
|
||||||
|
|
|
||||||
|
|
@ -68,7 +68,7 @@ class WineRegionListView(generics.ListAPIView):
|
||||||
pagination_class = None
|
pagination_class = None
|
||||||
model = models.WineRegion
|
model = models.WineRegion
|
||||||
permission_classes = (permissions.AllowAny,)
|
permission_classes = (permissions.AllowAny,)
|
||||||
queryset = models.WineRegion.objects.with_sub_region_related().all()
|
queryset = models.WineRegion.objects.with_sub_region_related().having_wines()
|
||||||
serializer_class = serializers.WineRegionSerializer
|
serializer_class = serializers.WineRegionSerializer
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
37
apps/main/filters.py
Normal file
37
apps/main/filters.py
Normal file
|
|
@ -0,0 +1,37 @@
|
||||||
|
from django.core.validators import EMPTY_VALUES
|
||||||
|
from django_filters import rest_framework as filters
|
||||||
|
|
||||||
|
from review import models
|
||||||
|
|
||||||
|
|
||||||
|
class AwardFilter(filters.FilterSet):
|
||||||
|
"""Award filter set."""
|
||||||
|
|
||||||
|
establishment_id = filters.NumberFilter(field_name='object_id', )
|
||||||
|
product_id = filters.NumberFilter(field_name='object_id', )
|
||||||
|
employee_id = filters.NumberFilter(field_name='object_id', )
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
"""Meta class."""
|
||||||
|
|
||||||
|
model = models.Review
|
||||||
|
fields = (
|
||||||
|
'establishment_id',
|
||||||
|
'product_id',
|
||||||
|
'employee_id',
|
||||||
|
)
|
||||||
|
|
||||||
|
def by_establishment_id(self, queryset, name, value):
|
||||||
|
if value not in EMPTY_VALUES:
|
||||||
|
return queryset.by_establishment_id(value, content_type='establishment')
|
||||||
|
return queryset
|
||||||
|
|
||||||
|
def by_product_id(self, queryset, name, value):
|
||||||
|
if value not in EMPTY_VALUES:
|
||||||
|
return queryset.by_product_id(value, content_type='product')
|
||||||
|
return queryset
|
||||||
|
|
||||||
|
def by_employee_id(self, queryset, name, value):
|
||||||
|
if value not in EMPTY_VALUES:
|
||||||
|
return queryset.by_employee_id(value, content_type='establishmentemployee')
|
||||||
|
return queryset
|
||||||
|
|
@ -153,7 +153,7 @@ class Award(TranslatedFieldsMixin, URLImageMixin, models.Model):
|
||||||
PUBLISHED = 1
|
PUBLISHED = 1
|
||||||
|
|
||||||
STATE_CHOICES = (
|
STATE_CHOICES = (
|
||||||
(WAITING,'waiting'),
|
(WAITING, 'waiting'),
|
||||||
(PUBLISHED, 'published')
|
(PUBLISHED, 'published')
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -68,7 +68,6 @@ class Command(BaseCommand):
|
||||||
cursor.execute('''
|
cursor.execute('''
|
||||||
select
|
select
|
||||||
DISTINCT
|
DISTINCT
|
||||||
m.id as old_id,
|
|
||||||
trim(CONVERT(m.value USING utf8)) as tag_value,
|
trim(CONVERT(m.value USING utf8)) as tag_value,
|
||||||
trim(CONVERT(v.key_name USING utf8)) as tag_category
|
trim(CONVERT(v.key_name USING utf8)) as tag_category
|
||||||
FROM product_metadata m
|
FROM product_metadata m
|
||||||
|
|
@ -103,6 +102,14 @@ class Command(BaseCommand):
|
||||||
p.tags.clear()
|
p.tags.clear()
|
||||||
print('End clear tags product')
|
print('End clear tags product')
|
||||||
|
|
||||||
|
|
||||||
|
def remove_tags(self):
|
||||||
|
print('Begin delete many tags')
|
||||||
|
Tag.objects.\
|
||||||
|
filter(news__isnull=True, establishments__isnull=True).delete()
|
||||||
|
print('End delete many tags')
|
||||||
|
|
||||||
|
|
||||||
def product_sql(self):
|
def product_sql(self):
|
||||||
with connections['legacy'].cursor() as cursor:
|
with connections['legacy'].cursor() as cursor:
|
||||||
cursor.execute('''
|
cursor.execute('''
|
||||||
|
|
@ -145,6 +152,7 @@ class Command(BaseCommand):
|
||||||
|
|
||||||
def handle(self, *args, **kwargs):
|
def handle(self, *args, **kwargs):
|
||||||
self.remove_tags_product()
|
self.remove_tags_product()
|
||||||
|
self.remove_tags()
|
||||||
self.add_category_tag()
|
self.add_category_tag()
|
||||||
self.add_type_product_category()
|
self.add_type_product_category()
|
||||||
self.add_tag()
|
self.add_tag()
|
||||||
|
|
|
||||||
|
|
@ -265,8 +265,10 @@ class Product(GalleryModelMixin, TranslatedFieldsMixin, BaseAttributes, HasTagsM
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def related_tags(self):
|
def related_tags(self):
|
||||||
return super().visible_tags.exclude(category__index_name__in=['sugar-content', 'wine-color',
|
return super().visible_tags.exclude(category__index_name__in=[
|
||||||
'bottles-produced','serial-number', 'grape-variety'])
|
'sugar-content', 'wine-color', 'bottles-produced',
|
||||||
|
'serial-number', 'grape-variety']
|
||||||
|
)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def display_name(self):
|
def display_name(self):
|
||||||
|
|
@ -363,7 +365,7 @@ class ProductStandard(models.Model):
|
||||||
|
|
||||||
|
|
||||||
class ProductGallery(IntermediateGalleryModelMixin):
|
class ProductGallery(IntermediateGalleryModelMixin):
|
||||||
|
"""Gallery for model Product."""
|
||||||
product = models.ForeignKey(Product, null=True,
|
product = models.ForeignKey(Product, null=True,
|
||||||
related_name='product_gallery',
|
related_name='product_gallery',
|
||||||
on_delete=models.CASCADE,
|
on_delete=models.CASCADE,
|
||||||
|
|
|
||||||
|
|
@ -17,7 +17,6 @@ class ProductBaseView(generics.GenericAPIView):
|
||||||
return Product.objects.published() \
|
return Product.objects.published() \
|
||||||
.with_base_related() \
|
.with_base_related() \
|
||||||
.annotate_in_favorites(self.request.user) \
|
.annotate_in_favorites(self.request.user) \
|
||||||
.by_country_code(self.request.country_code) \
|
|
||||||
.order_by('-created')
|
.order_by('-created')
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -27,7 +26,8 @@ class ProductListView(ProductBaseView, generics.ListAPIView):
|
||||||
filter_class = filters.ProductFilterSet
|
filter_class = filters.ProductFilterSet
|
||||||
|
|
||||||
def get_queryset(self):
|
def get_queryset(self):
|
||||||
qs = super().get_queryset().with_extended_related()
|
qs = super().get_queryset().with_extended_related() \
|
||||||
|
.by_country_code(self.request.country_code)
|
||||||
return qs
|
return qs
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,7 @@ class ReviewFilter(filters.FilterSet):
|
||||||
"""Review filter set."""
|
"""Review filter set."""
|
||||||
|
|
||||||
establishment_id = filters.NumberFilter(field_name='object_id', )
|
establishment_id = filters.NumberFilter(field_name='object_id', )
|
||||||
|
product_id = filters.NumberFilter(field_name='object_id', )
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
"""Meta class."""
|
"""Meta class."""
|
||||||
|
|
@ -15,9 +16,15 @@ class ReviewFilter(filters.FilterSet):
|
||||||
model = models.Review
|
model = models.Review
|
||||||
fields = (
|
fields = (
|
||||||
'establishment_id',
|
'establishment_id',
|
||||||
|
'product_id',
|
||||||
)
|
)
|
||||||
|
|
||||||
def by_establishment_id(self, queryset, name, value):
|
def by_establishment_id(self, queryset, name, value):
|
||||||
if value not in EMPTY_VALUES:
|
if value not in EMPTY_VALUES:
|
||||||
return queryset.by_establishment_id(value, content_type='establishment')
|
return queryset.by_establishment_id(value, content_type='establishment')
|
||||||
return queryset
|
return queryset
|
||||||
|
|
||||||
|
def by_product_id(self, queryset, name, value):
|
||||||
|
if value not in EMPTY_VALUES:
|
||||||
|
return queryset.by_product_id(value, content_type='product')
|
||||||
|
return queryset
|
||||||
|
|
|
||||||
|
|
@ -34,7 +34,7 @@ def transfer_languages():
|
||||||
|
|
||||||
def transfer_reviews():
|
def transfer_reviews():
|
||||||
establishments = Establishment.objects.filter(old_id__isnull=False).values_list('old_id', flat=True)
|
establishments = Establishment.objects.filter(old_id__isnull=False).values_list('old_id', flat=True)
|
||||||
queryset = Reviews.objects.filter(
|
queryset = Reviews.objects.exclude(product_id__isnull=False).filter(
|
||||||
establishment_id__in=list(establishments),
|
establishment_id__in=list(establishments),
|
||||||
).values('id', 'reviewer_id', 'aasm_state', 'created_at', 'establishment_id', 'mark', 'vintage')
|
).values('id', 'reviewer_id', 'aasm_state', 'created_at', 'establishment_id', 'mark', 'vintage')
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -33,8 +33,38 @@ class ProductDocument(Document):
|
||||||
properties={
|
properties={
|
||||||
'id': fields.IntegerField(),
|
'id': fields.IntegerField(),
|
||||||
'name': fields.KeywordField(),
|
'name': fields.KeywordField(),
|
||||||
|
'index_name': fields.KeywordField(),
|
||||||
'slug': fields.KeywordField(),
|
'slug': fields.KeywordField(),
|
||||||
# 'city' TODO: city indexing
|
'city': fields.ObjectField(
|
||||||
|
attr='address.city',
|
||||||
|
properties={
|
||||||
|
'id': fields.IntegerField(),
|
||||||
|
'name': fields.KeywordField(),
|
||||||
|
'code': fields.KeywordField(),
|
||||||
|
'country': fields.ObjectField(
|
||||||
|
properties={
|
||||||
|
'id': fields.IntegerField(),
|
||||||
|
'name': fields.ObjectField(attr='name_indexing',
|
||||||
|
properties=OBJECT_FIELD_PROPERTIES),
|
||||||
|
'code': fields.KeywordField(),
|
||||||
|
'svg_image': fields.KeywordField(attr='svg_image_indexing')
|
||||||
|
}
|
||||||
|
),
|
||||||
|
}
|
||||||
|
),
|
||||||
|
'address': fields.ObjectField(
|
||||||
|
properties={
|
||||||
|
'city': fields.ObjectField(
|
||||||
|
properties={
|
||||||
|
'country': fields.ObjectField(
|
||||||
|
properties={
|
||||||
|
'code': fields.KeywordField()
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
)
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
wine_colors = fields.ObjectField(
|
wine_colors = fields.ObjectField(
|
||||||
|
|
|
||||||
|
|
@ -70,10 +70,16 @@ class CustomSearchFilterBackend(SearchFilterBackend):
|
||||||
__queries.append(
|
__queries.append(
|
||||||
Q("match", **{k: v})
|
Q("match", **{k: v})
|
||||||
)
|
)
|
||||||
|
__queries.append(
|
||||||
|
Q('wildcard', **{k: f'*{search_term.lower()}*'})
|
||||||
|
)
|
||||||
else:
|
else:
|
||||||
__queries.append(
|
__queries.append(
|
||||||
Q("match", **field_kwargs)
|
Q("match", **field_kwargs)
|
||||||
)
|
)
|
||||||
|
__queries.append(
|
||||||
|
Q('wildcard', **{field: f'*{search_term.lower()}*'})
|
||||||
|
)
|
||||||
else:
|
else:
|
||||||
for field in view.search_fields:
|
for field in view.search_fields:
|
||||||
# Initial kwargs for the match query
|
# Initial kwargs for the match query
|
||||||
|
|
@ -92,8 +98,14 @@ class CustomSearchFilterBackend(SearchFilterBackend):
|
||||||
__queries.append(
|
__queries.append(
|
||||||
Q("match", **{k: v})
|
Q("match", **{k: v})
|
||||||
)
|
)
|
||||||
|
__queries.append(
|
||||||
|
Q('wildcard', **{k: f'*{search_term.lower()}*'})
|
||||||
|
)
|
||||||
else:
|
else:
|
||||||
__queries.append(
|
__queries.append(
|
||||||
Q("match", **field_kwargs)
|
Q("match", **field_kwargs)
|
||||||
)
|
)
|
||||||
|
__queries.append(
|
||||||
|
Q('wildcard', **{field: f'*{search_term.lower()}*'})
|
||||||
|
)
|
||||||
return __queries
|
return __queries
|
||||||
|
|
@ -95,14 +95,6 @@ class ProductTypeDocumentSerializer(serializers.Serializer):
|
||||||
return get_translated_value(obj.name)
|
return get_translated_value(obj.name)
|
||||||
|
|
||||||
|
|
||||||
class ProductEstablishmentDocumentSerializer(serializers.Serializer):
|
|
||||||
"""Related to Product Establishment ES document serializer."""
|
|
||||||
|
|
||||||
id = serializers.IntegerField()
|
|
||||||
name = serializers.CharField()
|
|
||||||
slug = serializers.CharField()
|
|
||||||
|
|
||||||
|
|
||||||
class CityDocumentShortSerializer(serializers.Serializer):
|
class CityDocumentShortSerializer(serializers.Serializer):
|
||||||
"""City serializer for ES Document,"""
|
"""City serializer for ES Document,"""
|
||||||
|
|
||||||
|
|
@ -111,6 +103,39 @@ class CityDocumentShortSerializer(serializers.Serializer):
|
||||||
name = serializers.CharField()
|
name = serializers.CharField()
|
||||||
|
|
||||||
|
|
||||||
|
class CountryDocumentSerializer(serializers.Serializer):
|
||||||
|
|
||||||
|
id = serializers.IntegerField()
|
||||||
|
code = serializers.CharField(allow_null=True)
|
||||||
|
svg_image = serializers.CharField()
|
||||||
|
name_translated = serializers.SerializerMethodField()
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def get_name_translated(obj):
|
||||||
|
return get_translated_value(obj.name)
|
||||||
|
|
||||||
|
|
||||||
|
class AnotherCityDocumentShortSerializer(CityDocumentShortSerializer):
|
||||||
|
|
||||||
|
country = CountryDocumentSerializer()
|
||||||
|
|
||||||
|
def to_representation(self, instance):
|
||||||
|
if instance != AttrDict(d={}) or \
|
||||||
|
(isinstance(instance, dict) and len(instance) != 0):
|
||||||
|
return super().to_representation(instance)
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
class ProductEstablishmentDocumentSerializer(serializers.Serializer):
|
||||||
|
"""Related to Product Establishment ES document serializer."""
|
||||||
|
|
||||||
|
id = serializers.IntegerField()
|
||||||
|
name = serializers.CharField()
|
||||||
|
slug = serializers.CharField()
|
||||||
|
index_name = serializers.CharField()
|
||||||
|
city = AnotherCityDocumentShortSerializer()
|
||||||
|
|
||||||
|
|
||||||
class AddressDocumentSerializer(serializers.Serializer):
|
class AddressDocumentSerializer(serializers.Serializer):
|
||||||
"""Address serializer for ES Document."""
|
"""Address serializer for ES Document."""
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -243,7 +243,7 @@ class ProductDocumentViewSet(BaseDocumentViewSet):
|
||||||
'lookups': [constants.LOOKUP_QUERY_IN],
|
'lookups': [constants.LOOKUP_QUERY_IN],
|
||||||
},
|
},
|
||||||
'country': {
|
'country': {
|
||||||
'field': 'wine_region.country.code',
|
'field': 'establishment.address.city.country.code',
|
||||||
},
|
},
|
||||||
'wine_colors_id': {
|
'wine_colors_id': {
|
||||||
'field': 'wine_colors.id',
|
'field': 'wine_colors.id',
|
||||||
|
|
|
||||||
|
|
@ -44,7 +44,7 @@ class TagCategoryFilterSet(TagsBaseFilterSet):
|
||||||
|
|
||||||
def by_product_type(self, queryset, name, value):
|
def by_product_type(self, queryset, name, value):
|
||||||
if value == product_models.ProductType.WINE:
|
if value == product_models.ProductType.WINE:
|
||||||
queryset = queryset.filter(index_name='wine-color')
|
queryset = queryset.filter(index_name='wine-color').filter(tags__products__isnull=False)
|
||||||
queryset = queryset.by_product_type(value)
|
queryset = queryset.by_product_type(value)
|
||||||
return queryset
|
return queryset
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -69,6 +69,7 @@ class ProductReviewSerializer(ReviewSerializer):
|
||||||
data.pop('reviewer_id')
|
data.pop('reviewer_id')
|
||||||
data.pop('product_id')
|
data.pop('product_id')
|
||||||
data.pop('aasm_state')
|
data.pop('aasm_state')
|
||||||
|
data.pop('establishment_id')
|
||||||
return data
|
return data
|
||||||
|
|
||||||
def create(self, validated_data):
|
def create(self, validated_data):
|
||||||
|
|
|
||||||
|
|
@ -238,6 +238,10 @@ class SVGImageMixin(models.Model):
|
||||||
validators=[svg_image_validator, ],
|
validators=[svg_image_validator, ],
|
||||||
verbose_name=_('SVG image'))
|
verbose_name=_('SVG image'))
|
||||||
|
|
||||||
|
@property
|
||||||
|
def svg_image_indexing(self):
|
||||||
|
return self.svg_image.url if self.svg_image else None
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
abstract = True
|
abstract = True
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -503,4 +503,4 @@ ESTABLISHMENT_CHOSEN_TAGS = ['gastronomic', 'en_vogue', 'terrace', 'streetfood',
|
||||||
NEWS_CHOSEN_TAGS = ['eat', 'drink', 'cook', 'style', 'international', 'event', 'partnership']
|
NEWS_CHOSEN_TAGS = ['eat', 'drink', 'cook', 'style', 'international', 'event', 'partnership']
|
||||||
INTERNATIONAL_COUNTRY_CODES = ['www', 'main', 'next']
|
INTERNATIONAL_COUNTRY_CODES = ['www', 'main', 'next']
|
||||||
|
|
||||||
#ELASTICSEARCH_DSL_AUTOSYNC = False
|
ELASTICSEARCH_DSL_AUTOSYNC = False
|
||||||
Loading…
Reference in New Issue
Block a user