Merge branch 'feature/gm-192' into feature/gm-148
# Conflicts: # apps/news/models.py # apps/news/serializers.py # apps/news/views.py
This commit is contained in:
commit
2d830b2821
|
|
@ -40,8 +40,7 @@ class PasswordResetConfirmView(JWTGenericViewMixin):
|
|||
queryset = models.User.objects.active()
|
||||
|
||||
def get_object(self):
|
||||
"""Override get_object method
|
||||
"""
|
||||
"""Override get_object method"""
|
||||
queryset = self.filter_queryset(self.get_queryset())
|
||||
uidb64 = self.kwargs.get('uidb64')
|
||||
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ from django.utils.translation import gettext_lazy as _
|
|||
|
||||
from comment.models import Comment
|
||||
from establishment import models
|
||||
from main.models import Award, MetaDataContent
|
||||
from main.models import Award
|
||||
from review import models as review_models
|
||||
|
||||
|
||||
|
|
@ -24,11 +24,6 @@ class AwardInline(GenericTabularInline):
|
|||
extra = 0
|
||||
|
||||
|
||||
class MetaDataContentInline(GenericTabularInline):
|
||||
model = MetaDataContent
|
||||
extra = 0
|
||||
|
||||
|
||||
class ContactPhoneInline(admin.TabularInline):
|
||||
"""Contact phone inline admin."""
|
||||
model = models.ContactPhone
|
||||
|
|
@ -56,8 +51,7 @@ class EstablishmentAdmin(admin.ModelAdmin):
|
|||
"""Establishment admin."""
|
||||
list_display = ['id', '__str__', 'image_tag', ]
|
||||
inlines = [
|
||||
AwardInline, MetaDataContentInline,
|
||||
ContactPhoneInline, ContactEmailInline,
|
||||
AwardInline, ContactPhoneInline, ContactEmailInline,
|
||||
ReviewInline, CommentInline]
|
||||
|
||||
|
||||
|
|
@ -84,4 +78,19 @@ class MenuAdmin(admin.ModelAdmin):
|
|||
"""Get user's short name."""
|
||||
return obj.category_translated
|
||||
|
||||
category_translated.short_description = _('category')
|
||||
category_translated.short_description = _('category')
|
||||
|
||||
|
||||
@admin.register(models.EstablishmentTypeTagCategory)
|
||||
class EstablishmentTypeTagCategoryAdmin(admin.ModelAdmin):
|
||||
"""EstablishmentTypeTagCategory admin."""
|
||||
|
||||
|
||||
@admin.register(models.EstablishmentSubTypeTagCategory)
|
||||
class EstablishmentSubTypeTagCategoryAdmin(admin.ModelAdmin):
|
||||
"""EstablishmentTypeTagCategory admin."""
|
||||
|
||||
|
||||
@admin.register(models.EstablishmentTag)
|
||||
class EstablishmentTagAdmin(admin.ModelAdmin):
|
||||
"""EstablishmentTag admin."""
|
||||
|
|
|
|||
|
|
@ -26,3 +26,17 @@ class EstablishmentFilter(filters.FilterSet):
|
|||
if value not in EMPTY_VALUES:
|
||||
return queryset.search(value, locale=self.request.locale)
|
||||
return queryset
|
||||
|
||||
|
||||
class EstablishmentTypeTagFilter(filters.FilterSet):
|
||||
"""Establishment tag filter set."""
|
||||
|
||||
type_id = filters.NumberFilter(field_name='id')
|
||||
|
||||
class Meta:
|
||||
"""Meta class."""
|
||||
|
||||
model = models.EstablishmentType
|
||||
fields = (
|
||||
'type_id',
|
||||
)
|
||||
|
|
|
|||
|
|
@ -0,0 +1,35 @@
|
|||
# Generated by Django 2.2.4 on 2019-10-09 07:15
|
||||
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('establishment', '0031_establishment_slug'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name='EstablishmentTag',
|
||||
fields=[
|
||||
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
],
|
||||
options={
|
||||
'verbose_name': 'establishment tag',
|
||||
'verbose_name_plural': 'establishment tags',
|
||||
},
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='EstablishmentTypeTagCategory',
|
||||
fields=[
|
||||
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('establishment_type', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='tag_categories', to='establishment.EstablishmentType', verbose_name='establishment type')),
|
||||
],
|
||||
options={
|
||||
'verbose_name': 'establishment type tag categories',
|
||||
'verbose_name_plural': 'establishment type tag categories',
|
||||
},
|
||||
),
|
||||
]
|
||||
30
apps/establishment/migrations/0033_auto_20191009_0715.py
Normal file
30
apps/establishment/migrations/0033_auto_20191009_0715.py
Normal file
|
|
@ -0,0 +1,30 @@
|
|||
# Generated by Django 2.2.4 on 2019-10-09 07:15
|
||||
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('tag', '0001_initial'),
|
||||
('establishment', '0032_establishmenttag_establishmenttypetagcategory'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='establishmenttypetagcategory',
|
||||
name='tag_category',
|
||||
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='est_type_tag_categories', to='tag.TagCategory', verbose_name='tag category'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='establishmenttag',
|
||||
name='establishment',
|
||||
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='tags', to='establishment.Establishment', verbose_name='establishment'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='establishmenttag',
|
||||
name='tag',
|
||||
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='tags', to='tag.Tag', verbose_name='tag'),
|
||||
),
|
||||
]
|
||||
14
apps/establishment/migrations/0034_merge_20191009_1457.py
Normal file
14
apps/establishment/migrations/0034_merge_20191009_1457.py
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
# Generated by Django 2.2.4 on 2019-10-09 14:57
|
||||
|
||||
from django.db import migrations
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('establishment', '0033_auto_20191009_0715'),
|
||||
('establishment', '0033_auto_20191003_0943_squashed_0034_auto_20191003_1036'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
]
|
||||
|
|
@ -0,0 +1,27 @@
|
|||
# Generated by Django 2.2.4 on 2019-10-11 10:47
|
||||
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('tag', '0002_auto_20191009_1408'),
|
||||
('establishment', '0034_merge_20191009_1457'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name='EstablishmentSubTypeTagCategory',
|
||||
fields=[
|
||||
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('establishment_subtype', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='tag_categories', to='establishment.EstablishmentSubType', verbose_name='establishment subtype')),
|
||||
('tag_category', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='est_subtype_tag_categories', to='tag.TagCategory', verbose_name='tag category')),
|
||||
],
|
||||
options={
|
||||
'verbose_name': 'establishment subtype tag categories',
|
||||
'verbose_name_plural': 'establishment subtype tag categories',
|
||||
},
|
||||
),
|
||||
]
|
||||
18
apps/establishment/migrations/0036_auto_20191011_1356.py
Normal file
18
apps/establishment/migrations/0036_auto_20191011_1356.py
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
# Generated by Django 2.2.4 on 2019-10-11 13:56
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('establishment', '0035_establishmentsubtypetagcategory'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='establishment',
|
||||
name='establishment_subtypes',
|
||||
field=models.ManyToManyField(blank=True, related_name='subtype_establishment', to='establishment.EstablishmentSubType', verbose_name='subtype'),
|
||||
),
|
||||
]
|
||||
|
|
@ -16,12 +16,29 @@ from phonenumber_field.modelfields import PhoneNumberField
|
|||
|
||||
from collection.models import Collection
|
||||
from location.models import Address
|
||||
from main.models import Award, MetaDataContent
|
||||
from main.models import Award
|
||||
from tag.models import Tag, TagCategory
|
||||
from review.models import Review
|
||||
from utils.models import (ProjectBaseMixin, TJSONField, URLImageMixin,
|
||||
TranslatedFieldsMixin, BaseAttributes)
|
||||
|
||||
|
||||
class EstablishmentTypeQuerySet(models.QuerySet):
|
||||
"""QuerySet for model EstablishmentType."""
|
||||
|
||||
def with_base_related(self):
|
||||
"""Return QuerySet with base related."""
|
||||
return self.prefetch_related(
|
||||
models.Prefetch('tag_categories',
|
||||
EstablishmentTypeTagCategory.objects.select_related('tag_category')),
|
||||
models.Prefetch('establishmentsubtype_set',
|
||||
EstablishmentSubType.objects.prefetch_related(
|
||||
models.Prefetch(
|
||||
'tag_categories',
|
||||
EstablishmentSubTypeTagCategory.objects.select_related('tag_category'))))
|
||||
)
|
||||
|
||||
|
||||
# todo: establishment type&subtypes check
|
||||
class EstablishmentType(TranslatedFieldsMixin, ProjectBaseMixin):
|
||||
"""Establishment type model."""
|
||||
|
|
@ -32,6 +49,8 @@ class EstablishmentType(TranslatedFieldsMixin, ProjectBaseMixin):
|
|||
help_text='{"en-GB":"some text"}')
|
||||
use_subtypes = models.BooleanField(_('Use subtypes'), default=True)
|
||||
|
||||
objects = EstablishmentTypeQuerySet.as_manager()
|
||||
|
||||
class Meta:
|
||||
"""Meta class."""
|
||||
|
||||
|
|
@ -76,10 +95,13 @@ class EstablishmentQuerySet(models.QuerySet):
|
|||
|
||||
def with_base_related(self):
|
||||
"""Return qs with related objects."""
|
||||
return self.select_related('address').prefetch_related(
|
||||
return self.select_related('address', 'establishment_type').prefetch_related(
|
||||
models.Prefetch('tags',
|
||||
MetaDataContent.objects.select_related(
|
||||
'metadata__category'))
|
||||
EstablishmentTag.objects.select_related('tag')),
|
||||
models.Prefetch('establishment_type__tag_categories',
|
||||
EstablishmentTypeTagCategory.objects.select_related('tag_category')),
|
||||
models.Prefetch('establishment_type__establishmentsubtype_set',
|
||||
EstablishmentSubType.objects.prefetch_related('tag_categories')),
|
||||
)
|
||||
|
||||
def with_extended_related(self):
|
||||
|
|
@ -256,6 +278,7 @@ class Establishment(ProjectBaseMixin, URLImageMixin, TranslatedFieldsMixin):
|
|||
on_delete=models.PROTECT,
|
||||
verbose_name=_('type'))
|
||||
establishment_subtypes = models.ManyToManyField(EstablishmentSubType,
|
||||
blank=True,
|
||||
related_name='subtype_establishment',
|
||||
verbose_name=_('subtype'))
|
||||
address = models.ForeignKey(Address, blank=True, null=True, default=None,
|
||||
|
|
@ -478,6 +501,7 @@ class ContactEmail(models.Model):
|
|||
def __str__(self):
|
||||
return f'{self.email}'
|
||||
|
||||
|
||||
#
|
||||
# class Wine(TranslatedFieldsMixin, models.Model):
|
||||
# """Wine model."""
|
||||
|
|
@ -551,3 +575,82 @@ class SocialNetwork(models.Model):
|
|||
|
||||
def __str__(self):
|
||||
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 EstablishmentTag(models.Model):
|
||||
"""Establishment tag model."""
|
||||
tag = models.ForeignKey('tag.Tag',
|
||||
on_delete=models.CASCADE,
|
||||
related_name='tags',
|
||||
verbose_name=_('tag'))
|
||||
establishment = models.ForeignKey('establishment.Establishment',
|
||||
on_delete=models.CASCADE,
|
||||
related_name='tags',
|
||||
verbose_name=_('establishment'))
|
||||
objects = EstablishmentTagQuerySet.as_manager()
|
||||
|
||||
class Meta:
|
||||
verbose_name = _('establishment tag')
|
||||
verbose_name_plural = _('establishment tags')
|
||||
|
||||
|
||||
class EstablishmentTypeTagCategoryQuerySet(models.QuerySet):
|
||||
"""EstablishmentTypeTagCategory QuerySet."""
|
||||
|
||||
def by_country_code(self, code):
|
||||
"""Return establishment tags by country code"""
|
||||
return self.filter(tag_category__country__code=code)
|
||||
|
||||
def with_base_related(self):
|
||||
"""Return with related relations."""
|
||||
return self.select_related('establishment_type', 'tag_category')
|
||||
|
||||
|
||||
class EstablishmentTypeTagCategory(models.Model):
|
||||
"""Tag categories based on establishment type."""
|
||||
establishment_type = models.ForeignKey(EstablishmentType,
|
||||
on_delete=models.CASCADE,
|
||||
related_name='tag_categories',
|
||||
verbose_name=_('establishment type'))
|
||||
tag_category = models.ForeignKey('tag.TagCategory',
|
||||
on_delete=models.CASCADE,
|
||||
related_name='est_type_tag_categories',
|
||||
verbose_name=_('tag category'))
|
||||
objects = EstablishmentTypeTagCategoryQuerySet.as_manager()
|
||||
|
||||
class Meta:
|
||||
verbose_name = _('establishment type tag categories')
|
||||
verbose_name_plural = _('establishment type tag categories')
|
||||
|
||||
|
||||
class EstablishmentSubTypeTagCategoryQuerySet(models.QuerySet):
|
||||
"""QuerySet for tag categories based on establishment subtype."""
|
||||
|
||||
def with_base_related(self):
|
||||
"""Return queryset with base related."""
|
||||
return self.select_related('establishment_subtype', 'tag_category')
|
||||
|
||||
|
||||
class EstablishmentSubTypeTagCategory(models.Model):
|
||||
"""Tag categories based on establishment subtype."""
|
||||
establishment_subtype = models.ForeignKey(EstablishmentSubType,
|
||||
on_delete=models.CASCADE,
|
||||
related_name='tag_categories',
|
||||
verbose_name=_('establishment subtype'))
|
||||
tag_category = models.ForeignKey('tag.TagCategory',
|
||||
on_delete=models.CASCADE,
|
||||
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')
|
||||
|
|
|
|||
|
|
@ -1,13 +1,16 @@
|
|||
from django.utils.translation import gettext_lazy as _
|
||||
from rest_framework import serializers
|
||||
|
||||
from establishment import models
|
||||
from establishment.serializers import (
|
||||
EstablishmentBaseSerializer, PlateSerializer, ContactEmailsSerializer,
|
||||
ContactPhonesSerializer, SocialNetworkRelatedSerializers,
|
||||
EstablishmentTypeSerializer)
|
||||
|
||||
from utils.decorators import with_base_attributes
|
||||
|
||||
EstablishmentTypeBaseSerializer, EstablishmentSubTypeBaseSerializer,
|
||||
EstablishmentTypeTagCategoryBaseSerializer)
|
||||
from main.models import Currency
|
||||
from tag.serializers import TagBaseSerializer
|
||||
from utils.decorators import with_base_attributes
|
||||
from utils.serializers import TranslatedField
|
||||
|
||||
|
||||
class EstablishmentListCreateSerializer(EstablishmentBaseSerializer):
|
||||
|
|
@ -21,7 +24,7 @@ class EstablishmentListCreateSerializer(EstablishmentBaseSerializer):
|
|||
emails = ContactEmailsSerializer(read_only=True, many=True, )
|
||||
socials = SocialNetworkRelatedSerializers(read_only=True, many=True, )
|
||||
slug = serializers.SlugField(required=True, allow_blank=False, max_length=50)
|
||||
type = EstablishmentTypeSerializer(source='establishment_type', read_only=True)
|
||||
type = EstablishmentTypeBaseSerializer(source='establishment_type', read_only=True)
|
||||
|
||||
class Meta:
|
||||
model = models.Establishment
|
||||
|
|
@ -55,7 +58,7 @@ class EstablishmentRUDSerializer(EstablishmentBaseSerializer):
|
|||
phones = ContactPhonesSerializer(read_only=False, many=True, )
|
||||
emails = ContactEmailsSerializer(read_only=False, many=True, )
|
||||
socials = SocialNetworkRelatedSerializers(read_only=False, many=True, )
|
||||
type = EstablishmentTypeSerializer(source='establishment_type')
|
||||
type = EstablishmentTypeBaseSerializer(source='establishment_type')
|
||||
|
||||
class Meta:
|
||||
model = models.Establishment
|
||||
|
|
@ -142,3 +145,95 @@ class EmployeeBackSerializers(serializers.ModelSerializer):
|
|||
'name'
|
||||
]
|
||||
|
||||
|
||||
class EstablishmentTagCreateSerializer(serializers.ModelSerializer):
|
||||
"""Serializer for model EstablishmentTag."""
|
||||
class Meta:
|
||||
model = models.EstablishmentTag
|
||||
fields = [
|
||||
'tag',
|
||||
'establishment'
|
||||
]
|
||||
extra_kwargs = {
|
||||
'tag': {'write_only': True},
|
||||
'establishment': {'write_only': True},
|
||||
}
|
||||
|
||||
def validate(self, attrs):
|
||||
"""Validate method."""
|
||||
establishment = attrs.get('establishment')
|
||||
tag = attrs.get('tag')
|
||||
|
||||
# Check if tag is already added to establishment.
|
||||
if establishment.tags.filter(tag=tag).exists():
|
||||
raise serializers.ValidationError(detail={'detail': _('Tag is already added.')})
|
||||
|
||||
# Сhecking tag availability for establishment type.
|
||||
if not establishment.establishment_type.use_subtypes:
|
||||
qs = establishment.establishment_type.tag_categories.filter(tag_category=tag.category)
|
||||
else:
|
||||
# Сhecking tag availability for establishment subtype.
|
||||
qs = establishment.establishment_type.tag_categories.filter(
|
||||
establishmentsubtype_set__tag_category=tag.category)
|
||||
if not qs.exists():
|
||||
raise serializers.ValidationError(
|
||||
detail={'detail': _('Tag is not available for this establishment type|subtype.')})
|
||||
return attrs
|
||||
|
||||
|
||||
class EstablishmentSubTypeTagCategoryBaseSerializer(serializers.ModelSerializer):
|
||||
"""Serializer for intermediate model EstablishmentSubTypeTagCategories."""
|
||||
id = serializers.IntegerField(source='tag_category.id', read_only=True)
|
||||
label_translated = TranslatedField(source='tag_category.label_translated')
|
||||
tags = TagBaseSerializer(source='tag_category.tags', many=True, read_only=True)
|
||||
|
||||
class Meta:
|
||||
"""Meta class."""
|
||||
model = models.EstablishmentSubTypeTagCategory
|
||||
fields = [
|
||||
'id',
|
||||
'label_translated',
|
||||
'tags',
|
||||
'establishment_subtype',
|
||||
'tag_category',
|
||||
]
|
||||
extra_kwargs = {
|
||||
'establishment_subtype': {'write_only': True},
|
||||
'tag_category': {'write_only': True},
|
||||
}
|
||||
|
||||
def validate(self, attrs):
|
||||
"""Override validate method."""
|
||||
if models.EstablishmentTypeTagCategory.objects.filter(
|
||||
establishment_type=attrs.get('establishment_type'),
|
||||
tag_category=attrs.get('tag_category')).exists():
|
||||
raise serializers.ValidationError(detail={'detail': _('Objects is already attached.')})
|
||||
return attrs
|
||||
|
||||
|
||||
class EstablishmentSubTypeSerializer(EstablishmentSubTypeBaseSerializer):
|
||||
"""Extended serializer for EstablishmentSubType model with tags."""
|
||||
tag_categories = EstablishmentSubTypeTagCategoryBaseSerializer(many=True, read_only=True)
|
||||
|
||||
class Meta(EstablishmentSubTypeBaseSerializer.Meta):
|
||||
"""Meta class"""
|
||||
fields = [
|
||||
'id',
|
||||
'name_translated',
|
||||
'tag_categories'
|
||||
]
|
||||
|
||||
|
||||
class EstablishmentTagsByType(EstablishmentTypeBaseSerializer):
|
||||
"""Tags by establishment type"""
|
||||
tag_categories = EstablishmentTypeTagCategoryBaseSerializer(many=True)
|
||||
subtypes = EstablishmentSubTypeSerializer(many=True, source='establishmentsubtype_set')
|
||||
|
||||
class Meta(EstablishmentTypeBaseSerializer.Meta):
|
||||
"""Meta class."""
|
||||
fields = [
|
||||
'id',
|
||||
'name_translated',
|
||||
'tag_categories',
|
||||
'subtypes',
|
||||
]
|
||||
|
|
|
|||
|
|
@ -1,17 +1,19 @@
|
|||
"""Establishment serializers."""
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
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 favorites.models import Favorites
|
||||
from location.serializers import AddressBaseSerializer
|
||||
from main.models import MetaDataContent
|
||||
from main.serializers import MetaDataContentSerializer, AwardSerializer, CurrencySerializer
|
||||
from main.serializers import AwardSerializer, CurrencySerializer
|
||||
from review import models as review_models
|
||||
from tag.serializers import TagBaseSerializer
|
||||
from timetable.serialziers import ScheduleRUDSerializer
|
||||
from utils import exceptions as utils_exceptions
|
||||
from utils.serializers import TranslatedField, ProjectModelSerializer
|
||||
from utils.serializers import ProjectModelSerializer
|
||||
from utils.serializers import TranslatedField
|
||||
|
||||
|
||||
class ContactPhonesSerializer(serializers.ModelSerializer):
|
||||
|
|
@ -86,30 +88,6 @@ class MenuRUDSerializers(ProjectModelSerializer):
|
|||
]
|
||||
|
||||
|
||||
class EstablishmentTypeSerializer(serializers.ModelSerializer):
|
||||
"""Serializer for EstablishmentType model."""
|
||||
|
||||
name_translated = serializers.CharField(allow_null=True)
|
||||
|
||||
class Meta:
|
||||
"""Meta class."""
|
||||
|
||||
model = models.EstablishmentType
|
||||
fields = ('id', 'name_translated')
|
||||
|
||||
|
||||
class EstablishmentSubTypeSerializer(serializers.ModelSerializer):
|
||||
"""Serializer for EstablishmentSubType models."""
|
||||
|
||||
name_translated = serializers.CharField(allow_null=True)
|
||||
|
||||
class Meta:
|
||||
"""Meta class."""
|
||||
|
||||
model = models.EstablishmentSubType
|
||||
fields = ('id', 'name_translated')
|
||||
|
||||
|
||||
class ReviewSerializer(serializers.ModelSerializer):
|
||||
"""Serializer for model Review."""
|
||||
text_translated = serializers.CharField(read_only=True)
|
||||
|
|
@ -122,6 +100,75 @@ class ReviewSerializer(serializers.ModelSerializer):
|
|||
)
|
||||
|
||||
|
||||
class EstablishmentTypeBaseSerializer(serializers.ModelSerializer):
|
||||
"""Serializer for EstablishmentType model."""
|
||||
name_translated = TranslatedField()
|
||||
|
||||
class Meta:
|
||||
"""Meta class."""
|
||||
model = models.EstablishmentType
|
||||
fields = [
|
||||
'id',
|
||||
'name',
|
||||
'name_translated',
|
||||
'use_subtypes'
|
||||
]
|
||||
extra_kwargs = {
|
||||
'name': {'write_only': True},
|
||||
'use_subtypes': {'write_only': True},
|
||||
}
|
||||
|
||||
|
||||
class EstablishmentSubTypeBaseSerializer(serializers.ModelSerializer):
|
||||
"""Serializer for EstablishmentSubType models."""
|
||||
|
||||
name_translated = TranslatedField()
|
||||
|
||||
class Meta:
|
||||
"""Meta class."""
|
||||
model = models.EstablishmentSubType
|
||||
fields = [
|
||||
'id',
|
||||
'name',
|
||||
'name_translated',
|
||||
'establishment_type'
|
||||
]
|
||||
extra_kwargs = {
|
||||
'name': {'write_only': True},
|
||||
'establishment_type': {'write_only': True}
|
||||
}
|
||||
|
||||
|
||||
class EstablishmentTypeTagCategoryBaseSerializer(serializers.ModelSerializer):
|
||||
"""Serializer for intermediate model EstablishmentTypeTagCategories."""
|
||||
id = serializers.IntegerField(source='tag_category.id', read_only=True)
|
||||
label_translated = TranslatedField(source='tag_category.label_translated')
|
||||
tags = TagBaseSerializer(source='tag_category.tags', many=True, read_only=True)
|
||||
|
||||
class Meta:
|
||||
"""Meta class."""
|
||||
model = models.EstablishmentTypeTagCategory
|
||||
fields = [
|
||||
'id',
|
||||
'label_translated',
|
||||
'tags',
|
||||
'establishment_type',
|
||||
'tag_category',
|
||||
]
|
||||
extra_kwargs = {
|
||||
'establishment_type': {'write_only': True},
|
||||
'tag_category': {'write_only': True},
|
||||
}
|
||||
|
||||
def validate(self, attrs):
|
||||
"""Override validate method."""
|
||||
if models.EstablishmentTypeTagCategory.objects.filter(
|
||||
establishment_type=attrs.get('establishment_type'),
|
||||
tag_category=attrs.get('tag_category')).exists():
|
||||
raise serializers.ValidationError(detail={'detail': _('Objects is already attached.')})
|
||||
return attrs
|
||||
|
||||
|
||||
class EstablishmentEmployeeSerializer(serializers.ModelSerializer):
|
||||
"""Serializer for actual employees."""
|
||||
|
||||
|
|
@ -138,14 +185,28 @@ class EstablishmentEmployeeSerializer(serializers.ModelSerializer):
|
|||
fields = ('id', 'name', 'position_translated', 'awards', 'priority')
|
||||
|
||||
|
||||
class EstablishmentTagSerializer(serializers.ModelSerializer):
|
||||
"""Serializer for intermediate model EstablishmentTag."""
|
||||
id = serializers.IntegerField(source='tag.id')
|
||||
label_translated = serializers.CharField(source='tag.label_translated')
|
||||
|
||||
class Meta:
|
||||
"""Meta class."""
|
||||
model = models.EstablishmentTag
|
||||
fields = [
|
||||
'id',
|
||||
'label_translated'
|
||||
]
|
||||
|
||||
|
||||
class EstablishmentBaseSerializer(ProjectModelSerializer):
|
||||
"""Base serializer for Establishment model."""
|
||||
|
||||
preview_image = serializers.URLField(source='preview_image_url')
|
||||
slug = serializers.SlugField(allow_blank=False, required=True, max_length=50)
|
||||
address = AddressBaseSerializer()
|
||||
tags = MetaDataContentSerializer(many=True)
|
||||
in_favorites = serializers.BooleanField(allow_null=True)
|
||||
tags = EstablishmentTagSerializer(many=True)
|
||||
|
||||
class Meta:
|
||||
"""Meta class."""
|
||||
|
|
@ -171,8 +232,8 @@ class EstablishmentDetailSerializer(EstablishmentBaseSerializer):
|
|||
|
||||
description_translated = TranslatedField()
|
||||
image = serializers.URLField(source='image_url')
|
||||
type = EstablishmentTypeSerializer(source='establishment_type', read_only=True)
|
||||
subtypes = EstablishmentSubTypeSerializer(many=True, source='establishment_subtypes')
|
||||
type = EstablishmentTypeBaseSerializer(source='establishment_type', read_only=True)
|
||||
subtypes = EstablishmentSubTypeBaseSerializer(many=True, source='establishment_subtypes')
|
||||
awards = AwardSerializer(many=True)
|
||||
schedule = ScheduleRUDSerializer(many=True, allow_null=True)
|
||||
phones = ContactPhonesSerializer(read_only=True, many=True)
|
||||
|
|
@ -306,17 +367,3 @@ class EstablishmentFavoritesCreateSerializer(serializers.ModelSerializer):
|
|||
})
|
||||
return super().create(validated_data)
|
||||
|
||||
|
||||
class EstablishmentTagListSerializer(serializers.ModelSerializer):
|
||||
"""List establishment tag serializer."""
|
||||
id = serializers.IntegerField(source='metadata.id')
|
||||
label_translated = serializers.CharField(
|
||||
source='metadata.label_translated', read_only=True, allow_null=True)
|
||||
|
||||
class Meta:
|
||||
"""Meta class."""
|
||||
model = MetaDataContent
|
||||
fields = [
|
||||
'id',
|
||||
'label_translated',
|
||||
]
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@ urlpatterns = [
|
|||
name='schedule-rud'),
|
||||
path('<int:pk>/schedule/', views.EstablishmentScheduleCreateView.as_view(),
|
||||
name='schedule-create'),
|
||||
path('attach-tag/', views.EstablishmentTagCreateView.as_view(), name='attach-tag'),
|
||||
path('menus/', views.MenuListCreateView.as_view(), name='menu-list'),
|
||||
path('menus/<int:pk>/', views.MenuRUDView.as_view(), name='menu-rud'),
|
||||
path('plates/', views.PlateListCreateView.as_view(), name='plates'),
|
||||
|
|
@ -26,4 +27,13 @@ urlpatterns = [
|
|||
path('emails/<int:pk>/', views.EmailRUDView.as_view(), name='emails-rud'),
|
||||
path('employees/', views.EmployeeListCreateView.as_view(), name='employees'),
|
||||
path('employees/<int:pk>/', views.EmployeeRUDView.as_view(), name='employees-rud'),
|
||||
]
|
||||
path('types/', views.EstablishmentTypeListCreateView.as_view(), name='type-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/attach-tag-category/', views.EstablishmentTypeAttachTagCategoryView.as_view(),
|
||||
name='type-attach-tag-category'),
|
||||
path('subtypes/', views.EstablishmentSubtypeListCreateView.as_view(), name='subtype-list'),
|
||||
path('subtypes/<int:pk>/', views.EstablishmentSubtypeRUDView.as_view(), name='subtype-rud'),
|
||||
path('subtypes/attach-tag-category/', views.EstablishmentSubTypeAttachTagCategoryView.as_view(),
|
||||
name='subtype-attach-tag-category'),
|
||||
]
|
||||
|
|
|
|||
|
|
@ -7,7 +7,6 @@ app_name = 'establishment'
|
|||
|
||||
urlpatterns = [
|
||||
path('', views.EstablishmentListView.as_view(), name='list'),
|
||||
path('tags/', views.EstablishmentTagListView.as_view(), name='tags'),
|
||||
path('recent-reviews/', views.EstablishmentRecentReviewListView.as_view(),
|
||||
name='recent-reviews'),
|
||||
path('slug/<slug:slug>/', views.EstablishmentRetrieveView.as_view(), name='detail'),
|
||||
|
|
|
|||
|
|
@ -4,4 +4,4 @@ from establishment.urls.common import urlpatterns as common_urlpatterns
|
|||
|
||||
urlpatterns = []
|
||||
|
||||
urlpatterns.extend(common_urlpatterns)
|
||||
urlpatterns.extend(common_urlpatterns)
|
||||
|
|
|
|||
|
|
@ -1,9 +1,11 @@
|
|||
"""Establishment app views."""
|
||||
from django.shortcuts import get_object_or_404
|
||||
from rest_framework import generics, status, permissions
|
||||
|
||||
from rest_framework import generics
|
||||
|
||||
from establishment import models
|
||||
from establishment import serializers
|
||||
from establishment import models, serializers
|
||||
from rest_framework.response import Response
|
||||
from timetable.serialziers import ScheduleRUDSerializer, ScheduleCreateSerializer
|
||||
from establishment.filters import EstablishmentTypeTagFilter
|
||||
|
||||
|
||||
class EstablishmentMixinViews:
|
||||
|
|
@ -25,6 +27,53 @@ class EstablishmentRUDView(generics.RetrieveUpdateDestroyAPIView):
|
|||
serializer_class = serializers.EstablishmentRUDSerializer
|
||||
|
||||
|
||||
class EstablishmentScheduleRUDView(generics.RetrieveUpdateDestroyAPIView):
|
||||
"""Establishment schedule RUD view"""
|
||||
serializer_class = ScheduleRUDSerializer
|
||||
|
||||
def get_object(self):
|
||||
"""
|
||||
Returns the object the view is displaying.
|
||||
"""
|
||||
establishment_pk = self.kwargs['pk']
|
||||
schedule_id = self.kwargs['schedule_id']
|
||||
|
||||
establishment = get_object_or_404(klass=models.Establishment.objects.all(),
|
||||
pk=establishment_pk)
|
||||
schedule = get_object_or_404(klass=establishment.schedule,
|
||||
id=schedule_id)
|
||||
|
||||
# May raise a permission denied
|
||||
self.check_object_permissions(self.request, establishment)
|
||||
self.check_object_permissions(self.request, schedule)
|
||||
|
||||
return schedule
|
||||
|
||||
|
||||
class EstablishmentScheduleCreateView(generics.CreateAPIView):
|
||||
"""Establishment schedule Create view"""
|
||||
serializer_class = ScheduleCreateSerializer
|
||||
|
||||
|
||||
class EstablishmentTypeAttachTagCategoryView(generics.CreateAPIView):
|
||||
"""Attach tag category to establishment type."""
|
||||
serializer_class = serializers.EstablishmentTypeTagCategoryBaseSerializer
|
||||
|
||||
def get_queryset(self):
|
||||
"""Override get_queryset method."""
|
||||
return models.EstablishmentTypeTagCategory.objects.with_base_related()
|
||||
|
||||
def post(self, request, *args, **kwargs):
|
||||
"""Overridden post-method."""
|
||||
super(EstablishmentTypeAttachTagCategoryView, self).post(request)
|
||||
return Response(status=status.HTTP_200_OK)
|
||||
|
||||
|
||||
class EstablishmentTagCreateView(EstablishmentMixinViews, generics.CreateAPIView):
|
||||
"""Attach tag to establishment."""
|
||||
serializer_class = serializers.EstablishmentTagCreateSerializer
|
||||
|
||||
|
||||
class MenuListCreateView(generics.ListCreateAPIView):
|
||||
"""Menu list create view."""
|
||||
serializer_class = serializers.MenuSerializers
|
||||
|
|
@ -100,3 +149,52 @@ class EmployeeRUDView(generics.RetrieveUpdateDestroyAPIView):
|
|||
"""Social RUD view."""
|
||||
serializer_class = serializers.EmployeeBackSerializers
|
||||
queryset = models.Employee.objects.all()
|
||||
|
||||
|
||||
class EstablishmentTypeListCreateView(generics.ListCreateAPIView):
|
||||
"""Establishment type list/create view."""
|
||||
serializer_class = serializers.EstablishmentTypeBaseSerializer
|
||||
queryset = models.EstablishmentType.objects.all()
|
||||
pagination_class = None
|
||||
|
||||
|
||||
class EstablishmentTypeRUDView(generics.RetrieveUpdateDestroyAPIView):
|
||||
"""Establishment type retrieve/update/destroy view."""
|
||||
serializer_class = serializers.EstablishmentTypeBaseSerializer
|
||||
queryset = models.EstablishmentType.objects.all()
|
||||
|
||||
|
||||
class EstablishmentTypeTagListView(generics.ListAPIView):
|
||||
"""List of tags with categories by establishment type."""
|
||||
serializer_class = serializers.EstablishmentTagsByType
|
||||
queryset = models.EstablishmentType.objects.with_base_related()
|
||||
filter_class = EstablishmentTypeTagFilter
|
||||
permission_classes = (permissions.AllowAny, )
|
||||
pagination_class = None
|
||||
|
||||
|
||||
class EstablishmentSubtypeListCreateView(generics.ListCreateAPIView):
|
||||
"""Establishment subtype list/create view."""
|
||||
serializer_class = serializers.EstablishmentSubTypeBaseSerializer
|
||||
queryset = models.EstablishmentSubType.objects.all()
|
||||
pagination_class = None
|
||||
|
||||
|
||||
class EstablishmentSubtypeRUDView(generics.RetrieveUpdateDestroyAPIView):
|
||||
"""Establishment subtype retrieve/update/destroy view."""
|
||||
serializer_class = serializers.EstablishmentSubTypeBaseSerializer
|
||||
queryset = models.EstablishmentSubType.objects.all()
|
||||
|
||||
|
||||
class EstablishmentSubTypeAttachTagCategoryView(generics.CreateAPIView):
|
||||
"""Attach tag category to establishment subtype."""
|
||||
serializer_class = serializers.EstablishmentSubTypeTagCategoryBaseSerializer
|
||||
|
||||
def get_queryset(self):
|
||||
"""Override get_queryset method."""
|
||||
return models.EstablishmentSubTypeTagCategory.objects.with_base_related()
|
||||
|
||||
def post(self, request, *args, **kwargs):
|
||||
"""Overridden post-method."""
|
||||
super(EstablishmentSubTypeAttachTagCategoryView, self).post(request)
|
||||
return Response(status=status.HTTP_200_OK)
|
||||
|
|
|
|||
|
|
@ -9,7 +9,6 @@ from establishment import filters
|
|||
from establishment import models, serializers
|
||||
from main import methods
|
||||
from main.models import MetaDataContent
|
||||
from timetable.serialziers import ScheduleRUDSerializer, ScheduleCreateSerializer
|
||||
from utils.pagination import EstablishmentPortionPagination
|
||||
|
||||
|
||||
|
|
@ -19,9 +18,10 @@ class EstablishmentMixinView:
|
|||
permission_classes = (permissions.AllowAny,)
|
||||
|
||||
def get_queryset(self):
|
||||
"""Overrided method 'get_queryset'."""
|
||||
return models.Establishment.objects.published().with_base_related().\
|
||||
annotate_in_favorites(self.request.user)
|
||||
"""Overridden method 'get_queryset'."""
|
||||
return models.Establishment.objects.published() \
|
||||
.with_base_related() \
|
||||
.annotate_in_favorites(self.request.user)
|
||||
|
||||
|
||||
class EstablishmentListView(EstablishmentMixinView, generics.ListAPIView):
|
||||
|
|
@ -84,7 +84,7 @@ class EstablishmentTypeListView(generics.ListAPIView):
|
|||
"""Resource for getting a list of establishment types."""
|
||||
|
||||
permission_classes = (permissions.AllowAny,)
|
||||
serializer_class = serializers.EstablishmentTypeSerializer
|
||||
serializer_class = serializers.EstablishmentTypeBaseSerializer
|
||||
queryset = models.EstablishmentType.objects.all()
|
||||
|
||||
|
||||
|
|
@ -174,44 +174,3 @@ class EstablishmentNearestRetrieveView(EstablishmentListView, generics.ListAPIVi
|
|||
return qs.by_distance_from_point(**{k: v for k, v in filter_kwargs.items()
|
||||
if v is not None})
|
||||
return qs
|
||||
|
||||
|
||||
class EstablishmentTagListView(generics.ListAPIView):
|
||||
"""List view for establishment tags."""
|
||||
serializer_class = serializers.EstablishmentTagListSerializer
|
||||
permission_classes = (permissions.AllowAny,)
|
||||
pagination_class = None
|
||||
|
||||
def get_queryset(self):
|
||||
"""Override get_queryset method"""
|
||||
return MetaDataContent.objects.by_content_type(app_label='establishment',
|
||||
model='establishment')\
|
||||
.distinct('metadata__label')
|
||||
|
||||
|
||||
class EstablishmentScheduleRUDView(generics.RetrieveUpdateDestroyAPIView):
|
||||
"""Establishment schedule RUD view"""
|
||||
serializer_class = ScheduleRUDSerializer
|
||||
|
||||
def get_object(self):
|
||||
"""
|
||||
Returns the object the view is displaying.
|
||||
"""
|
||||
establishment_pk = self.kwargs['pk']
|
||||
schedule_id = self.kwargs['schedule_id']
|
||||
|
||||
establishment = get_object_or_404(klass=models.Establishment.objects.all(),
|
||||
pk=establishment_pk)
|
||||
schedule = get_object_or_404(klass=establishment.schedule,
|
||||
id=schedule_id)
|
||||
|
||||
# May raise a permission denied
|
||||
self.check_object_permissions(self.request, establishment)
|
||||
self.check_object_permissions(self.request, schedule)
|
||||
|
||||
return schedule
|
||||
|
||||
|
||||
class EstablishmentScheduleCreateView(generics.CreateAPIView):
|
||||
"""Establishment schedule Create view"""
|
||||
serializer_class = ScheduleCreateSerializer
|
||||
|
|
|
|||
|
|
@ -25,22 +25,6 @@ class AwardAdmin(admin.ModelAdmin):
|
|||
# list_display_links = ['id', '__str__']
|
||||
|
||||
|
||||
@admin.register(models.MetaData)
|
||||
class MetaDataAdmin(admin.ModelAdmin):
|
||||
"""MetaData admin."""
|
||||
|
||||
|
||||
@admin.register(models.MetaDataCategory)
|
||||
class MetaDataCategoryAdmin(admin.ModelAdmin):
|
||||
"""MetaData admin."""
|
||||
list_display = ['id', 'country', 'content_type']
|
||||
|
||||
|
||||
@admin.register(models.MetaDataContent)
|
||||
class MetaDataContentAdmin(admin.ModelAdmin):
|
||||
"""MetaDataContent admin"""
|
||||
|
||||
|
||||
@admin.register(models.Currency)
|
||||
class CurrencContentAdmin(admin.ModelAdmin):
|
||||
"""CurrencContent admin"""
|
||||
|
|
|
|||
24
apps/news/migrations/0021_auto_20191009_1408.py
Normal file
24
apps/news/migrations/0021_auto_20191009_1408.py
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
# Generated by Django 2.2.4 on 2019-10-09 14:08
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('tag', '0002_auto_20191009_1408'),
|
||||
('news', '0020_remove_news_author'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='news',
|
||||
name='tags',
|
||||
field=models.ManyToManyField(related_name='news', to='tag.Tag', verbose_name='Tags'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='newstype',
|
||||
name='tag_categories',
|
||||
field=models.ManyToManyField(related_name='news_types', to='tag.TagCategory'),
|
||||
),
|
||||
]
|
||||
|
|
@ -12,6 +12,8 @@ class NewsType(models.Model):
|
|||
"""NewsType model."""
|
||||
|
||||
name = models.CharField(_('name'), max_length=250)
|
||||
tag_categories = models.ManyToManyField('tag.TagCategory',
|
||||
related_name='news_types')
|
||||
|
||||
class Meta:
|
||||
"""Meta class."""
|
||||
|
|
@ -133,8 +135,8 @@ class News(BaseAttributes, TranslatedFieldsMixin):
|
|||
country = models.ForeignKey('location.Country', blank=True, null=True,
|
||||
on_delete=models.SET_NULL,
|
||||
verbose_name=_('country'))
|
||||
tags = generic.GenericRelation(to='main.MetaDataContent')
|
||||
|
||||
tags = models.ManyToManyField('tag.Tag', related_name='news',
|
||||
verbose_name=_('Tags'))
|
||||
gallery = models.ManyToManyField('gallery.Image', through='news.NewsGallery')
|
||||
ratings = generic.GenericRelation(Rating)
|
||||
|
||||
|
|
|
|||
|
|
@ -6,8 +6,8 @@ from account.serializers.common import UserBaseSerializer
|
|||
from gallery.models import Image
|
||||
from location import models as location_models
|
||||
from location.serializers import CountrySimpleSerializer
|
||||
from main.serializers import MetaDataContentSerializer
|
||||
from news import models
|
||||
from tag.serializers import TagBaseSerializer
|
||||
from utils.serializers import TranslatedField, ProjectModelSerializer
|
||||
|
||||
|
||||
|
|
@ -100,7 +100,7 @@ class NewsBaseSerializer(ProjectModelSerializer):
|
|||
|
||||
# related fields
|
||||
news_type = NewsTypeSerializer(read_only=True)
|
||||
tags = MetaDataContentSerializer(read_only=True, many=True)
|
||||
tags = TagBaseSerializer(read_only=True, many=True)
|
||||
gallery = NewsImageSerializer(read_only=True, many=True)
|
||||
|
||||
class Meta:
|
||||
|
|
|
|||
|
|
@ -7,5 +7,7 @@ app_name = 'news'
|
|||
urlpatterns = [
|
||||
path('', views.NewsListView.as_view(), name='list'),
|
||||
path('types/', views.NewsTypeListView.as_view(), name='type'),
|
||||
path('types/<int:pk>/tags/', views.NewsTypeTagsView.as_view(),
|
||||
name='type-tags'),
|
||||
path('slug/<slug:slug>/', views.NewsDetailView.as_view(), name='rud'),
|
||||
]
|
||||
|
|
|
|||
|
|
@ -1,4 +1,6 @@
|
|||
"""News app views."""
|
||||
from django.shortcuts import get_object_or_404
|
||||
from rest_framework import generics, permissions
|
||||
from django.conf import settings
|
||||
from django.db.transaction import on_commit
|
||||
from django.shortcuts import get_object_or_404
|
||||
|
|
@ -8,6 +10,8 @@ from rest_framework.response import Response
|
|||
from gallery.tasks import delete_image
|
||||
from news import filters, models, serializers
|
||||
from rating.tasks import add_rating
|
||||
from tag.serializers import TagCategoryDetailSerializer
|
||||
|
||||
|
||||
class NewsMixinView:
|
||||
"""News mixin."""
|
||||
|
|
@ -40,6 +44,7 @@ class NewsDetailView(NewsMixinView, generics.RetrieveAPIView):
|
|||
"""Override get_queryset method."""
|
||||
return super().get_queryset().with_extended_related()
|
||||
|
||||
|
||||
class NewsTypeListView(generics.ListAPIView):
|
||||
"""NewsType list view."""
|
||||
|
||||
|
|
@ -49,6 +54,18 @@ class NewsTypeListView(generics.ListAPIView):
|
|||
serializer_class = serializers.NewsTypeSerializer
|
||||
|
||||
|
||||
class NewsTypeTagsView(generics.ListAPIView):
|
||||
"""Resource to get a list of tags for a news type."""
|
||||
|
||||
pagination_class = None
|
||||
permission_classes = (permissions.AllowAny, )
|
||||
serializer_class = TagCategoryDetailSerializer
|
||||
|
||||
def get_queryset(self):
|
||||
news_type = get_object_or_404(models.NewsType, pk=self.kwargs.get('pk'))
|
||||
return news_type.tag_categories.with_related()
|
||||
|
||||
|
||||
class NewsBackOfficeMixinView:
|
||||
"""News back office mixin view."""
|
||||
|
||||
|
|
|
|||
|
|
@ -21,24 +21,29 @@ class EstablishmentDocument(Document):
|
|||
properties={
|
||||
'id': fields.IntegerField(),
|
||||
'name': fields.ObjectField(attr='name_indexing',
|
||||
properties=OBJECT_FIELD_PROPERTIES)
|
||||
properties=OBJECT_FIELD_PROPERTIES),
|
||||
'tag_categories': fields.ObjectField(properties={
|
||||
'tag_category': fields.ObjectField(
|
||||
properties={
|
||||
'id': fields.IntegerField()
|
||||
}
|
||||
)
|
||||
}),
|
||||
})
|
||||
establishment_subtypes = fields.ObjectField(
|
||||
properties={
|
||||
'id': fields.IntegerField(),
|
||||
'name': fields.ObjectField(attr='name_indexing',
|
||||
properties=OBJECT_FIELD_PROPERTIES)
|
||||
properties={
|
||||
'id': fields.IntegerField(),
|
||||
}),
|
||||
},
|
||||
multi=True)
|
||||
tags = fields.ObjectField(
|
||||
properties={
|
||||
'id': fields.IntegerField(attr='metadata.id'),
|
||||
'label': fields.ObjectField(attr='metadata.label_indexing',
|
||||
properties=OBJECT_FIELD_PROPERTIES),
|
||||
'category': fields.ObjectField(attr='metadata.category',
|
||||
properties={
|
||||
'id': fields.IntegerField(),
|
||||
})
|
||||
'tag': fields.ObjectField(properties={
|
||||
'id': fields.IntegerField(),
|
||||
}),
|
||||
},
|
||||
multi=True)
|
||||
address = fields.ObjectField(
|
||||
|
|
|
|||
0
apps/tag/__init__.py
Normal file
0
apps/tag/__init__.py
Normal file
12
apps/tag/admin.py
Normal file
12
apps/tag/admin.py
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
from django.contrib import admin
|
||||
from .models import Tag, TagCategory
|
||||
|
||||
|
||||
@admin.register(Tag)
|
||||
class TagAdmin(admin.ModelAdmin):
|
||||
"""Admin model for model Tag."""
|
||||
|
||||
|
||||
@admin.register(TagCategory)
|
||||
class TagCategoryAdmin(admin.ModelAdmin):
|
||||
"""Admin model for model TagCategory."""
|
||||
7
apps/tag/apps.py
Normal file
7
apps/tag/apps.py
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
from django.apps import AppConfig
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
|
||||
class TagConfig(AppConfig):
|
||||
name = 'tag'
|
||||
verbose_name = _('tag')
|
||||
44
apps/tag/migrations/0001_initial.py
Normal file
44
apps/tag/migrations/0001_initial.py
Normal file
|
|
@ -0,0 +1,44 @@
|
|||
# Generated by Django 2.2.4 on 2019-10-09 07:15
|
||||
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
import utils.models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
initial = True
|
||||
|
||||
dependencies = [
|
||||
('location', '0010_auto_20190904_0711'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name='TagCategory',
|
||||
fields=[
|
||||
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('label', utils.models.TJSONField(blank=True, default=None, help_text='{"en-GB":"some text"}', null=True, verbose_name='label')),
|
||||
('public', models.BooleanField(default=False)),
|
||||
('country', models.ForeignKey(default=None, null=True, on_delete=django.db.models.deletion.SET_NULL, to='location.Country')),
|
||||
],
|
||||
options={
|
||||
'verbose_name': 'tag category',
|
||||
'verbose_name_plural': 'tag categories',
|
||||
},
|
||||
bases=(utils.models.TranslatedFieldsMixin, models.Model),
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='Tag',
|
||||
fields=[
|
||||
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('label', utils.models.TJSONField(blank=True, default=None, help_text='{"en-GB":"some text"}', null=True, verbose_name='label')),
|
||||
('category', models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='tags', to='tag.TagCategory', verbose_name='category')),
|
||||
],
|
||||
options={
|
||||
'verbose_name': 'tag',
|
||||
'verbose_name_plural': 'tags',
|
||||
},
|
||||
bases=(utils.models.TranslatedFieldsMixin, models.Model),
|
||||
),
|
||||
]
|
||||
27
apps/tag/migrations/0002_auto_20191009_1408.py
Normal file
27
apps/tag/migrations/0002_auto_20191009_1408.py
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
# Generated by Django 2.2.4 on 2019-10-09 14:08
|
||||
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('tag', '0001_initial'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterModelOptions(
|
||||
name='tag',
|
||||
options={'verbose_name': 'Tag', 'verbose_name_plural': 'Tags'},
|
||||
),
|
||||
migrations.AlterModelOptions(
|
||||
name='tagcategory',
|
||||
options={'verbose_name': 'Tag category', 'verbose_name_plural': 'Tag categories'},
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='tag',
|
||||
name='category',
|
||||
field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.PROTECT, related_name='tags', to='tag.TagCategory', verbose_name='Category'),
|
||||
),
|
||||
]
|
||||
0
apps/tag/migrations/__init__.py
Normal file
0
apps/tag/migrations/__init__.py
Normal file
66
apps/tag/models.py
Normal file
66
apps/tag/models.py
Normal file
|
|
@ -0,0 +1,66 @@
|
|||
"""Tag app models."""
|
||||
from django.db import models
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
from configuration.models import TranslationSettings
|
||||
from utils.models import TJSONField, TranslatedFieldsMixin
|
||||
|
||||
|
||||
class Tag(TranslatedFieldsMixin, models.Model):
|
||||
"""Tag model."""
|
||||
|
||||
label = TJSONField(blank=True, null=True, default=None,
|
||||
verbose_name=_('label'),
|
||||
help_text='{"en-GB":"some text"}')
|
||||
category = models.ForeignKey('TagCategory', on_delete=models.PROTECT,
|
||||
null=True, related_name='tags',
|
||||
verbose_name=_('Category'))
|
||||
|
||||
class Meta:
|
||||
"""Meta class."""
|
||||
|
||||
verbose_name = _('Tag')
|
||||
verbose_name_plural = _('Tags')
|
||||
|
||||
def __str__(self):
|
||||
label = 'None'
|
||||
lang = TranslationSettings.get_solo().default_language
|
||||
if self.label and lang in self.label:
|
||||
label = self.label[lang]
|
||||
return f'id:{self.id}-{label}'
|
||||
|
||||
|
||||
class TagCategoryQuerySet(models.QuerySet):
|
||||
"""Extended queryset for TagCategory model."""
|
||||
|
||||
def by_news_type(self, news_type):
|
||||
return self.filter(news_types=news_type)
|
||||
|
||||
def with_related(self):
|
||||
return self.select_related('country').prefetch_related('tags')
|
||||
|
||||
|
||||
class TagCategory(TranslatedFieldsMixin, models.Model):
|
||||
"""Tag base category model."""
|
||||
|
||||
label = TJSONField(blank=True, null=True, default=None,
|
||||
verbose_name=_('label'),
|
||||
help_text='{"en-GB":"some text"}')
|
||||
country = models.ForeignKey('location.Country',
|
||||
on_delete=models.SET_NULL, null=True,
|
||||
default=None)
|
||||
public = models.BooleanField(default=False)
|
||||
|
||||
objects = TagCategoryQuerySet.as_manager()
|
||||
|
||||
class Meta:
|
||||
"""Meta class."""
|
||||
|
||||
verbose_name = _('Tag category')
|
||||
verbose_name_plural = _('Tag categories')
|
||||
|
||||
def __str__(self):
|
||||
label = 'None'
|
||||
lang = TranslationSettings.get_solo().default_language
|
||||
if self.label and lang in self.label:
|
||||
label = self.label[lang]
|
||||
return f'id:{self.id}-{label}'
|
||||
59
apps/tag/serializers.py
Normal file
59
apps/tag/serializers.py
Normal file
|
|
@ -0,0 +1,59 @@
|
|||
"""Tag serializers."""
|
||||
from rest_framework import serializers
|
||||
from tag import models
|
||||
from utils.serializers import TranslatedField
|
||||
|
||||
|
||||
class TagBaseSerializer(serializers.ModelSerializer):
|
||||
"""Serializer for model Tag."""
|
||||
|
||||
label_translated = TranslatedField()
|
||||
|
||||
class Meta:
|
||||
"""Meta class."""
|
||||
|
||||
model = models.Tag
|
||||
fields = [
|
||||
'id',
|
||||
'label',
|
||||
'label_translated',
|
||||
'category'
|
||||
]
|
||||
extra_kwargs = {
|
||||
'label': {'write_only': True},
|
||||
'category': {'write_only': True}
|
||||
}
|
||||
|
||||
|
||||
class TagCategoryBaseSerializer(serializers.ModelSerializer):
|
||||
"""Serializer for model TagCategory."""
|
||||
|
||||
label_translated = TranslatedField()
|
||||
country_translated = TranslatedField(source='country.name_translated')
|
||||
|
||||
class Meta:
|
||||
"""Meta class."""
|
||||
|
||||
model = models.TagCategory
|
||||
fields = (
|
||||
'id',
|
||||
'label',
|
||||
'label_translated',
|
||||
'country',
|
||||
'country_translated',
|
||||
'public',
|
||||
)
|
||||
extra_kwargs = {
|
||||
'label': {'write_only': True},
|
||||
'country': {'write_only': True},
|
||||
}
|
||||
|
||||
|
||||
class TagCategoryDetailSerializer(TagCategoryBaseSerializer):
|
||||
|
||||
tags = TagBaseSerializer(many=True)
|
||||
|
||||
class Meta(TagCategoryBaseSerializer.Meta):
|
||||
"""Meta class."""
|
||||
|
||||
fields = TagCategoryBaseSerializer.Meta.fields + ('tags', )
|
||||
3
apps/tag/tests.py
Normal file
3
apps/tag/tests.py
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
from django.test import TestCase
|
||||
|
||||
# Create your tests here.
|
||||
10
apps/tag/urls.py
Normal file
10
apps/tag/urls.py
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
"""Urlconf for app tag."""
|
||||
from django.urls import path
|
||||
from . import views
|
||||
|
||||
app_name = 'tag'
|
||||
|
||||
urlpatterns = [
|
||||
path('', views.TagListCreateView.as_view(), name='list-create'),
|
||||
path('category/', views.TagCategoryListCreateView.as_view(), name='category-list-create'),
|
||||
]
|
||||
19
apps/tag/views.py
Normal file
19
apps/tag/views.py
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
"""Tag views."""
|
||||
from rest_framework import generics
|
||||
from tag import serializers, models
|
||||
|
||||
|
||||
class TagListCreateView(generics.ListCreateAPIView):
|
||||
"""List/create tag view."""
|
||||
|
||||
queryset = models.Tag.objects.all()
|
||||
serializer_class = serializers.TagBaseSerializer
|
||||
pagination_class = None
|
||||
|
||||
|
||||
class TagCategoryListCreateView(generics.ListCreateAPIView):
|
||||
"""List/create tag category view."""
|
||||
|
||||
queryset = models.TagCategory.objects.all()
|
||||
serializer_class = serializers.TagCategoryBaseSerializer
|
||||
pagination_class = None
|
||||
|
|
@ -73,6 +73,7 @@ PROJECT_APPS = [
|
|||
'comment.apps.CommentConfig',
|
||||
'favorites.apps.FavoritesConfig',
|
||||
'rating.apps.RatingConfig',
|
||||
'tag.apps.TagConfig',
|
||||
]
|
||||
|
||||
EXTERNAL_APPS = [
|
||||
|
|
|
|||
|
|
@ -3,11 +3,11 @@ from django.urls import path, include
|
|||
app_name = 'back'
|
||||
|
||||
urlpatterns = [
|
||||
path('gallery/', include(('gallery.urls', 'gallery'),
|
||||
namespace='gallery')),
|
||||
path('gallery/', include(('gallery.urls', 'gallery'), namespace='gallery')),
|
||||
path('establishments/', include('establishment.urls.back')),
|
||||
path('location/', include('location.urls.back')),
|
||||
path('news/', include('news.urls.back')),
|
||||
path('tags/', include(('tag.urls', 'tag'), namespace='tag'))
|
||||
path('account/', include('account.urls.back')),
|
||||
path('comment/', include('comment.urls.back')),
|
||||
]
|
||||
]
|
||||
|
|
|
|||
|
|
@ -24,7 +24,8 @@ urlpatterns = [
|
|||
path('collections/', include('collection.urls.web')),
|
||||
path('establishments/', include('establishment.urls.web')),
|
||||
path('news/', include('news.urls.web')),
|
||||
path('notifications/', include(('notification.urls.web', "notification"), namespace='notification')),
|
||||
path('notifications/', include(('notification.urls.web', "notification"),
|
||||
namespace='notification')),
|
||||
path('partner/', include('partner.urls.web')),
|
||||
path('location/', include('location.urls.web')),
|
||||
path('main/', include('main.urls')),
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user