Merge branch 'develop' into feature/add_tag_product
This commit is contained in:
commit
097bab4bb1
|
|
@ -6,4 +6,4 @@ from . import models
|
|||
@admin.register(models.Comment)
|
||||
class CommentModelAdmin(admin.ModelAdmin):
|
||||
"""Model admin for model Comment"""
|
||||
raw_id_fields = ('user', 'country')
|
||||
raw_id_fields = ('user',)
|
||||
|
|
|
|||
17
apps/comment/migrations/0005_remove_comment_country.py
Normal file
17
apps/comment/migrations/0005_remove_comment_country.py
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
# Generated by Django 2.2.7 on 2019-11-12 13:17
|
||||
|
||||
from django.db import migrations
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('comment', '0004_comment_old_id'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.RemoveField(
|
||||
model_name='comment',
|
||||
name='country',
|
||||
),
|
||||
]
|
||||
|
|
@ -4,10 +4,9 @@ from django.db import models
|
|||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
from account.models import User
|
||||
from translation.models import Language
|
||||
from utils.models import ProjectBaseMixin
|
||||
from utils.querysets import ContentTypeQuerySetMixin
|
||||
from translation.models import Language
|
||||
from location.models import Country
|
||||
|
||||
|
||||
class CommentQuerySet(ContentTypeQuerySetMixin):
|
||||
|
|
@ -34,7 +33,6 @@ class Comment(ProjectBaseMixin):
|
|||
text = models.TextField(verbose_name=_('Comment text'))
|
||||
mark = models.PositiveIntegerField(blank=True, null=True, default=None, verbose_name=_('Mark'))
|
||||
user = models.ForeignKey('account.User', related_name='comments', on_delete=models.CASCADE, verbose_name=_('User'))
|
||||
country = models.ForeignKey(Country, verbose_name=_('Country'), on_delete=models.SET_NULL, null=True)
|
||||
old_id = models.IntegerField(null=True, blank=True, default=None)
|
||||
|
||||
content_type = models.ForeignKey(generic.ContentType, on_delete=models.CASCADE)
|
||||
|
|
|
|||
|
|
@ -1,8 +1,7 @@
|
|||
from pprint import pprint
|
||||
|
||||
from django.db.models import Q
|
||||
|
||||
from account.transfer_data import STOP_LIST
|
||||
from account.models import User
|
||||
from establishment.models import Establishment
|
||||
from transfer.models import Comments
|
||||
from transfer.serializers.comments import CommentSerializer
|
||||
|
||||
|
|
@ -10,19 +9,15 @@ from transfer.serializers.comments import CommentSerializer
|
|||
def transfer_comments():
|
||||
# В queryset исключены объекты по условию в связанные моделях
|
||||
# см. transfer_establishment() и transfer_user()
|
||||
queryset = Comments.objects.exclude(
|
||||
Q(establishment__type='Wineyard') |
|
||||
Q(establishment__location__timezone__isnull=True) |
|
||||
Q(account__confirmed_at__isnull=True) |
|
||||
Q(account__email__in=STOP_LIST)
|
||||
).filter(
|
||||
account__isnull=False,
|
||||
mark__isnull=False
|
||||
establishments = Establishment.objects.all().values_list('old_id', flat=True)
|
||||
users = User.objects.all().values_list('old_id', flat=True)
|
||||
queryset = Comments.objects.filter(
|
||||
establishment_id__in=list(establishments),
|
||||
account_id__in=list(users),
|
||||
).only(
|
||||
'id',
|
||||
'comment',
|
||||
'mark',
|
||||
'locale',
|
||||
'establishment_id',
|
||||
'account_id',
|
||||
)
|
||||
|
|
|
|||
|
|
@ -0,0 +1,14 @@
|
|||
from django.core.management.base import BaseCommand
|
||||
from timetable.models import Timetable
|
||||
|
||||
class Command(BaseCommand):
|
||||
help = '''Add closed_at, opening_at Timetable fields'''
|
||||
|
||||
def handle(self, *args, **options):
|
||||
for tt in Timetable.objects.all():
|
||||
end = tt.dinner_end or tt.lunch_end
|
||||
start = tt.lunch_start or tt.dinner_start
|
||||
if end or start:
|
||||
tt.closed_at = end
|
||||
tt.opening_at = start
|
||||
tt.save()
|
||||
33
apps/establishment/migrations/0059_establishmentnote.py
Normal file
33
apps/establishment/migrations/0059_establishmentnote.py
Normal file
|
|
@ -0,0 +1,33 @@
|
|||
# Generated by Django 2.2.7 on 2019-11-12 10:07
|
||||
|
||||
from django.conf import settings
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
import django.utils.timezone
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
|
||||
('establishment', '0058_merge_20191106_0921'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name='EstablishmentNote',
|
||||
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')),
|
||||
('old_id', models.PositiveIntegerField(blank=True, null=True)),
|
||||
('text', models.TextField(verbose_name='text')),
|
||||
('establishment', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='establishment_notes', to='establishment.Establishment', verbose_name='establishment')),
|
||||
('user', models.ForeignKey(null=True, on_delete=django.db.models.deletion.PROTECT, related_name='establishment_notes', to=settings.AUTH_USER_MODEL, verbose_name='author')),
|
||||
],
|
||||
options={
|
||||
'verbose_name': 'product notes',
|
||||
'verbose_name_plural': 'product note',
|
||||
},
|
||||
),
|
||||
]
|
||||
|
|
@ -111,6 +111,19 @@ class EstablishmentQuerySet(models.QuerySet):
|
|||
return self.select_related('address', 'establishment_type').\
|
||||
prefetch_related('tags')
|
||||
|
||||
def with_schedule(self):
|
||||
"""Return qs with related schedule."""
|
||||
return self.prefetch_related('schedule')
|
||||
|
||||
def with_currency_related(self):
|
||||
"""Return qs with related """
|
||||
return self.prefetch_related('currency')
|
||||
|
||||
def with_extended_address_related(self):
|
||||
"""Return qs with deeply related address models."""
|
||||
return self.select_related('address__city', 'address__city__region', 'address__city__region__country',
|
||||
'address__city__country')
|
||||
|
||||
def with_extended_related(self):
|
||||
return self.select_related('establishment_type').\
|
||||
prefetch_related('establishment_subtypes', 'awards', 'schedule',
|
||||
|
|
@ -461,6 +474,11 @@ class Establishment(ProjectBaseMixin, URLImageMixin, TranslatedFieldsMixin):
|
|||
""" Used for indexing working by day """
|
||||
return [ret.weekday for ret in self.schedule.all() if ret.works_at_noon]
|
||||
|
||||
@property
|
||||
def works_at_weekday(self):
|
||||
""" Used for indexing by working whole day criteria """
|
||||
return [ret.weekday for ret in self.schedule.all()]
|
||||
|
||||
@property
|
||||
def works_evening(self):
|
||||
""" Used for indexing working by day """
|
||||
|
|
@ -520,6 +538,30 @@ class Establishment(ProjectBaseMixin, URLImageMixin, TranslatedFieldsMixin):
|
|||
return self.products.wines()
|
||||
|
||||
|
||||
class EstablishmentNoteQuerySet(models.QuerySet):
|
||||
"""QuerySet for model EstablishmentNote."""
|
||||
|
||||
|
||||
class EstablishmentNote(ProjectBaseMixin):
|
||||
"""Note model for Establishment entity."""
|
||||
old_id = models.PositiveIntegerField(null=True, blank=True)
|
||||
text = models.TextField(verbose_name=_('text'))
|
||||
establishment = models.ForeignKey(Establishment, on_delete=models.PROTECT,
|
||||
related_name='establishment_notes',
|
||||
verbose_name=_('establishment'))
|
||||
user = models.ForeignKey('account.User', on_delete=models.PROTECT,
|
||||
null=True,
|
||||
related_name='establishment_notes',
|
||||
verbose_name=_('author'))
|
||||
|
||||
objects = EstablishmentNoteQuerySet.as_manager()
|
||||
|
||||
class Meta:
|
||||
"""Meta class."""
|
||||
verbose_name_plural = _('product note')
|
||||
verbose_name = _('product notes')
|
||||
|
||||
|
||||
class Position(BaseAttributes, TranslatedFieldsMixin):
|
||||
"""Position model."""
|
||||
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ from rest_framework import serializers
|
|||
from comment import models as comment_models
|
||||
from comment.serializers import common as comment_serializers
|
||||
from establishment import models
|
||||
from location.serializers import AddressBaseSerializer, CitySerializer
|
||||
from location.serializers import AddressBaseSerializer, CitySerializer, AddressDetailSerializer
|
||||
from main.serializers import AwardSerializer, CurrencySerializer
|
||||
from tag.serializers import TagBaseSerializer
|
||||
from timetable.serialziers import ScheduleRUDSerializer
|
||||
|
|
@ -225,6 +225,19 @@ class EstablishmentBaseSerializer(ProjectModelSerializer):
|
|||
'currency'
|
||||
]
|
||||
|
||||
class EstablishmentListRetrieveSerializer(EstablishmentBaseSerializer):
|
||||
"""Establishment with city serializer."""
|
||||
|
||||
address = AddressDetailSerializer()
|
||||
schedule = ScheduleRUDSerializer(many=True, allow_null=True)
|
||||
|
||||
class Meta(EstablishmentBaseSerializer.Meta):
|
||||
"""Meta class."""
|
||||
|
||||
fields = EstablishmentBaseSerializer.Meta.fields + [
|
||||
'schedule',
|
||||
]
|
||||
|
||||
|
||||
class EstablishmentGeoSerializer(EstablishmentBaseSerializer):
|
||||
"""Serializer for Geo view."""
|
||||
|
|
@ -260,6 +273,8 @@ class EstablishmentDetailSerializer(EstablishmentBaseSerializer):
|
|||
review = ReviewShortSerializer(source='last_published_review', allow_null=True)
|
||||
employees = EstablishmentEmployeeSerializer(source='actual_establishment_employees',
|
||||
many=True)
|
||||
address = AddressDetailSerializer(read_only=True)
|
||||
|
||||
menu = MenuSerializers(source='menu_set', many=True, read_only=True)
|
||||
best_price_menu = serializers.DecimalField(max_digits=14, decimal_places=2, read_only=True)
|
||||
best_price_carte = serializers.DecimalField(max_digits=14, decimal_places=2, read_only=True)
|
||||
|
|
|
|||
|
|
@ -4,8 +4,9 @@ from django.db.models import Q, F
|
|||
|
||||
from establishment.models import Establishment
|
||||
from location.models import Address
|
||||
from transfer.models import Establishments, Dishes
|
||||
from transfer.serializers.establishment import EstablishmentSerializer
|
||||
from transfer.models import Establishments, Dishes, EstablishmentNotes
|
||||
from transfer.serializers.establishment import EstablishmentSerializer, \
|
||||
EstablishmentNoteSerializer
|
||||
from transfer.serializers.plate import PlateSerializer
|
||||
|
||||
|
||||
|
|
@ -124,10 +125,26 @@ def transfer_establishment_addresses():
|
|||
establishment.save()
|
||||
|
||||
|
||||
def transfer_establishment_note():
|
||||
errors = []
|
||||
queryset = EstablishmentNotes.objects.exclude(text__exact='') \
|
||||
.exclude(text__isnull=True) \
|
||||
.exclude(establishment_id__isnull=True)
|
||||
serialized_data = EstablishmentNoteSerializer(
|
||||
data=list(queryset.values()),
|
||||
many=True)
|
||||
if serialized_data.is_valid():
|
||||
serialized_data.save()
|
||||
else:
|
||||
for d in serialized_data.errors: errors.append(d) if d else None
|
||||
pprint(f"transfer_establishment_note errors: {errors}")
|
||||
|
||||
|
||||
data_types = {
|
||||
"establishment": [
|
||||
transfer_establishment,
|
||||
],
|
||||
"establishment_note": [transfer_establishment_note],
|
||||
"location_establishment": [
|
||||
transfer_establishment_addresses
|
||||
],
|
||||
|
|
|
|||
|
|
@ -32,7 +32,11 @@ class EstablishmentListView(EstablishmentMixinView, generics.ListAPIView):
|
|||
"""Resource for getting a list of establishments."""
|
||||
|
||||
filter_class = filters.EstablishmentFilter
|
||||
serializer_class = serializers.EstablishmentBaseSerializer
|
||||
serializer_class = serializers.EstablishmentListRetrieveSerializer
|
||||
|
||||
def get_queryset(self):
|
||||
return super().get_queryset().with_schedule()\
|
||||
.with_extended_address_related().with_currency_related()
|
||||
|
||||
|
||||
class EstablishmentRetrieveView(EstablishmentMixinView, generics.RetrieveAPIView):
|
||||
|
|
|
|||
|
|
@ -68,7 +68,7 @@ class CitySerializer(serializers.ModelSerializer):
|
|||
queryset=models.Country.objects.all(),
|
||||
write_only=True
|
||||
)
|
||||
country = CountrySerializer()
|
||||
country = CountrySerializer(read_only=True)
|
||||
|
||||
class Meta:
|
||||
model = models.City
|
||||
|
|
|
|||
18
apps/main/migrations/0034_sitefeature_nested.py
Normal file
18
apps/main/migrations/0034_sitefeature_nested.py
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
# Generated by Django 2.2.4 on 2019-11-07 14:41
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('main', '0033_auto_20191106_0744'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='sitefeature',
|
||||
name='nested',
|
||||
field=models.ManyToManyField(to='main.SiteFeature'),
|
||||
),
|
||||
]
|
||||
14
apps/main/migrations/0035_merge_20191112_1218.py
Normal file
14
apps/main/migrations/0035_merge_20191112_1218.py
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
# Generated by Django 2.2.7 on 2019-11-12 12:18
|
||||
|
||||
from django.db import migrations
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('main', '0034_sitefeature_nested'),
|
||||
('main', '0034_auto_20191112_0104'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
]
|
||||
|
|
@ -151,6 +151,7 @@ class SiteFeature(ProjectBaseMixin):
|
|||
feature = models.ForeignKey(Feature, on_delete=models.PROTECT)
|
||||
published = models.BooleanField(default=False, verbose_name=_('Published'))
|
||||
main = models.BooleanField(default=False, verbose_name=_('Main'))
|
||||
nested = models.ManyToManyField('self', symmetrical=False)
|
||||
|
||||
objects = SiteFeatureQuerySet.as_manager()
|
||||
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ from rest_framework import serializers
|
|||
from advertisement.serializers.web import AdvertisementSerializer
|
||||
from location.serializers import CountrySerializer
|
||||
from main import models
|
||||
from utils.serializers import ProjectModelSerializer, TranslatedField
|
||||
from utils.serializers import ProjectModelSerializer, TranslatedField, RecursiveFieldSerializer
|
||||
|
||||
|
||||
class FeatureSerializer(serializers.ModelSerializer):
|
||||
|
|
@ -27,6 +27,7 @@ class SiteFeatureSerializer(serializers.ModelSerializer):
|
|||
priority = serializers.IntegerField(source='feature.priority')
|
||||
route = serializers.CharField(source='feature.route.page_name')
|
||||
source = serializers.IntegerField(source='feature.source')
|
||||
nested = RecursiveFieldSerializer(many=True, allow_null=True)
|
||||
|
||||
class Meta:
|
||||
"""Meta class."""
|
||||
|
|
@ -36,8 +37,9 @@ class SiteFeatureSerializer(serializers.ModelSerializer):
|
|||
'slug',
|
||||
'priority',
|
||||
'route',
|
||||
'source'
|
||||
)
|
||||
'source',
|
||||
'nested',
|
||||
)
|
||||
|
||||
|
||||
class CurrencySerializer(ProjectModelSerializer):
|
||||
|
|
|
|||
|
|
@ -1,14 +1,21 @@
|
|||
"""Filters from application News"""
|
||||
import django_filters
|
||||
from django_filters import rest_framework as filters
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
from news import models
|
||||
|
||||
|
||||
class NewsListFilterSet(django_filters.FilterSet):
|
||||
class NewsListFilterSet(filters.FilterSet):
|
||||
"""FilterSet for News list"""
|
||||
|
||||
is_highlighted = django_filters.BooleanFilter()
|
||||
title = django_filters.CharFilter(method='by_title')
|
||||
is_highlighted = filters.BooleanFilter()
|
||||
title = filters.CharFilter(method='by_title')
|
||||
tag_group = filters.ChoiceFilter(
|
||||
choices=(
|
||||
(models.News.RECIPES_TAG_VALUE, _('Recipes')),
|
||||
),
|
||||
method='by_tag_group'
|
||||
)
|
||||
|
||||
class Meta:
|
||||
"""Meta class"""
|
||||
|
|
@ -16,8 +23,14 @@ class NewsListFilterSet(django_filters.FilterSet):
|
|||
fields = (
|
||||
'title',
|
||||
'is_highlighted',
|
||||
'tag_group',
|
||||
)
|
||||
|
||||
def by_tag_group(self, queryset, name, value):
|
||||
if value == models.News.RECIPES_TAG_VALUE:
|
||||
queryset = queryset.recipe_news()
|
||||
return queryset
|
||||
|
||||
def by_title(self, queryset, name, value):
|
||||
"""Crappy search by title according to locale"""
|
||||
if value:
|
||||
|
|
|
|||
|
|
@ -53,6 +53,10 @@ class NewsQuerySet(TranslationQuerysetMixin):
|
|||
"""Filter collection by country code."""
|
||||
return self.filter(country__code=code)
|
||||
|
||||
def recipe_news(self):
|
||||
"""Returns news with tag 'cook' qs."""
|
||||
return self.filter(tags__value=News.RECIPES_TAG_VALUE)
|
||||
|
||||
def published(self):
|
||||
"""Return only published news"""
|
||||
now = timezone.now()
|
||||
|
|
@ -127,6 +131,8 @@ class News(BaseAttributes, TranslatedFieldsMixin):
|
|||
(PUBLISHED_EXCLUSIVE, _('Published exclusive')),
|
||||
)
|
||||
|
||||
RECIPES_TAG_VALUE = 'cook'
|
||||
|
||||
old_id = models.PositiveIntegerField(_('old id'), blank=True, null=True, default=None)
|
||||
news_type = models.ForeignKey(NewsType, on_delete=models.PROTECT,
|
||||
verbose_name=_('news type'))
|
||||
|
|
|
|||
9
apps/news/urls/common.py
Normal file
9
apps/news/urls/common.py
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
from django.urls import path
|
||||
from news import views
|
||||
|
||||
common_urlpatterns = [
|
||||
path('', views.NewsListView.as_view(), name='list'),
|
||||
path('types/', views.NewsTypeListView.as_view(), name='type'),
|
||||
path('slug/<slug:slug>/', views.NewsDetailView.as_view(), name='rud'),
|
||||
path('slug/<slug:slug>/favorites/', views.NewsFavoritesCreateDestroyView.as_view(), name='create-destroy-favorites')
|
||||
]
|
||||
8
apps/news/urls/mobile.py
Normal file
8
apps/news/urls/mobile.py
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
"""News app urlconf."""
|
||||
from news.urls.common import common_urlpatterns
|
||||
|
||||
app_name = 'news'
|
||||
|
||||
urlpatterns = []
|
||||
|
||||
urlpatterns.extend(common_urlpatterns)
|
||||
|
|
@ -1,12 +1,8 @@
|
|||
"""News app urlconf."""
|
||||
from django.urls import path
|
||||
from news import views
|
||||
from news.urls.common import common_urlpatterns
|
||||
|
||||
app_name = 'news'
|
||||
|
||||
urlpatterns = [
|
||||
path('', views.NewsListView.as_view(), name='list'),
|
||||
path('types/', views.NewsTypeListView.as_view(), name='type'),
|
||||
path('slug/<slug:slug>/', views.NewsDetailView.as_view(), name='rud'),
|
||||
path('slug/<slug:slug>/favorites/', views.NewsFavoritesCreateDestroyView.as_view(), name='create-destroy-favorites')
|
||||
]
|
||||
urlpatterns = []
|
||||
|
||||
urlpatterns.extend(common_urlpatterns)
|
||||
|
|
|
|||
37
apps/product/migrations/0012_auto_20191112_1007.py
Normal file
37
apps/product/migrations/0012_auto_20191112_1007.py
Normal file
|
|
@ -0,0 +1,37 @@
|
|||
# Generated by Django 2.2.7 on 2019-11-12 10:07
|
||||
|
||||
from django.conf import settings
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
import django.utils.timezone
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
|
||||
('product', '0011_product_win_import_id'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.RemoveField(
|
||||
model_name='product',
|
||||
name='win_import_id',
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='ProductNote',
|
||||
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')),
|
||||
('old_id', models.PositiveIntegerField(blank=True, null=True)),
|
||||
('text', models.TextField(verbose_name='text')),
|
||||
('product', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='product_notes', to='product.Product', verbose_name='product')),
|
||||
('user', models.ForeignKey(null=True, on_delete=django.db.models.deletion.PROTECT, related_name='product_notes', to=settings.AUTH_USER_MODEL, verbose_name='author')),
|
||||
],
|
||||
options={
|
||||
'verbose_name': 'product notes',
|
||||
'verbose_name_plural': 'product note',
|
||||
},
|
||||
),
|
||||
]
|
||||
|
|
@ -193,9 +193,6 @@ class Product(TranslatedFieldsMixin, BaseAttributes):
|
|||
validators=[MinValueValidator(EARLIEST_VINTAGE_YEAR),
|
||||
MaxValueValidator(LATEST_VINTAGE_YEAR)])
|
||||
gallery = models.ManyToManyField('gallery.Image', through='ProductGallery')
|
||||
win_import_id = models.CharField(max_length=255,
|
||||
blank=True, null=True, default=None,
|
||||
help_text=_('attribute from legacy db'))
|
||||
reviews = generic.GenericRelation(to='review.Review')
|
||||
comments = generic.GenericRelation(to='comment.Comment')
|
||||
awards = generic.GenericRelation(to='main.Award', related_query_name='product')
|
||||
|
|
@ -409,3 +406,27 @@ class ProductClassification(models.Model):
|
|||
"""Meta class."""
|
||||
verbose_name = _('product classification')
|
||||
verbose_name_plural = _('product classifications')
|
||||
|
||||
|
||||
class ProductNoteQuerySet(models.QuerySet):
|
||||
"""QuerySet for model ProductNote."""
|
||||
|
||||
|
||||
class ProductNote(ProjectBaseMixin):
|
||||
"""Note model for Product entity."""
|
||||
old_id = models.PositiveIntegerField(null=True, blank=True)
|
||||
text = models.TextField(verbose_name=_('text'))
|
||||
product = models.ForeignKey(Product, on_delete=models.PROTECT,
|
||||
related_name='product_notes',
|
||||
verbose_name=_('product'))
|
||||
user = models.ForeignKey('account.User', on_delete=models.PROTECT,
|
||||
null=True,
|
||||
related_name='product_notes',
|
||||
verbose_name=_('author'))
|
||||
|
||||
objects = ProductNoteQuerySet.as_manager()
|
||||
|
||||
class Meta:
|
||||
"""Meta class."""
|
||||
verbose_name_plural = _('product note')
|
||||
verbose_name = _('product notes')
|
||||
|
|
|
|||
|
|
@ -76,7 +76,7 @@ class ProductBaseSerializer(serializers.ModelSerializer):
|
|||
subtypes = ProductSubTypeBaseSerializer(many=True)
|
||||
establishment = EstablishmentShortSerializer()
|
||||
tags = TagBaseSerializer(source='related_tags', many=True)
|
||||
preview_image_url = serializers.ImageField(source='preview_main_image_url', allow_null=True)
|
||||
preview_image_url = serializers.URLField(source='preview_main_image_url', allow_null=True)
|
||||
|
||||
class Meta:
|
||||
"""Meta class."""
|
||||
|
|
|
|||
|
|
@ -101,6 +101,7 @@ def transfer_wine_classifications():
|
|||
|
||||
|
||||
def transfer_product():
|
||||
errors = []
|
||||
queryset = transfer_models.Products.objects.all()
|
||||
serialized_data = product_serializers.ProductSerializer(
|
||||
data=list(queryset.values()),
|
||||
|
|
@ -108,26 +109,25 @@ def transfer_product():
|
|||
if serialized_data.is_valid():
|
||||
serialized_data.save()
|
||||
else:
|
||||
errors = []
|
||||
for d in serialized_data.errors: errors.append(d) if d else None
|
||||
pprint(f"transfer_product errors: {errors}")
|
||||
|
||||
|
||||
def transfer_product_description():
|
||||
pass
|
||||
# queryset = transfer_models.Products.objects.all()
|
||||
# serialized_data = product_serializers.ProductSerializer(
|
||||
# data=list(queryset.values()),
|
||||
# many=True)
|
||||
# if serialized_data.is_valid():
|
||||
# serialized_data.save()
|
||||
# else:
|
||||
# errors = []
|
||||
# for d in serialized_data.errors: errors.append(d) if d else None
|
||||
# pprint(f"transfer_product errors: {errors}")
|
||||
def transfer_product_note():
|
||||
errors = []
|
||||
queryset = transfer_models.ProductNotes.objects.exclude(text='')
|
||||
serialized_data = product_serializers.ProductNoteSerializer(
|
||||
data=list(queryset.values()),
|
||||
many=True)
|
||||
if serialized_data.is_valid():
|
||||
serialized_data.save()
|
||||
else:
|
||||
for d in serialized_data.errors: errors.append(d) if d else None
|
||||
pprint(f"transfer_product_note errors: {errors}")
|
||||
|
||||
|
||||
def transfer_plate():
|
||||
errors = []
|
||||
queryset = transfer_models.Merchandise.objects.all()
|
||||
serialized_data = product_serializers.PlateSerializer(
|
||||
data=list(queryset.values()),
|
||||
|
|
@ -135,12 +135,12 @@ def transfer_plate():
|
|||
if serialized_data.is_valid():
|
||||
serialized_data.save()
|
||||
else:
|
||||
errors = []
|
||||
for d in serialized_data.errors: errors.append(d) if d else None
|
||||
pprint(f"transfer_plates errors: {errors}")
|
||||
|
||||
|
||||
def transfer_plate_image():
|
||||
errors = []
|
||||
queryset = transfer_models.Merchandise.objects.all()
|
||||
serialized_data = product_serializers.PlateImageSerializer(
|
||||
data=list(queryset.values()),
|
||||
|
|
@ -148,7 +148,6 @@ def transfer_plate_image():
|
|||
if serialized_data.is_valid():
|
||||
serialized_data.save()
|
||||
else:
|
||||
errors = []
|
||||
for d in serialized_data.errors: errors.append(d) if d else None
|
||||
pprint(f"transfer_plates_images errors: {errors}")
|
||||
|
||||
|
|
@ -166,9 +165,9 @@ data_types = {
|
|||
"product": [
|
||||
transfer_product,
|
||||
],
|
||||
# "product_description": [
|
||||
# transfer_product_description,
|
||||
# ],
|
||||
"product_note": [
|
||||
transfer_product_note,
|
||||
],
|
||||
"souvenir": [
|
||||
transfer_plate,
|
||||
transfer_plate_image,
|
||||
|
|
|
|||
|
|
@ -37,6 +37,9 @@ class EstablishmentDocument(Document):
|
|||
works_noon = fields.ListField(fields.IntegerField(
|
||||
attr='works_noon'
|
||||
))
|
||||
works_at_weekday = fields.ListField(fields.IntegerField(
|
||||
attr='works_at_weekday'
|
||||
))
|
||||
works_now = fields.BooleanField(attr='works_now')
|
||||
tags = fields.ObjectField(
|
||||
properties={
|
||||
|
|
@ -65,7 +68,6 @@ class EstablishmentDocument(Document):
|
|||
'number': fields.IntegerField(),
|
||||
'postal_code': fields.KeywordField(),
|
||||
'coordinates': fields.GeoPointField(attr='location_field_indexing'),
|
||||
# todo: remove if not used
|
||||
'city': fields.ObjectField(
|
||||
properties={
|
||||
'id': fields.IntegerField(),
|
||||
|
|
|
|||
|
|
@ -19,10 +19,19 @@ class TagsDocumentSerializer(serializers.Serializer):
|
|||
return get_translated_value(obj.label)
|
||||
|
||||
|
||||
class CityDocumentShortSerializer(serializers.Serializer):
|
||||
"""City serializer for ES Document,"""
|
||||
|
||||
id = serializers.IntegerField()
|
||||
code = serializers.CharField(allow_null=True)
|
||||
name = serializers.CharField()
|
||||
|
||||
|
||||
class AddressDocumentSerializer(serializers.Serializer):
|
||||
"""Address serializer for ES Document."""
|
||||
|
||||
id = serializers.IntegerField()
|
||||
city = CityDocumentShortSerializer()
|
||||
street_name_1 = serializers.CharField()
|
||||
street_name_2 = serializers.CharField()
|
||||
number = serializers.IntegerField()
|
||||
|
|
@ -108,6 +117,7 @@ class EstablishmentDocumentSerializer(DocumentSerializer):
|
|||
'schedule',
|
||||
'works_noon',
|
||||
'works_evening',
|
||||
'works_at_weekday',
|
||||
# 'works_now',
|
||||
# 'collections',
|
||||
# 'establishment_type',
|
||||
|
|
|
|||
|
|
@ -2,13 +2,226 @@
|
|||
from django_elasticsearch_dsl import fields
|
||||
from utils.models import get_current_locale, get_default_locale
|
||||
|
||||
ALL_LOCALES_LIST = [
|
||||
'af-ZA',
|
||||
'am-ET',
|
||||
'ar-AE',
|
||||
'ar-BH',
|
||||
'ar-DZ',
|
||||
'ar-EG',
|
||||
'ar-IQ',
|
||||
'ar-JO',
|
||||
'ar-KW',
|
||||
'ar-LB',
|
||||
'ar-LY',
|
||||
'ar-MA',
|
||||
'arn-CL',
|
||||
'ar-OM',
|
||||
'ar-QA',
|
||||
'ar-SA',
|
||||
'ar-SY',
|
||||
'ar-TN',
|
||||
'ar-YE',
|
||||
'as-IN',
|
||||
'az-Cyrl-AZ',
|
||||
'az-Latn-AZ',
|
||||
'ba-RU',
|
||||
'be-BY',
|
||||
'bg-BG',
|
||||
'bn-BD',
|
||||
'bn-IN',
|
||||
'bo-CN',
|
||||
'br-FR',
|
||||
'bs-Cyrl-BA',
|
||||
'bs-Latn-BA',
|
||||
'ca-ES',
|
||||
'co-FR',
|
||||
'cs-CZ',
|
||||
'cy-GB',
|
||||
'da-DK',
|
||||
'de-AT',
|
||||
'de-CH',
|
||||
'de-DE',
|
||||
'de-LI',
|
||||
'de-LU',
|
||||
'dsb-DE',
|
||||
'dv-MV',
|
||||
'el-GR',
|
||||
'en-029',
|
||||
'en-AU',
|
||||
'en-BZ',
|
||||
'en-CA',
|
||||
'en-GB',
|
||||
'en-IE',
|
||||
'en-IN',
|
||||
'en-JM',
|
||||
'en-MY',
|
||||
'en-NZ',
|
||||
'en-PH',
|
||||
'en-SG',
|
||||
'en-TT',
|
||||
'en-US',
|
||||
'en-ZA',
|
||||
'en-ZW',
|
||||
'es-AR',
|
||||
'es-BO',
|
||||
'es-CL',
|
||||
'es-CO',
|
||||
'es-CR',
|
||||
'es-DO',
|
||||
'es-EC',
|
||||
'es-ES',
|
||||
'es-GT',
|
||||
'es-HN',
|
||||
'es-MX',
|
||||
'es-NI',
|
||||
'es-PA',
|
||||
'es-PE',
|
||||
'es-PR',
|
||||
'es-PY',
|
||||
'es-SV',
|
||||
'es-US',
|
||||
'es-UY',
|
||||
'es-VE',
|
||||
'et-EE',
|
||||
'eu-ES',
|
||||
'fa-IR',
|
||||
'fi-FI',
|
||||
'fil-PH',
|
||||
'fo-FO',
|
||||
'fr-BE',
|
||||
'fr-CA',
|
||||
'fr-CH',
|
||||
'fr-FR',
|
||||
'fr-LU',
|
||||
'fr-MC',
|
||||
'fy-NL',
|
||||
'ga-IE',
|
||||
'gd-GB',
|
||||
'gl-ES',
|
||||
'gsw-FR',
|
||||
'gu-IN',
|
||||
'ha-Latn-NG',
|
||||
'he-IL',
|
||||
'hi-IN',
|
||||
'hr-BA',
|
||||
'hr-HR',
|
||||
'hsb-DE',
|
||||
'hu-HU',
|
||||
'hy-AM',
|
||||
'id-ID',
|
||||
'ig-NG',
|
||||
'ii-CN',
|
||||
'is-IS',
|
||||
'it-CH',
|
||||
'it-IT',
|
||||
'iu-Cans-CA',
|
||||
'iu-Latn-CA',
|
||||
'ja-JP',
|
||||
'ka-GE',
|
||||
'kk-KZ',
|
||||
'kl-GL',
|
||||
'km-KH',
|
||||
'kn-IN',
|
||||
'kok-IN',
|
||||
'ko-KR',
|
||||
'ky-KG',
|
||||
'lb-LU',
|
||||
'lo-LA',
|
||||
'lt-LT',
|
||||
'lv-LV',
|
||||
'mi-NZ',
|
||||
'mk-MK',
|
||||
'ml-IN',
|
||||
'mn-MN',
|
||||
'mn-Mong-CN',
|
||||
'moh-CA',
|
||||
'mr-IN',
|
||||
'ms-BN',
|
||||
'ms-MY',
|
||||
'mt-MT',
|
||||
'nb-NO',
|
||||
'ne-NP',
|
||||
'nl-BE',
|
||||
'nl-NL',
|
||||
'nn-NO',
|
||||
'nso-ZA',
|
||||
'oc-FR',
|
||||
'or-IN',
|
||||
'pa-IN',
|
||||
'pl-PL',
|
||||
'prs-AF',
|
||||
'ps-AF',
|
||||
'pt-BR',
|
||||
'pt-PT',
|
||||
'qut-GT',
|
||||
'quz-BO',
|
||||
'quz-EC',
|
||||
'quz-PE',
|
||||
'rm-CH',
|
||||
'ro-RO',
|
||||
'ru-RU',
|
||||
'rw-RW',
|
||||
'sah-RU',
|
||||
'sa-IN',
|
||||
'se-FI',
|
||||
'se-NO',
|
||||
'se-SE',
|
||||
'si-LK',
|
||||
'sk-SK',
|
||||
'sl-SI',
|
||||
'sma-NO',
|
||||
'sma-SE',
|
||||
'smj-NO',
|
||||
'smj-SE',
|
||||
'smn-FI',
|
||||
'sms-FI',
|
||||
'sq-AL',
|
||||
'sr-Cyrl-BA',
|
||||
'sr-Cyrl-CS',
|
||||
'sr-Cyrl-ME',
|
||||
'sr-Cyrl-RS',
|
||||
'sr-Latn-BA',
|
||||
'sr-Latn-CS',
|
||||
'sr-Latn-ME',
|
||||
'sr-Latn-RS',
|
||||
'sv-FI',
|
||||
'sv-SE',
|
||||
'sw-KE',
|
||||
'syr-SY',
|
||||
'ta-IN',
|
||||
'te-IN',
|
||||
'tg-Cyrl-TJ',
|
||||
'th-TH',
|
||||
'tk-TM',
|
||||
'tn-ZA',
|
||||
'tr-TR',
|
||||
'tt-RU',
|
||||
'tzm-Latn-DZ',
|
||||
'ug-CN',
|
||||
'uk-UA',
|
||||
'ur-PK',
|
||||
'uz-Cyrl-UZ',
|
||||
'uz-Latn-UZ',
|
||||
'vi-VN',
|
||||
'wo-SN',
|
||||
'xh-ZA',
|
||||
'yo-NG',
|
||||
'zh-CN',
|
||||
'zh-HK',
|
||||
'zh-MO',
|
||||
'zh-SG',
|
||||
'zh-TW',
|
||||
'zu-ZA',
|
||||
]
|
||||
|
||||
# object field properties
|
||||
OBJECT_FIELD_PROPERTIES = {
|
||||
OBJECT_FIELD_PROPERTIES = {locale: fields.TextField() for locale in ALL_LOCALES_LIST}
|
||||
OBJECT_FIELD_PROPERTIES.update({
|
||||
'en-GB': fields.TextField(analyzer='english'),
|
||||
'ru-RU': fields.TextField(analyzer='russian'),
|
||||
'fr-FR': fields.TextField(analyzer='french'),
|
||||
}
|
||||
'fr-FR': fields.TextField(analyzer='french')
|
||||
})
|
||||
|
||||
|
||||
# todo: refactor serializer
|
||||
|
|
@ -17,10 +230,14 @@ def get_translated_value(value):
|
|||
return None
|
||||
elif not isinstance(value, dict):
|
||||
field_dict = value.to_dict()
|
||||
elif isinstance(value, dict):
|
||||
else:
|
||||
field_dict = value
|
||||
value = field_dict.get(get_current_locale())
|
||||
field_dict = {k: v for k, v in field_dict.items() if v is not None}
|
||||
result = field_dict.get(get_current_locale(), None)
|
||||
# fallback
|
||||
if value is None:
|
||||
value = field_dict.get(get_default_locale())
|
||||
return value
|
||||
if result is None:
|
||||
result = field_dict.get(get_default_locale(), None)
|
||||
if result is None:
|
||||
values = list(field_dict.values())
|
||||
result = values[0] if values else None
|
||||
return result
|
||||
|
|
|
|||
|
|
@ -156,6 +156,12 @@ class EstablishmentDocumentViewSet(BaseDocumentViewSet):
|
|||
constants.LOOKUP_QUERY_IN,
|
||||
],
|
||||
},
|
||||
'works_at_weekday': {
|
||||
'field': 'works_at_weekday',
|
||||
'lookups': [
|
||||
constants.LOOKUP_QUERY_IN,
|
||||
],
|
||||
},
|
||||
'works_evening': {
|
||||
'field': 'works_evening',
|
||||
'lookups': [
|
||||
|
|
|
|||
|
|
@ -46,7 +46,7 @@ class Command(BaseCommand):
|
|||
'en-GB': key_value.key_name,
|
||||
'fr-FR': key_value.key_name,
|
||||
'ru-RU': key_value.key_name,
|
||||
},
|
||||
}
|
||||
tag_category.value_type = key_value.value_type
|
||||
tag_category.save()
|
||||
est_type.tag_categories.add(
|
||||
|
|
|
|||
|
|
@ -42,9 +42,7 @@ class TagBackOfficeSerializer(TagBaseSerializer):
|
|||
class TagCategoryBaseSerializer(serializers.ModelSerializer):
|
||||
"""Serializer for model TagCategory."""
|
||||
|
||||
# todo: refactor this
|
||||
# label_translated = TranslatedField()
|
||||
label_translated = serializers.CharField(source='index_name', read_only=True, allow_null=True)
|
||||
label_translated = TranslatedField()
|
||||
tags = TagBaseSerializer(many=True, read_only=True)
|
||||
|
||||
class Meta:
|
||||
|
|
|
|||
|
|
@ -66,6 +66,7 @@ card = {
|
|||
"fields": {
|
||||
"Schedules": {
|
||||
# нет аналогов для weekday, opening_at, closed_at
|
||||
# upd: запустить команду add_closed_at_timetable. она заполнит opening_at, closed_at
|
||||
"lunch_start": "lunch_start",
|
||||
"lunch_end": "lunch_end",
|
||||
"diner_start": "diner_start",
|
||||
|
|
|
|||
|
|
@ -32,8 +32,9 @@ class Command(BaseCommand):
|
|||
'inquiries', # №6 - перенос запросов оценок
|
||||
'wine_characteristics',
|
||||
'product',
|
||||
'product_description',
|
||||
'product_note',
|
||||
'souvenir',
|
||||
'establishment_note',
|
||||
]
|
||||
|
||||
def handle(self, *args, **options):
|
||||
|
|
|
|||
|
|
@ -447,6 +447,18 @@ class Establishments(MigrateMixin):
|
|||
db_table = 'establishments'
|
||||
|
||||
|
||||
class EstablishmentNotes(MigrateMixin):
|
||||
using = 'legacy'
|
||||
|
||||
establishment_id = models.IntegerField(null=True, blank=True)
|
||||
account_id = models.IntegerField(null=True, blank=True)
|
||||
text = models.TextField(null=True)
|
||||
|
||||
class Meta:
|
||||
managed = False
|
||||
db_table = 'notes'
|
||||
|
||||
|
||||
class Descriptions(MigrateMixin):
|
||||
using = 'legacy'
|
||||
|
||||
|
|
@ -973,7 +985,7 @@ class Products(MigrateMixin):
|
|||
class ProductNotes(MigrateMixin):
|
||||
using = 'legacy'
|
||||
|
||||
product_id = models.ForeignKey(Products, on_delete=models.DO_NOTHING)
|
||||
product_id = models.IntegerField(null=True, blank=True)
|
||||
text = models.CharField(max_length=255)
|
||||
win_import_id = models.CharField(max_length=255)
|
||||
|
||||
|
|
|
|||
|
|
@ -1,14 +1,13 @@
|
|||
from rest_framework import serializers
|
||||
|
||||
from comment.models import Comment, User
|
||||
from establishment.models import Establishment
|
||||
from location.models import Country
|
||||
|
||||
|
||||
class CommentSerializer(serializers.Serializer):
|
||||
id = serializers.IntegerField()
|
||||
comment = serializers.CharField()
|
||||
mark = serializers.DecimalField(max_digits=4, decimal_places=2)
|
||||
locale = serializers.CharField()
|
||||
mark = serializers.DecimalField(max_digits=4, decimal_places=2, allow_null=True)
|
||||
account_id = serializers.IntegerField()
|
||||
establishment_id = serializers.CharField()
|
||||
|
||||
|
|
@ -16,14 +15,12 @@ class CommentSerializer(serializers.Serializer):
|
|||
data.update({
|
||||
'old_id': data.pop('id'),
|
||||
'text': data.pop('comment'),
|
||||
'mark': data['mark'] * -1 if data['mark'] < 0 else data['mark'],
|
||||
'mark': self.get_mark(data),
|
||||
'content_object': self.get_content_object(data),
|
||||
'user': self.get_account(data),
|
||||
'country': self.get_country(data),
|
||||
})
|
||||
data.pop('establishment_id')
|
||||
data.pop('account_id')
|
||||
data.pop('locale')
|
||||
return data
|
||||
|
||||
def create(self, validated_data):
|
||||
|
|
@ -47,10 +44,7 @@ class CommentSerializer(serializers.Serializer):
|
|||
return user
|
||||
|
||||
@staticmethod
|
||||
def get_country(data):
|
||||
locale = data['locale']
|
||||
country_code = locale[:locale.index("-")] if len(locale) > 2 else locale
|
||||
country = Country.objects.filter(code=country_code).first()
|
||||
if not country:
|
||||
raise ValueError(f"Country not found with code {country_code}")
|
||||
return country
|
||||
def get_mark(data):
|
||||
if not data['mark']:
|
||||
return None
|
||||
return data['mark'] * -1 if data['mark'] < 0 else data['mark']
|
||||
|
|
|
|||
|
|
@ -1,16 +1,17 @@
|
|||
from django.conf import settings
|
||||
from django.core.exceptions import MultipleObjectsReturned, ValidationError
|
||||
from django.db import transaction
|
||||
from django.utils.text import slugify
|
||||
from rest_framework import serializers
|
||||
|
||||
from establishment.models import Establishment, ContactEmail, ContactPhone, EstablishmentType, \
|
||||
EstablishmentSubType
|
||||
from account.models import User
|
||||
from establishment.models import Establishment, ContactEmail, ContactPhone, \
|
||||
EstablishmentType, EstablishmentSubType, EstablishmentNote
|
||||
from location.models import Address
|
||||
from timetable.models import Timetable
|
||||
from utils.legacy_parser import parse_legacy_schedule_content
|
||||
from utils.serializers import TimeZoneChoiceField
|
||||
from utils.slug_generator import generate_unique_slug
|
||||
from django.utils.text import slugify
|
||||
|
||||
|
||||
class EstablishmentSerializer(serializers.ModelSerializer):
|
||||
|
|
@ -173,3 +174,45 @@ class EstablishmentSerializer(serializers.ModelSerializer):
|
|||
index_name=slugify(subtype_name),
|
||||
establishment_type_id=establishment_type_id)
|
||||
return subtype
|
||||
|
||||
|
||||
class EstablishmentNoteSerializer(serializers.ModelSerializer):
|
||||
|
||||
id = serializers.IntegerField()
|
||||
establishment_id = serializers.IntegerField()
|
||||
account_id = serializers.IntegerField(allow_null=True)
|
||||
text = serializers.CharField(allow_blank=True, allow_null=True)
|
||||
|
||||
class Meta:
|
||||
model = EstablishmentNote
|
||||
fields = (
|
||||
'id',
|
||||
'establishment_id',
|
||||
'account_id',
|
||||
'text',
|
||||
)
|
||||
|
||||
def validate(self, attrs):
|
||||
attrs['old_id'] = attrs['id']
|
||||
attrs['establishment'] = self.get_establishment(attrs.pop('establishment_id'))
|
||||
attrs['user'] = self.get_user(attrs.pop('account_id'))
|
||||
return attrs
|
||||
|
||||
def create(self, validated_data):
|
||||
qs = self.Meta.model.objects.filter(**validated_data)
|
||||
establishment = validated_data.get('establishment')
|
||||
|
||||
if not qs.exists() and establishment:
|
||||
obj = super().create(validated_data)
|
||||
return obj
|
||||
|
||||
def get_establishment(self, old_id):
|
||||
if old_id:
|
||||
qs = Establishment.objects.filter(old_id=old_id)
|
||||
if qs.exists():
|
||||
return qs.first()
|
||||
|
||||
def get_user(self, old_id):
|
||||
qs = User.objects.exclude(old_id__isnull=True).filter(old_id=old_id)
|
||||
if qs.exists():
|
||||
return qs.first()
|
||||
|
|
|
|||
|
|
@ -541,3 +541,36 @@ class PlateImageSerializer(serializers.ModelSerializer):
|
|||
product_qs = models.Product.objects.filter(old_id=product_id)
|
||||
if product_qs.exists():
|
||||
return product_qs.first()
|
||||
|
||||
|
||||
class ProductNoteSerializer(serializers.ModelSerializer):
|
||||
|
||||
id = serializers.IntegerField()
|
||||
product_id = serializers.IntegerField()
|
||||
text = serializers.CharField(allow_blank=True)
|
||||
|
||||
class Meta:
|
||||
model = models.ProductNote
|
||||
fields = (
|
||||
'id',
|
||||
'product_id',
|
||||
'text',
|
||||
)
|
||||
|
||||
def validate(self, attrs):
|
||||
attrs['old_id'] = attrs['id']
|
||||
attrs['product'] = self.get_product(attrs.pop('product_id'))
|
||||
return attrs
|
||||
|
||||
def create(self, validated_data):
|
||||
qs = self.Meta.model.objects.filter(**validated_data)
|
||||
product = validated_data.get('product')
|
||||
|
||||
if not qs.exists() and product:
|
||||
return super().create(validated_data)
|
||||
|
||||
def get_product(self, old_id):
|
||||
if old_id:
|
||||
qs = models.Product.objects.filter(old_id=old_id)
|
||||
if qs.exists():
|
||||
return qs.first()
|
||||
|
|
|
|||
|
|
@ -98,3 +98,9 @@ class FavoritesCreateSerializer(serializers.ModelSerializer):
|
|||
@property
|
||||
def slug(self):
|
||||
return self.request.parser_context.get('kwargs').get('slug')
|
||||
|
||||
|
||||
class RecursiveFieldSerializer(serializers.Serializer):
|
||||
def to_representation(self, value):
|
||||
serializer = self.parent.parent.__class__(value, context=self.context)
|
||||
return serializer.data
|
||||
|
|
|
|||
|
|
@ -12,6 +12,6 @@ urlpatterns = [
|
|||
# path('advertisement/', include('advertisement.urls.web')),
|
||||
# path('collection/', include('collection.urls.web')),
|
||||
# path('establishments/', include('establishment.urls.web')),
|
||||
# path('news/', include('news.urls.web')),
|
||||
path('news/', include('news.urls.mobile')),
|
||||
# path('partner/', include('partner.urls.web')),
|
||||
]
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user