refactor tags

This commit is contained in:
evgeniy-st 2019-10-15 17:17:03 +03:00
parent 1764cfc08b
commit 60cdec99e0
19 changed files with 494 additions and 323 deletions

View File

@ -80,17 +80,17 @@ class MenuAdmin(admin.ModelAdmin):
category_translated.short_description = _('category') category_translated.short_description = _('category')
#
@admin.register(models.EstablishmentTypeTagCategory) # @admin.register(models.EstablishmentTypeTagCategory)
class EstablishmentTypeTagCategoryAdmin(admin.ModelAdmin): # class EstablishmentTypeTagCategoryAdmin(admin.ModelAdmin):
"""EstablishmentTypeTagCategory admin.""" # """EstablishmentTypeTagCategory admin."""
#
#
@admin.register(models.EstablishmentSubTypeTagCategory) # @admin.register(models.EstablishmentSubTypeTagCategory)
class EstablishmentSubTypeTagCategoryAdmin(admin.ModelAdmin): # class EstablishmentSubTypeTagCategoryAdmin(admin.ModelAdmin):
"""EstablishmentTypeTagCategory admin.""" # """EstablishmentTypeTagCategory admin."""
#
#
@admin.register(models.EstablishmentTag) # @admin.register(models.EstablishmentTag)
class EstablishmentTagAdmin(admin.ModelAdmin): # class EstablishmentTagAdmin(admin.ModelAdmin):
"""EstablishmentTag admin.""" # """EstablishmentTag admin."""

View File

@ -0,0 +1,54 @@
# Generated by Django 2.2.4 on 2019-10-15 14:04
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('tag', '0002_auto_20191009_1408'),
('establishment', '0036_auto_20191011_1356'),
]
operations = [
migrations.RemoveField(
model_name='establishmenttag',
name='establishment',
),
migrations.RemoveField(
model_name='establishmenttag',
name='tag',
),
migrations.RemoveField(
model_name='establishmenttypetagcategory',
name='establishment_type',
),
migrations.RemoveField(
model_name='establishmenttypetagcategory',
name='tag_category',
),
migrations.AddField(
model_name='establishment',
name='tags',
field=models.ManyToManyField(related_name='establishments', to='tag.Tag', verbose_name='Tag'),
),
migrations.AddField(
model_name='establishmentsubtype',
name='tag_categories',
field=models.ManyToManyField(related_name='establishment_subtypes', to='tag.TagCategory', verbose_name='Tag'),
),
migrations.AddField(
model_name='establishmenttype',
name='tag_categories',
field=models.ManyToManyField(related_name='establishment_types', to='tag.TagCategory', verbose_name='Tag'),
),
migrations.DeleteModel(
name='EstablishmentSubTypeTagCategory',
),
migrations.DeleteModel(
name='EstablishmentTag',
),
migrations.DeleteModel(
name='EstablishmentTypeTagCategory',
),
]

View File

@ -27,15 +27,16 @@ class EstablishmentTypeQuerySet(models.QuerySet):
def with_base_related(self): def with_base_related(self):
"""Return QuerySet with base related.""" """Return QuerySet with base related."""
return self.prefetch_related( return self
models.Prefetch('tag_categories', # return self.prefetch_related(
EstablishmentTypeTagCategory.objects.select_related('tag_category')), # models.Prefetch('tag_categories',
models.Prefetch('establishmentsubtype_set', # EstablishmentTypeTagCategory.objects.select_related('tag_category')),
EstablishmentSubType.objects.prefetch_related( # models.Prefetch('establishmentsubtype_set',
models.Prefetch( # EstablishmentSubType.objects.prefetch_related(
'tag_categories', # models.Prefetch(
EstablishmentSubTypeTagCategory.objects.select_related('tag_category')))) # 'tag_categories',
) # EstablishmentSubTypeTagCategory.objects.select_related('tag_category'))))
# )
# todo: establishment type&subtypes check # todo: establishment type&subtypes check
@ -47,6 +48,9 @@ class EstablishmentType(TranslatedFieldsMixin, ProjectBaseMixin):
name = TJSONField(blank=True, null=True, default=None, verbose_name=_('Description'), name = TJSONField(blank=True, null=True, default=None, verbose_name=_('Description'),
help_text='{"en-GB":"some text"}') help_text='{"en-GB":"some text"}')
use_subtypes = models.BooleanField(_('Use subtypes'), default=True) use_subtypes = models.BooleanField(_('Use subtypes'), default=True)
tag_categories = models.ManyToManyField('tag.TagCategory',
related_name='establishment_types',
verbose_name=_('Tag'))
objects = EstablishmentTypeQuerySet.as_manager() objects = EstablishmentTypeQuerySet.as_manager()
@ -75,6 +79,9 @@ class EstablishmentSubType(ProjectBaseMixin, TranslatedFieldsMixin):
establishment_type = models.ForeignKey(EstablishmentType, establishment_type = models.ForeignKey(EstablishmentType,
on_delete=models.CASCADE, on_delete=models.CASCADE,
verbose_name=_('Type')) verbose_name=_('Type'))
tag_categories = models.ManyToManyField('tag.TagCategory',
related_name='establishment_subtypes',
verbose_name=_('Tag'))
objects = EstablishmentSubTypeManager() objects = EstablishmentSubTypeManager()
@ -94,14 +101,15 @@ class EstablishmentQuerySet(models.QuerySet):
def with_base_related(self): def with_base_related(self):
"""Return qs with related objects.""" """Return qs with related objects."""
return self.select_related('address', 'establishment_type').prefetch_related( return self
models.Prefetch('tags', # return self.select_related('address', 'establishment_type').prefetch_related(
EstablishmentTag.objects.select_related('tag')), # models.Prefetch('tags',
models.Prefetch('establishment_type__tag_categories', # EstablishmentTag.objects.select_related('tag')),
EstablishmentTypeTagCategory.objects.select_related('tag_category')), # models.Prefetch('establishment_type__tag_categories',
models.Prefetch('establishment_type__establishmentsubtype_set', # EstablishmentTypeTagCategory.objects.select_related('tag_category')),
EstablishmentSubType.objects.prefetch_related('tag_categories')), # models.Prefetch('establishment_type__establishmentsubtype_set',
) # EstablishmentSubType.objects.prefetch_related('tag_categories')),
# )
def with_extended_related(self): def with_extended_related(self):
return self.select_related('establishment_type').\ return self.select_related('establishment_type').\
@ -320,7 +328,11 @@ class Establishment(ProjectBaseMixin, URLImageMixin, TranslatedFieldsMixin):
verbose_name=_('Establishment slug'), editable=True) verbose_name=_('Establishment slug'), editable=True)
awards = generic.GenericRelation(to='main.Award', related_query_name='establishment') awards = generic.GenericRelation(to='main.Award', related_query_name='establishment')
tags = generic.GenericRelation(to='main.MetaDataContent') # todo: remove after data merge
# tags = generic.GenericRelation(to='main.MetaDataContent')
tags = models.ManyToManyField('tag.Tag', related_name='establishments',
verbose_name=_('Tag'))
old_tags = generic.GenericRelation(to='main.MetaDataContent')
reviews = generic.GenericRelation(to='review.Review') reviews = generic.GenericRelation(to='review.Review')
comments = generic.GenericRelation(to='comment.Comment') comments = generic.GenericRelation(to='comment.Comment')
favorites = generic.GenericRelation(to='favorites.Favorites') favorites = generic.GenericRelation(to='favorites.Favorites')
@ -575,81 +587,81 @@ class SocialNetwork(models.Model):
def __str__(self): def __str__(self):
return self.title return self.title
#
# class EstablishmentTagQuerySet(models.QuerySet):
# """Establishment tag QuerySet."""
#
# def by_country_code(self, code):
# """Return establishment tags by establishment country code."""
# return self.filter(establishment__address__city__country__code=code)
class EstablishmentTagQuerySet(models.QuerySet): #
"""Establishment tag QuerySet.""" # class EstablishmentTag(models.Model):
# """Establishment tag model."""
def by_country_code(self, code): # tag = models.ForeignKey('tag.Tag',
"""Return establishment tags by establishment country code.""" # on_delete=models.CASCADE,
return self.filter(establishment__address__city__country__code=code) # related_name='tags',
# verbose_name=_('tag'))
# establishment = models.ForeignKey('establishment.Establishment',
class EstablishmentTag(models.Model): # on_delete=models.CASCADE,
"""Establishment tag model.""" # related_name='tags',
tag = models.ForeignKey('tag.Tag', # verbose_name=_('establishment'))
on_delete=models.CASCADE, # objects = EstablishmentTagQuerySet.as_manager()
related_name='tags', #
verbose_name=_('tag')) # class Meta:
establishment = models.ForeignKey('establishment.Establishment', # verbose_name = _('establishment tag')
on_delete=models.CASCADE, # verbose_name_plural = _('establishment tags')
related_name='tags', #
verbose_name=_('establishment')) #
objects = EstablishmentTagQuerySet.as_manager() # class EstablishmentTypeTagCategoryQuerySet(models.QuerySet):
# """EstablishmentTypeTagCategory QuerySet."""
class Meta: #
verbose_name = _('establishment tag') # def by_country_code(self, code):
verbose_name_plural = _('establishment tags') # """Return establishment tags by country code"""
# return self.filter(tag_category__country__code=code)
#
class EstablishmentTypeTagCategoryQuerySet(models.QuerySet): # def with_base_related(self):
"""EstablishmentTypeTagCategory QuerySet.""" # """Return with related relations."""
# return self.select_related('establishment_type', 'tag_category')
def by_country_code(self, code): #
"""Return establishment tags by country code""" #
return self.filter(tag_category__country__code=code) # class EstablishmentTypeTagCategory(models.Model):
# """Tag categories based on establishment type."""
def with_base_related(self): # establishment_type = models.ForeignKey(EstablishmentType,
"""Return with related relations.""" # on_delete=models.CASCADE,
return self.select_related('establishment_type', 'tag_category') # related_name='tag_categories',
# verbose_name=_('establishment type'))
# tag_category = models.ForeignKey('tag.TagCategory',
class EstablishmentTypeTagCategory(models.Model): # on_delete=models.CASCADE,
"""Tag categories based on establishment type.""" # related_name='est_type_tag_categories',
establishment_type = models.ForeignKey(EstablishmentType, # verbose_name=_('tag category'))
on_delete=models.CASCADE, # objects = EstablishmentTypeTagCategoryQuerySet.as_manager()
related_name='tag_categories', #
verbose_name=_('establishment type')) # class Meta:
tag_category = models.ForeignKey('tag.TagCategory', # verbose_name = _('establishment type tag categories')
on_delete=models.CASCADE, # verbose_name_plural = _('establishment type tag categories')
related_name='est_type_tag_categories', #
verbose_name=_('tag category')) #
objects = EstablishmentTypeTagCategoryQuerySet.as_manager() # class EstablishmentSubTypeTagCategoryQuerySet(models.QuerySet):
# """QuerySet for tag categories based on establishment subtype."""
class Meta: #
verbose_name = _('establishment type tag categories') # def with_base_related(self):
verbose_name_plural = _('establishment type tag categories') # """Return queryset with base related."""
# return self.select_related('establishment_subtype', 'tag_category')
#
class EstablishmentSubTypeTagCategoryQuerySet(models.QuerySet): #
"""QuerySet for tag categories based on establishment subtype.""" # class EstablishmentSubTypeTagCategory(models.Model):
# """Tag categories based on establishment subtype."""
def with_base_related(self): # establishment_subtype = models.ForeignKey(EstablishmentSubType,
"""Return queryset with base related.""" # on_delete=models.CASCADE,
return self.select_related('establishment_subtype', 'tag_category') # related_name='tag_categories',
# verbose_name=_('establishment subtype'))
# tag_category = models.ForeignKey('tag.TagCategory',
class EstablishmentSubTypeTagCategory(models.Model): # on_delete=models.CASCADE,
"""Tag categories based on establishment subtype.""" # related_name='est_subtype_tag_categories',
establishment_subtype = models.ForeignKey(EstablishmentSubType, # verbose_name=_('tag category'))
on_delete=models.CASCADE, # objects = EstablishmentSubTypeTagCategoryQuerySet.as_manager()
related_name='tag_categories', #
verbose_name=_('establishment subtype')) # class Meta:
tag_category = models.ForeignKey('tag.TagCategory', # verbose_name = _('establishment subtype tag categories')
on_delete=models.CASCADE, # verbose_name_plural = _('establishment subtype tag categories')
related_name='est_subtype_tag_categories',
verbose_name=_('tag category'))
objects = EstablishmentSubTypeTagCategoryQuerySet.as_manager()
class Meta:
verbose_name = _('establishment subtype tag categories')
verbose_name_plural = _('establishment subtype tag categories')

View File

@ -5,8 +5,8 @@ from establishment import models
from establishment.serializers import ( from establishment.serializers import (
EstablishmentBaseSerializer, PlateSerializer, ContactEmailsSerializer, EstablishmentBaseSerializer, PlateSerializer, ContactEmailsSerializer,
ContactPhonesSerializer, SocialNetworkRelatedSerializers, ContactPhonesSerializer, SocialNetworkRelatedSerializers,
EstablishmentTypeBaseSerializer, EstablishmentSubTypeBaseSerializer, EstablishmentTypeBaseSerializer, EstablishmentSubTypeBaseSerializer)
EstablishmentTypeTagCategoryBaseSerializer) # EstablishmentTypeTagCategoryBaseSerializer)
from main.models import Currency from main.models import Currency
from tag.serializers import TagBaseSerializer from tag.serializers import TagBaseSerializer
from utils.decorators import with_base_attributes from utils.decorators import with_base_attributes
@ -146,94 +146,94 @@ class EmployeeBackSerializers(serializers.ModelSerializer):
] ]
class EstablishmentTagCreateSerializer(serializers.ModelSerializer): # class EstablishmentTagCreateSerializer(serializers.ModelSerializer):
"""Serializer for model EstablishmentTag.""" # """Serializer for model EstablishmentTag."""
class Meta: # class Meta:
model = models.EstablishmentTag # model = models.EstablishmentTag
fields = [ # fields = [
'tag', # 'tag',
'establishment' # 'establishment'
] # ]
extra_kwargs = { # extra_kwargs = {
'tag': {'write_only': True}, # 'tag': {'write_only': True},
'establishment': {'write_only': True}, # 'establishment': {'write_only': True},
} # }
#
def validate(self, attrs): # def validate(self, attrs):
"""Validate method.""" # """Validate method."""
establishment = attrs.get('establishment') # establishment = attrs.get('establishment')
tag = attrs.get('tag') # tag = attrs.get('tag')
#
# Check if tag is already added to establishment. # # Check if tag is already added to establishment.
if establishment.tags.filter(tag=tag).exists(): # if establishment.tags.filter(tag=tag).exists():
raise serializers.ValidationError(detail={'detail': _('Tag is already added.')}) # raise serializers.ValidationError(detail={'detail': _('Tag is already added.')})
#
# Сhecking tag availability for establishment type. # # Сhecking tag availability for establishment type.
if not establishment.establishment_type.use_subtypes: # if not establishment.establishment_type.use_subtypes:
qs = establishment.establishment_type.tag_categories.filter(tag_category=tag.category) # qs = establishment.establishment_type.tag_categories.filter(tag_category=tag.category)
else: # else:
# Сhecking tag availability for establishment subtype. # # Сhecking tag availability for establishment subtype.
qs = establishment.establishment_type.tag_categories.filter( # qs = establishment.establishment_type.tag_categories.filter(
establishmentsubtype_set__tag_category=tag.category) # establishmentsubtype_set__tag_category=tag.category)
if not qs.exists(): # if not qs.exists():
raise serializers.ValidationError( # raise serializers.ValidationError(
detail={'detail': _('Tag is not available for this establishment type|subtype.')}) # detail={'detail': _('Tag is not available for this establishment type|subtype.')})
return attrs # return attrs
class EstablishmentSubTypeTagCategoryBaseSerializer(serializers.ModelSerializer): # class EstablishmentSubTypeTagCategoryBaseSerializer(serializers.ModelSerializer):
"""Serializer for intermediate model EstablishmentSubTypeTagCategories.""" # """Serializer for intermediate model EstablishmentSubTypeTagCategories."""
id = serializers.IntegerField(source='tag_category.id', read_only=True) # id = serializers.IntegerField(source='tag_category.id', read_only=True)
label_translated = TranslatedField(source='tag_category.label_translated') # label_translated = TranslatedField(source='tag_category.label_translated')
tags = TagBaseSerializer(source='tag_category.tags', many=True, read_only=True) # tags = TagBaseSerializer(source='tag_category.tags', many=True, read_only=True)
#
class Meta: # class Meta:
"""Meta class.""" # """Meta class."""
model = models.EstablishmentSubTypeTagCategory # model = models.EstablishmentSubTypeTagCategory
fields = [ # fields = [
'id', # 'id',
'label_translated', # 'label_translated',
'tags', # 'tags',
'establishment_subtype', # 'establishment_subtype',
'tag_category', # 'tag_category',
] # ]
extra_kwargs = { # extra_kwargs = {
'establishment_subtype': {'write_only': True}, # 'establishment_subtype': {'write_only': True},
'tag_category': {'write_only': True}, # 'tag_category': {'write_only': True},
} # }
#
def validate(self, attrs): # def validate(self, attrs):
"""Override validate method.""" # """Override validate method."""
if models.EstablishmentTypeTagCategory.objects.filter( # if models.EstablishmentTypeTagCategory.objects.filter(
establishment_type=attrs.get('establishment_type'), # establishment_type=attrs.get('establishment_type'),
tag_category=attrs.get('tag_category')).exists(): # tag_category=attrs.get('tag_category')).exists():
raise serializers.ValidationError(detail={'detail': _('Objects is already attached.')}) # raise serializers.ValidationError(detail={'detail': _('Objects is already attached.')})
return attrs # return attrs
#
#
class EstablishmentSubTypeSerializer(EstablishmentSubTypeBaseSerializer): # class EstablishmentSubTypeSerializer(EstablishmentSubTypeBaseSerializer):
"""Extended serializer for EstablishmentSubType model with tags.""" # """Extended serializer for EstablishmentSubType model with tags."""
tag_categories = EstablishmentSubTypeTagCategoryBaseSerializer(many=True, read_only=True) # tag_categories = EstablishmentSubTypeTagCategoryBaseSerializer(many=True, read_only=True)
#
class Meta(EstablishmentSubTypeBaseSerializer.Meta): # class Meta(EstablishmentSubTypeBaseSerializer.Meta):
"""Meta class""" # """Meta class"""
fields = [ # fields = [
'id', # 'id',
'name_translated', # 'name_translated',
'tag_categories' # 'tag_categories'
] # ]
#
#
class EstablishmentTagsByType(EstablishmentTypeBaseSerializer): # class EstablishmentTagsByType(EstablishmentTypeBaseSerializer):
"""Tags by establishment type""" # """Tags by establishment type"""
tag_categories = EstablishmentTypeTagCategoryBaseSerializer(many=True) # tag_categories = EstablishmentTypeTagCategoryBaseSerializer(many=True)
subtypes = EstablishmentSubTypeSerializer(many=True, source='establishmentsubtype_set') # subtypes = EstablishmentSubTypeSerializer(many=True, source='establishmentsubtype_set')
#
class Meta(EstablishmentTypeBaseSerializer.Meta): # class Meta(EstablishmentTypeBaseSerializer.Meta):
"""Meta class.""" # """Meta class."""
fields = [ # fields = [
'id', # 'id',
'name_translated', # 'name_translated',
'tag_categories', # 'tag_categories',
'subtypes', # 'subtypes',
] # ]

View File

@ -139,34 +139,34 @@ class EstablishmentSubTypeBaseSerializer(serializers.ModelSerializer):
} }
class EstablishmentTypeTagCategoryBaseSerializer(serializers.ModelSerializer): # class EstablishmentTypeTagCategoryBaseSerializer(serializers.ModelSerializer):
"""Serializer for intermediate model EstablishmentTypeTagCategories.""" # """Serializer for intermediate model EstablishmentTypeTagCategories."""
id = serializers.IntegerField(source='tag_category.id', read_only=True) # id = serializers.IntegerField(source='tag_category.id', read_only=True)
label_translated = TranslatedField(source='tag_category.label_translated') # label_translated = TranslatedField(source='tag_category.label_translated')
tags = TagBaseSerializer(source='tag_category.tags', many=True, read_only=True) # tags = TagBaseSerializer(source='tag_category.tags', many=True, read_only=True)
#
class Meta: # class Meta:
"""Meta class.""" # """Meta class."""
model = models.EstablishmentTypeTagCategory # model = models.EstablishmentTypeTagCategory
fields = [ # fields = [
'id', # 'id',
'label_translated', # 'label_translated',
'tags', # 'tags',
'establishment_type', # 'establishment_type',
'tag_category', # 'tag_category',
] # ]
extra_kwargs = { # extra_kwargs = {
'establishment_type': {'write_only': True}, # 'establishment_type': {'write_only': True},
'tag_category': {'write_only': True}, # 'tag_category': {'write_only': True},
} # }
#
def validate(self, attrs): # def validate(self, attrs):
"""Override validate method.""" # """Override validate method."""
if models.EstablishmentTypeTagCategory.objects.filter( # if models.EstablishmentTypeTagCategory.objects.filter(
establishment_type=attrs.get('establishment_type'), # establishment_type=attrs.get('establishment_type'),
tag_category=attrs.get('tag_category')).exists(): # tag_category=attrs.get('tag_category')).exists():
raise serializers.ValidationError(detail={'detail': _('Objects is already attached.')}) # raise serializers.ValidationError(detail={'detail': _('Objects is already attached.')})
return attrs # return attrs
class EstablishmentEmployeeSerializer(serializers.ModelSerializer): class EstablishmentEmployeeSerializer(serializers.ModelSerializer):
@ -184,19 +184,19 @@ class EstablishmentEmployeeSerializer(serializers.ModelSerializer):
model = models.Employee model = models.Employee
fields = ('id', 'name', 'position_translated', 'awards', 'priority') fields = ('id', 'name', 'position_translated', 'awards', 'priority')
#
class EstablishmentTagSerializer(serializers.ModelSerializer): # class EstablishmentTagSerializer(serializers.ModelSerializer):
"""Serializer for intermediate model EstablishmentTag.""" # """Serializer for intermediate model EstablishmentTag."""
id = serializers.IntegerField(source='tag.id') # id = serializers.IntegerField(source='tag.id')
label_translated = serializers.CharField(source='tag.label_translated') # label_translated = serializers.CharField(source='tag.label_translated')
#
class Meta: # class Meta:
"""Meta class.""" # """Meta class."""
model = models.EstablishmentTag # model = models.EstablishmentTag
fields = [ # fields = [
'id', # 'id',
'label_translated' # 'label_translated'
] # ]
class EstablishmentBaseSerializer(ProjectModelSerializer): class EstablishmentBaseSerializer(ProjectModelSerializer):
@ -206,7 +206,7 @@ class EstablishmentBaseSerializer(ProjectModelSerializer):
slug = serializers.SlugField(allow_blank=False, required=True, max_length=50) slug = serializers.SlugField(allow_blank=False, required=True, max_length=50)
address = AddressBaseSerializer() address = AddressBaseSerializer()
in_favorites = serializers.BooleanField(allow_null=True) in_favorites = serializers.BooleanField(allow_null=True)
tags = EstablishmentTagSerializer(many=True) tags = TagBaseSerializer(read_only=True, many=True)
class Meta: class Meta:
"""Meta class.""" """Meta class."""

View File

@ -14,7 +14,7 @@ urlpatterns = [
name='schedule-rud'), name='schedule-rud'),
path('<int:pk>/schedule/', views.EstablishmentScheduleCreateView.as_view(), path('<int:pk>/schedule/', views.EstablishmentScheduleCreateView.as_view(),
name='schedule-create'), name='schedule-create'),
path('attach-tag/', views.EstablishmentTagCreateView.as_view(), name='attach-tag'), # path('attach-tag/', views.EstablishmentTagCreateView.as_view(), name='attach-tag'),
path('menus/', views.MenuListCreateView.as_view(), name='menu-list'), path('menus/', views.MenuListCreateView.as_view(), name='menu-list'),
path('menus/<int:pk>/', views.MenuRUDView.as_view(), name='menu-rud'), path('menus/<int:pk>/', views.MenuRUDView.as_view(), name='menu-rud'),
path('plates/', views.PlateListCreateView.as_view(), name='plates'), path('plates/', views.PlateListCreateView.as_view(), name='plates'),
@ -28,12 +28,12 @@ urlpatterns = [
path('employees/', views.EmployeeListCreateView.as_view(), name='employees'), path('employees/', views.EmployeeListCreateView.as_view(), name='employees'),
path('employees/<int:pk>/', views.EmployeeRUDView.as_view(), name='employees-rud'), path('employees/<int:pk>/', views.EmployeeRUDView.as_view(), name='employees-rud'),
path('types/', views.EstablishmentTypeListCreateView.as_view(), name='type-list'), path('types/', views.EstablishmentTypeListCreateView.as_view(), name='type-list'),
path('types/tags/', views.EstablishmentTypeTagListView.as_view(), name='type-tag-list'), # path('types/tags/', views.EstablishmentTypeTagListView.as_view(), name='type-tag-list'),
path('types/<int:pk>/', views.EstablishmentTypeRUDView.as_view(), name='type-rud'), path('types/<int:pk>/', views.EstablishmentTypeRUDView.as_view(), name='type-rud'),
path('types/attach-tag-category/', views.EstablishmentTypeAttachTagCategoryView.as_view(), # path('types/attach-tag-category/', views.EstablishmentTypeAttachTagCategoryView.as_view(),
name='type-attach-tag-category'), # name='type-attach-tag-category'),
path('subtypes/', views.EstablishmentSubtypeListCreateView.as_view(), name='subtype-list'), path('subtypes/', views.EstablishmentSubtypeListCreateView.as_view(), name='subtype-list'),
path('subtypes/<int:pk>/', views.EstablishmentSubtypeRUDView.as_view(), name='subtype-rud'), path('subtypes/<int:pk>/', views.EstablishmentSubtypeRUDView.as_view(), name='subtype-rud'),
path('subtypes/attach-tag-category/', views.EstablishmentSubTypeAttachTagCategoryView.as_view(), # path('subtypes/attach-tag-category/', views.EstablishmentSubTypeAttachTagCategoryView.as_view(),
name='subtype-attach-tag-category'), # name='subtype-attach-tag-category'),
] ]

View File

@ -7,7 +7,7 @@ app_name = 'establishment'
urlpatterns = [ urlpatterns = [
path('', views.EstablishmentListView.as_view(), name='list'), path('', views.EstablishmentListView.as_view(), name='list'),
path('types/tags/', views.EstablishmentTypeTagListView.as_view(), name='type-tag-list'), # path('types/tags/', views.EstablishmentTypeTagListView.as_view(), name='type-tag-list'),
path('recent-reviews/', views.EstablishmentRecentReviewListView.as_view(), path('recent-reviews/', views.EstablishmentRecentReviewListView.as_view(),
name='recent-reviews'), name='recent-reviews'),
path('slug/<slug:slug>/', views.EstablishmentRetrieveView.as_view(), name='detail'), path('slug/<slug:slug>/', views.EstablishmentRetrieveView.as_view(), name='detail'),

View File

@ -55,24 +55,24 @@ class EstablishmentScheduleCreateView(generics.CreateAPIView):
serializer_class = ScheduleCreateSerializer serializer_class = ScheduleCreateSerializer
class EstablishmentTypeAttachTagCategoryView(generics.CreateAPIView): # class EstablishmentTypeAttachTagCategoryView(generics.CreateAPIView):
"""Attach tag category to establishment type.""" # """Attach tag category to establishment type."""
serializer_class = serializers.EstablishmentTypeTagCategoryBaseSerializer # serializer_class = serializers.EstablishmentTypeTagCategoryBaseSerializer
#
def get_queryset(self): # def get_queryset(self):
"""Override get_queryset method.""" # """Override get_queryset method."""
return models.EstablishmentTypeTagCategory.objects.with_base_related() # return models.EstablishmentTypeTagCategory.objects.with_base_related()
#
def post(self, request, *args, **kwargs): # def post(self, request, *args, **kwargs):
"""Overridden post-method.""" # """Overridden post-method."""
super(EstablishmentTypeAttachTagCategoryView, self).post(request) # super(EstablishmentTypeAttachTagCategoryView, self).post(request)
return Response(status=status.HTTP_200_OK) # return Response(status=status.HTTP_200_OK)
class EstablishmentTagCreateView(EstablishmentMixinViews, generics.CreateAPIView): # class EstablishmentTagCreateView(EstablishmentMixinViews, generics.CreateAPIView):
"""Attach tag to establishment.""" # """Attach tag to establishment."""
serializer_class = serializers.EstablishmentTagCreateSerializer # serializer_class = serializers.EstablishmentTagCreateSerializer
#
class MenuListCreateView(generics.ListCreateAPIView): class MenuListCreateView(generics.ListCreateAPIView):
"""Menu list create view.""" """Menu list create view."""
@ -164,13 +164,13 @@ class EstablishmentTypeRUDView(generics.RetrieveUpdateDestroyAPIView):
queryset = models.EstablishmentType.objects.all() queryset = models.EstablishmentType.objects.all()
class EstablishmentTypeTagListView(generics.ListAPIView): # class EstablishmentTypeTagListView(generics.ListAPIView):
"""List of tags with categories by establishment type.""" # """List of tags with categories by establishment type."""
serializer_class = serializers.EstablishmentTagsByType # serializer_class = serializers.EstablishmentTagsByType
queryset = models.EstablishmentType.objects.with_base_related() # queryset = models.EstablishmentType.objects.with_base_related()
filter_class = EstablishmentTypeTagFilter # filter_class = EstablishmentTypeTagFilter
permission_classes = (permissions.AllowAny, ) # permission_classes = (permissions.AllowAny, )
pagination_class = None # pagination_class = None
class EstablishmentSubtypeListCreateView(generics.ListCreateAPIView): class EstablishmentSubtypeListCreateView(generics.ListCreateAPIView):
@ -186,15 +186,15 @@ class EstablishmentSubtypeRUDView(generics.RetrieveUpdateDestroyAPIView):
queryset = models.EstablishmentSubType.objects.all() queryset = models.EstablishmentSubType.objects.all()
class EstablishmentSubTypeAttachTagCategoryView(generics.CreateAPIView): # class EstablishmentSubTypeAttachTagCategoryView(generics.CreateAPIView):
"""Attach tag category to establishment subtype.""" # """Attach tag category to establishment subtype."""
serializer_class = serializers.EstablishmentSubTypeTagCategoryBaseSerializer # serializer_class = serializers.EstablishmentSubTypeTagCategoryBaseSerializer
#
def get_queryset(self): # def get_queryset(self):
"""Override get_queryset method.""" # """Override get_queryset method."""
return models.EstablishmentSubTypeTagCategory.objects.with_base_related() # return models.EstablishmentSubTypeTagCategory.objects.with_base_related()
#
def post(self, request, *args, **kwargs): # def post(self, request, *args, **kwargs):
"""Overridden post-method.""" # """Overridden post-method."""
super(EstablishmentSubTypeAttachTagCategoryView, self).post(request) # super(EstablishmentSubTypeAttachTagCategoryView, self).post(request)
return Response(status=status.HTTP_200_OK) # return Response(status=status.HTTP_200_OK)

View File

@ -24,15 +24,15 @@ class NewsDocument(Document):
country = fields.ObjectField(properties={'id': fields.IntegerField(), country = fields.ObjectField(properties={'id': fields.IntegerField(),
'code': fields.KeywordField()}) 'code': fields.KeywordField()})
web_url = fields.KeywordField(attr='web_url') web_url = fields.KeywordField(attr='web_url')
tags = fields.ObjectField( # tags = fields.ObjectField(
properties={ # properties={
'id': fields.IntegerField(attr='metadata.id'), # 'id': fields.IntegerField(attr='metadata.id'),
'label': fields.ObjectField(attr='metadata.label_indexing', # 'label': fields.ObjectField(attr='metadata.label_indexing',
properties=OBJECT_FIELD_PROPERTIES), # properties=OBJECT_FIELD_PROPERTIES),
'category': fields.ObjectField(attr='metadata.category', # 'category': fields.ObjectField(attr='metadata.category',
properties={'id': fields.IntegerField()}) # properties={'id': fields.IntegerField()})
}, # },
multi=True) # multi=True)
class Django: class Django:

48
apps/tag/filters.py Normal file
View File

@ -0,0 +1,48 @@
"""Tag app filters."""
from django_filters import rest_framework as filters
from tag import models
class TagCategoryFilterSet(filters.FilterSet):
"""TagCategory filterset."""
# Object type choices
NEWS = 'news'
ESTABLISHMENT = 'establishment'
TYPE_CHOICES = (
(NEWS, 'News'),
(ESTABLISHMENT, 'Establishment'),
)
type = filters.MultipleChoiceFilter(choices=TYPE_CHOICES,
method='filter_by_type')
# Establishment type choices
RESTAURANT = 'restaurant'
ESTABLISHMENT_TYPE_CHOICES = (
(RESTAURANT, 'restaurant'),
)
establishment_type = filters.MultipleChoiceFilter(
choices=ESTABLISHMENT_TYPE_CHOICES,
method='filter_by_establishment_type')
class Meta:
"""Meta class."""
model = models.TagCategory
fields = ('type',
'establishment_type', )
def filter_by_type(self, queryset, name, value):
if self.NEWS in value:
queryset = queryset.for_news()
if self.ESTABLISHMENT in value:
queryset = queryset.for_establishments()
return queryset
# todo: filter by establishment type
def filter_by_establishment_type(self, queryset, name, value):
return queryset.for_establishments()

View File

@ -32,8 +32,16 @@ class Tag(TranslatedFieldsMixin, models.Model):
class TagCategoryQuerySet(models.QuerySet): class TagCategoryQuerySet(models.QuerySet):
"""Extended queryset for TagCategory model.""" """Extended queryset for TagCategory model."""
def by_news_type(self, news_type): def with_base_related(self):
return self.filter(news_types=news_type) return self.prefetch_related('tags')
def for_news(self):
return self.filter(news_types__isnull=True)
def for_establishments(self):
return self.filter(models.Q(est_subtype_tag_categories__isnull=True) |
models.Q(est_type_tag_categories__isnull=True)).\
distinct()
def with_related(self): def with_related(self):
return self.select_related('country').prefetch_related('tags') return self.select_related('country').prefetch_related('tags')

View File

@ -13,23 +13,29 @@ class TagBaseSerializer(serializers.ModelSerializer):
"""Meta class.""" """Meta class."""
model = models.Tag model = models.Tag
fields = [ fields = (
'id', 'id',
'label',
'label_translated', 'label_translated',
)
class TagBackOfficeSerializer(TagBaseSerializer):
"""Serializer for Tag model for Back office users."""
class Meta(TagBaseSerializer.Meta):
"""Meta class."""
fields = TagBaseSerializer.Meta.fields + (
'label',
'category' 'category'
] )
extra_kwargs = {
'label': {'write_only': True},
'category': {'write_only': True}
}
class TagCategoryBaseSerializer(serializers.ModelSerializer): class TagCategoryBaseSerializer(serializers.ModelSerializer):
"""Serializer for model TagCategory.""" """Serializer for model TagCategory."""
label_translated = TranslatedField() label_translated = TranslatedField()
country_translated = TranslatedField(source='country.name_translated') tags = TagBaseSerializer(many=True, read_only=True)
class Meta: class Meta:
"""Meta class.""" """Meta class."""
@ -37,23 +43,29 @@ class TagCategoryBaseSerializer(serializers.ModelSerializer):
model = models.TagCategory model = models.TagCategory
fields = ( fields = (
'id', 'id',
'label',
'label_translated', 'label_translated',
'country', 'tags'
'country_translated',
'public',
) )
extra_kwargs = {
'label': {'write_only': True},
'country': {'write_only': True},
}
class TagCategoryDetailSerializer(TagCategoryBaseSerializer): class TagCategoryDetailSerializer(TagCategoryBaseSerializer):
tags = TagBaseSerializer(many=True)
class Meta(TagCategoryBaseSerializer.Meta): class Meta(TagCategoryBaseSerializer.Meta):
"""Meta class.""" """Meta class."""
fields = TagCategoryBaseSerializer.Meta.fields + ('tags', ) fields = TagCategoryBaseSerializer.Meta.fields + ('tags', )
class TagCategoryBackOfficeDetailSerializer(TagCategoryDetailSerializer):
country_translated = TranslatedField(source='country.name_translated')
class Meta(TagCategoryDetailSerializer.Meta):
"""Meta class."""
fields = TagCategoryDetailSerializer.Meta.fields + (
'news_types',
'country',
'country_translated',
)

View File

View File

@ -1,10 +1,16 @@
"""Urlconf for app tag.""" """Urlconf for app tag."""
from django.urls import path from django.urls import path
from . import views from rest_framework.routers import SimpleRouter
from tag import views
app_name = 'tag' app_name = 'tag'
router = SimpleRouter()
router.register(r'', views.TagViewSet)
urlpatterns = [ urlpatterns = [
path('', views.TagListCreateView.as_view(), name='list-create'),
path('category/', views.TagCategoryListCreateView.as_view(), name='category-list-create'), path('category/', views.TagCategoryListCreateView.as_view(), name='category-list-create'),
] ]
urlpatterns += router.urls

16
apps/tag/urls/web.py Normal file
View File

@ -0,0 +1,16 @@
"""Tag app urlpatterns web users."""
from rest_framework.routers import SimpleRouter
from tag import views
app_name = 'tag'
router = SimpleRouter()
router.register(r'categories', views.TagCategoryViewSet)
urlpatterns = [
]
urlpatterns += router.urls

View File

@ -1,19 +1,33 @@
"""Tag views.""" """Tag views."""
from rest_framework import generics from rest_framework import generics, viewsets, mixins
from tag import serializers, models from tag import filters, models, serializers
from rest_framework import permissions
class TagListCreateView(generics.ListCreateAPIView): class TagViewSet(mixins.ListModelMixin, mixins.CreateModelMixin,
mixins.UpdateModelMixin, mixins.DestroyModelMixin,
viewsets.GenericViewSet):
"""List/create tag view.""" """List/create tag view."""
queryset = models.Tag.objects.all()
serializer_class = serializers.TagBaseSerializer
pagination_class = None pagination_class = None
queryset = models.Tag.objects.all()
serializer_class = serializers.TagBackOfficeSerializer
class TagCategoryListCreateView(generics.ListCreateAPIView): class TagCategoryListCreateView(generics.ListCreateAPIView):
"""List/create tag category view.""" """List/create tag category view."""
queryset = models.TagCategory.objects.all()
serializer_class = serializers.TagCategoryBaseSerializer
pagination_class = None pagination_class = None
permission_classes = (permissions.AllowAny, )
queryset = models.TagCategory.objects.all()
serializer_class = serializers.TagCategoryBackOfficeDetailSerializer
class TagCategoryViewSet(mixins.ListModelMixin, viewsets.GenericViewSet):
"""ViewSet for TagCategory model."""
filterset_class = filters.TagCategoryFilterSet
pagination_class = None
permission_classes = (permissions.AllowAny, )
queryset = models.TagCategory.objects.with_base_related()
serializer_class = serializers.TagCategoryBaseSerializer

View File

@ -222,8 +222,8 @@ REST_FRAMEWORK = {
'COERCE_DECIMAL_TO_STRING': False, 'COERCE_DECIMAL_TO_STRING': False,
'DEFAULT_AUTHENTICATION_CLASSES': ( 'DEFAULT_AUTHENTICATION_CLASSES': (
# JWT # JWT
'utils.authentication.GMJWTAuthentication',
'rest_framework.authentication.SessionAuthentication', 'rest_framework.authentication.SessionAuthentication',
# 'utils.authentication.GMJWTAuthentication',
), ),
'DEFAULT_VERSIONING_CLASS': 'rest_framework.versioning.AcceptHeaderVersioning', 'DEFAULT_VERSIONING_CLASS': 'rest_framework.versioning.AcceptHeaderVersioning',
'DEFAULT_VERSION': (AVAILABLE_VERSIONS['current'],), 'DEFAULT_VERSION': (AVAILABLE_VERSIONS['current'],),

View File

@ -7,7 +7,7 @@ urlpatterns = [
path('establishments/', include('establishment.urls.back')), path('establishments/', include('establishment.urls.back')),
path('location/', include('location.urls.back')), path('location/', include('location.urls.back')),
path('news/', include('news.urls.back')), path('news/', include('news.urls.back')),
path('tags/', include(('tag.urls', 'tag'), namespace='tag')), path('tags/', include(('tag.urls.back', 'tag'), namespace='tag')),
path('account/', include('account.urls.back')), path('account/', include('account.urls.back')),
path('comment/', include('comment.urls.back')), path('comment/', include('comment.urls.back')),
] ]

View File

@ -30,6 +30,7 @@ urlpatterns = [
path('location/', include('location.urls.web')), path('location/', include('location.urls.web')),
path('main/', include('main.urls')), path('main/', include('main.urls')),
path('recipes/', include('recipe.urls.web')), path('recipes/', include('recipe.urls.web')),
path('tags/', include('tag.urls.web')),
path('translation/', include('translation.urls')), path('translation/', include('translation.urls')),
path('comments/', include('comment.urls.web')), path('comments/', include('comment.urls.web')),
path('favorites/', include('favorites.urls')), path('favorites/', include('favorites.urls')),