Fix conflict
This commit is contained in:
commit
264e7bcb2a
|
|
@ -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')
|
||||
|
||||
|
|
|
|||
|
|
@ -1,10 +1,10 @@
|
|||
"""Authorization app celery tasks."""
|
||||
import logging
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
from celery import shared_task
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
from account import models as account_models
|
||||
from smtplib import SMTPException
|
||||
|
||||
logging.basicConfig(format='[%(levelname)s] %(message)s', level=logging.INFO)
|
||||
logger = logging.getLogger(__name__)
|
||||
|
|
|
|||
|
|
@ -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,4 @@ class MenuAdmin(admin.ModelAdmin):
|
|||
"""Get user's short name."""
|
||||
return obj.category_translated
|
||||
|
||||
category_translated.short_description = _('category')
|
||||
category_translated.short_description = _('category')
|
||||
|
|
|
|||
|
|
@ -10,6 +10,10 @@ class EstablishmentFilter(filters.FilterSet):
|
|||
tag_id = filters.NumberFilter(field_name='tags__metadata__id',)
|
||||
award_id = filters.NumberFilter(field_name='awards__id',)
|
||||
search = filters.CharFilter(method='search_text')
|
||||
est_type = filters.ChoiceFilter(choices=models.EstablishmentType.INDEX_NAME_TYPES,
|
||||
method='by_type')
|
||||
est_subtype = filters.ChoiceFilter(choices=models.EstablishmentSubType.INDEX_NAME_TYPES,
|
||||
method='by_subtype')
|
||||
|
||||
class Meta:
|
||||
"""Meta class."""
|
||||
|
|
@ -19,6 +23,8 @@ class EstablishmentFilter(filters.FilterSet):
|
|||
'tag_id',
|
||||
'award_id',
|
||||
'search',
|
||||
'est_type',
|
||||
'est_subtype',
|
||||
)
|
||||
|
||||
def search_text(self, queryset, name, value):
|
||||
|
|
@ -26,3 +32,23 @@ class EstablishmentFilter(filters.FilterSet):
|
|||
if value not in EMPTY_VALUES:
|
||||
return queryset.search(value, locale=self.request.locale)
|
||||
return queryset
|
||||
|
||||
def by_type(self, queryset, name, value):
|
||||
return queryset.by_type(value)
|
||||
|
||||
def by_subtype(self, queryset, name, value):
|
||||
return queryset.by_subtype(value)
|
||||
|
||||
|
||||
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'),
|
||||
),
|
||||
]
|
||||
54
apps/establishment/migrations/0037_auto_20191015_1404.py
Normal file
54
apps/establishment/migrations/0037_auto_20191015_1404.py
Normal 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',
|
||||
),
|
||||
]
|
||||
|
|
@ -0,0 +1,35 @@
|
|||
# Generated by Django 2.2.4 on 2019-10-16 11:33
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
def fill_establishment_type(apps, schema_editor):
|
||||
# We can't import the Person model directly as it may be a newer
|
||||
# version than this migration expects. We use the historical version.
|
||||
EstablishmentType = apps.get_model('establishment', 'EstablishmentType')
|
||||
for n, et in enumerate(EstablishmentType.objects.all()):
|
||||
et.index_name = f'Type {n}'
|
||||
et.save()
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('establishment', '0037_auto_20191015_1404'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='establishmenttype',
|
||||
name='index_name',
|
||||
field=models.CharField(blank=True, db_index=True, max_length=50, null=True, unique=True, default=None, verbose_name='Index name'),
|
||||
),
|
||||
migrations.RunPython(fill_establishment_type, migrations.RunPython.noop),
|
||||
migrations.AlterField(
|
||||
model_name='establishmenttype',
|
||||
name='index_name',
|
||||
field=models.CharField(choices=[('restaurant', 'Restaurant'), ('artisan', 'Artisan'),
|
||||
('producer', 'Producer')], db_index=True, max_length=50,
|
||||
unique=True, verbose_name='Index name'),
|
||||
),
|
||||
]
|
||||
|
|
@ -0,0 +1,35 @@
|
|||
# Generated by Django 2.2.4 on 2019-10-18 13:47
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
def fill_establishment_subtype(apps, schema_editor):
|
||||
# We can't import the Person model directly as it may be a newer
|
||||
# version than this migration expects. We use the historical version.
|
||||
EstablishmentSubType = apps.get_model('establishment', 'EstablishmentSubType')
|
||||
for n, et in enumerate(EstablishmentSubType.objects.all()):
|
||||
et.index_name = f'Type {n}'
|
||||
et.save()
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('establishment', '0038_establishmenttype_index_name'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='establishmentsubtype',
|
||||
name='index_name',
|
||||
field=models.CharField(blank=True, db_index=True, max_length=50, null=True, unique=True, default=None, verbose_name='Index name'),
|
||||
),
|
||||
migrations.RunPython(fill_establishment_subtype),
|
||||
migrations.AlterField(
|
||||
model_name='establishmentsubtype',
|
||||
name='index_name',
|
||||
field=models.CharField(choices=[('winery', 'Winery'), ], db_index=True, max_length=50,
|
||||
unique=True, verbose_name='Index name'),
|
||||
),
|
||||
|
||||
]
|
||||
|
|
@ -15,7 +15,7 @@ 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 review.models import Review
|
||||
from utils.models import (ProjectBaseMixin, TJSONField, URLImageMixin,
|
||||
TranslatedFieldsMixin, BaseAttributes)
|
||||
|
|
@ -27,9 +27,26 @@ class EstablishmentType(TranslatedFieldsMixin, ProjectBaseMixin):
|
|||
|
||||
STR_FIELD_NAME = 'name'
|
||||
|
||||
# INDEX NAME CHOICES
|
||||
RESTAURANT = 'restaurant'
|
||||
ARTISAN = 'artisan'
|
||||
PRODUCER = 'producer'
|
||||
|
||||
INDEX_NAME_TYPES = (
|
||||
(RESTAURANT, _('Restaurant')),
|
||||
(ARTISAN, _('Artisan')),
|
||||
(PRODUCER, _('Producer')),
|
||||
)
|
||||
|
||||
name = TJSONField(blank=True, null=True, default=None, verbose_name=_('Description'),
|
||||
help_text='{"en-GB":"some text"}')
|
||||
index_name = models.CharField(max_length=50, choices=INDEX_NAME_TYPES,
|
||||
unique=True, db_index=True,
|
||||
verbose_name=_('Index name'))
|
||||
use_subtypes = models.BooleanField(_('Use subtypes'), default=True)
|
||||
tag_categories = models.ManyToManyField('tag.TagCategory',
|
||||
related_name='establishment_types',
|
||||
verbose_name=_('Tag'))
|
||||
|
||||
class Meta:
|
||||
"""Meta class."""
|
||||
|
|
@ -51,11 +68,24 @@ class EstablishmentSubTypeManager(models.Manager):
|
|||
class EstablishmentSubType(ProjectBaseMixin, TranslatedFieldsMixin):
|
||||
"""Establishment type model."""
|
||||
|
||||
# INDEX NAME CHOICES
|
||||
WINERY = 'winery'
|
||||
|
||||
INDEX_NAME_TYPES = (
|
||||
(WINERY, _('Winery')),
|
||||
)
|
||||
|
||||
name = TJSONField(blank=True, null=True, default=None, verbose_name=_('Description'),
|
||||
help_text='{"en-GB":"some text"}')
|
||||
index_name = models.CharField(max_length=50, choices=INDEX_NAME_TYPES,
|
||||
unique=True, db_index=True,
|
||||
verbose_name=_('Index name'))
|
||||
establishment_type = models.ForeignKey(EstablishmentType,
|
||||
on_delete=models.CASCADE,
|
||||
verbose_name=_('Type'))
|
||||
tag_categories = models.ManyToManyField('tag.TagCategory',
|
||||
related_name='establishment_subtypes',
|
||||
verbose_name=_('Tag'))
|
||||
|
||||
objects = EstablishmentSubTypeManager()
|
||||
|
||||
|
|
@ -75,11 +105,8 @@ class EstablishmentQuerySet(models.QuerySet):
|
|||
|
||||
def with_base_related(self):
|
||||
"""Return qs with related objects."""
|
||||
return self.select_related('address').prefetch_related(
|
||||
models.Prefetch('tags',
|
||||
MetaDataContent.objects.select_related(
|
||||
'metadata__category'))
|
||||
)
|
||||
return self.select_related('address', 'establishment_type').\
|
||||
prefetch_related('tags')
|
||||
|
||||
def with_extended_related(self):
|
||||
return self.select_related('establishment_type').\
|
||||
|
|
@ -87,6 +114,9 @@ class EstablishmentQuerySet(models.QuerySet):
|
|||
'phones').\
|
||||
prefetch_actual_employees()
|
||||
|
||||
def with_type_related(self):
|
||||
return self.prefetch_related('establishment_subtypes')
|
||||
|
||||
def search(self, value, locale=None):
|
||||
"""Search text in JSON fields."""
|
||||
if locale is not None:
|
||||
|
|
@ -234,6 +264,31 @@ class EstablishmentQuerySet(models.QuerySet):
|
|||
kwargs = {unit: radius}
|
||||
return self.filter(address__coordinates__distance_lte=(center, DistanceMeasure(**kwargs)))
|
||||
|
||||
def artisans(self):
|
||||
"""Return artisans."""
|
||||
return self.filter(establishment_type__index_name=EstablishmentType.ARTISAN)
|
||||
|
||||
def producers(self):
|
||||
"""Return producers."""
|
||||
return self.filter(establishment_type__index_name=EstablishmentType.PRODUCER)
|
||||
|
||||
def restaurants(self):
|
||||
"""Return restaurants."""
|
||||
return self.filter(establishment_type__index_name=EstablishmentType.RESTAURANT)
|
||||
|
||||
def wineries(self):
|
||||
"""Return wineries."""
|
||||
return self.producers().filter(
|
||||
establishment_subtypes__index_name=EstablishmentSubType.WINERY)
|
||||
|
||||
def by_type(self, value):
|
||||
"""Return QuerySet with type by value."""
|
||||
return self.filter(establishment_type__index_name=value)
|
||||
|
||||
def by_subtype(self, value):
|
||||
"""Return QuerySet with subtype by value."""
|
||||
return self.filter(establishment_subtypes__index_name=value)
|
||||
|
||||
|
||||
class Establishment(ProjectBaseMixin, URLImageMixin, TranslatedFieldsMixin):
|
||||
"""Establishment model."""
|
||||
|
|
@ -255,6 +310,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,
|
||||
|
|
@ -297,7 +353,11 @@ class Establishment(ProjectBaseMixin, URLImageMixin, TranslatedFieldsMixin):
|
|||
verbose_name=_('Establishment slug'), editable=True)
|
||||
|
||||
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')
|
||||
comments = generic.GenericRelation(to='comment.Comment')
|
||||
favorites = generic.GenericRelation(to='favorites.Favorites')
|
||||
|
|
@ -491,6 +551,7 @@ class ContactEmail(models.Model):
|
|||
def __str__(self):
|
||||
return f'{self.email}'
|
||||
|
||||
|
||||
#
|
||||
# class Wine(TranslatedFieldsMixin, models.Model):
|
||||
# """Wine model."""
|
||||
|
|
@ -568,3 +629,4 @@ class SocialNetwork(models.Model):
|
|||
|
||||
def __str__(self):
|
||||
return self.title
|
||||
|
||||
|
|
|
|||
|
|
@ -1,13 +1,12 @@
|
|||
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)
|
||||
from main.models import Currency
|
||||
from utils.decorators import with_base_attributes
|
||||
|
||||
|
||||
class EstablishmentListCreateSerializer(EstablishmentBaseSerializer):
|
||||
|
|
@ -21,7 +20,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 +54,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
|
||||
|
|
@ -141,4 +140,3 @@ class EmployeeBackSerializers(serializers.ModelSerializer):
|
|||
'user',
|
||||
'name'
|
||||
]
|
||||
|
||||
|
|
|
|||
|
|
@ -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,45 @@ 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 EstablishmentEmployeeSerializer(serializers.ModelSerializer):
|
||||
"""Serializer for actual employees."""
|
||||
|
||||
|
|
@ -144,8 +161,8 @@ class EstablishmentBaseSerializer(ProjectModelSerializer):
|
|||
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 = TagBaseSerializer(read_only=True, many=True)
|
||||
|
||||
class Meta:
|
||||
"""Meta class."""
|
||||
|
|
@ -171,8 +188,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 +323,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',
|
||||
]
|
||||
|
|
|
|||
|
|
@ -26,4 +26,8 @@ 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/<int:pk>/', views.EstablishmentTypeRUDView.as_view(), name='type-rud'),
|
||||
path('subtypes/', views.EstablishmentSubtypeListCreateView.as_view(), name='subtype-list'),
|
||||
path('subtypes/<int:pk>/', views.EstablishmentSubtypeRUDView.as_view(), name='subtype-rud'),
|
||||
]
|
||||
|
|
|
|||
|
|
@ -7,9 +7,9 @@ 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('wineries/', views.WineriesListView.as_view(), name='wineries-list'),
|
||||
path('slug/<slug:slug>/', views.EstablishmentRetrieveView.as_view(), name='detail'),
|
||||
path('slug/<slug:slug>/similar/', views.EstablishmentSimilarListView.as_view(), name='similar'),
|
||||
path('slug/<slug:slug>/comments/', views.EstablishmentCommentListView.as_view(), name='list-comments'),
|
||||
|
|
|
|||
|
|
@ -4,4 +4,4 @@ from establishment.urls.common import urlpatterns as common_urlpatterns
|
|||
|
||||
urlpatterns = []
|
||||
|
||||
urlpatterns.extend(common_urlpatterns)
|
||||
urlpatterns.extend(common_urlpatterns)
|
||||
|
|
|
|||
|
|
@ -1,10 +1,10 @@
|
|||
"""Establishment app views."""
|
||||
|
||||
from django.shortcuts import get_object_or_404
|
||||
from rest_framework import generics
|
||||
|
||||
from establishment import models
|
||||
from establishment import serializers
|
||||
from utils.permissions import IsCountryAdmin, IsEstablishmentManager
|
||||
from establishment import models, serializers
|
||||
from timetable.serialziers import ScheduleRUDSerializer, ScheduleCreateSerializer
|
||||
|
||||
|
||||
class EstablishmentMixinViews:
|
||||
|
|
@ -28,6 +28,34 @@ class EstablishmentRUDView(generics.RetrieveUpdateDestroyAPIView):
|
|||
permission_classes = [IsCountryAdmin|IsEstablishmentManager]
|
||||
|
||||
|
||||
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 MenuListCreateView(generics.ListCreateAPIView):
|
||||
"""Menu list create view."""
|
||||
serializer_class = serializers.MenuSerializers
|
||||
|
|
@ -113,3 +141,29 @@ 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 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()
|
||||
|
|
|
|||
|
|
@ -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
|
||||
from utils.permissions import IsCountryAdmin
|
||||
|
||||
|
|
@ -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()
|
||||
|
||||
|
||||
|
|
@ -176,42 +176,12 @@ class EstablishmentNearestRetrieveView(EstablishmentListView, generics.ListAPIVi
|
|||
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
|
||||
# Wineries
|
||||
# todo: find out about difference between subtypes data
|
||||
# class WineriesListView(EstablishmentListView):
|
||||
# """Return list establishments with type Wineries"""
|
||||
#
|
||||
# def get_queryset(self):
|
||||
# """Overridden get_queryset method."""
|
||||
# qs = super(WineriesListView, self).get_queryset()
|
||||
# return qs.with_type_related().wineries()
|
||||
|
|
|
|||
|
|
@ -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"""
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
from django.contrib import admin
|
||||
|
||||
from news import models
|
||||
from .tasks import send_email_with_news
|
||||
|
||||
|
||||
@admin.register(models.NewsType)
|
||||
class NewsTypeAdmin(admin.ModelAdmin):
|
||||
"""News type 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'))
|
||||
ratings = generic.GenericRelation(Rating)
|
||||
|
||||
objects = NewsQuerySet.as_manager()
|
||||
|
|
@ -163,4 +165,3 @@ class News(BaseAttributes, TranslatedFieldsMixin):
|
|||
@property
|
||||
def same_theme(self):
|
||||
return self.__class__.objects.same_theme(self)[:3]
|
||||
|
||||
|
|
|
|||
|
|
@ -3,8 +3,8 @@ from rest_framework import serializers
|
|||
from account.serializers.common import UserBaseSerializer
|
||||
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
|
||||
|
||||
|
||||
|
|
@ -27,7 +27,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)
|
||||
|
||||
class Meta:
|
||||
"""Meta class."""
|
||||
|
|
|
|||
|
|
@ -1,9 +1,11 @@
|
|||
"""News app views."""
|
||||
from django.shortcuts import get_object_or_404
|
||||
from rest_framework import generics, permissions
|
||||
from news import filters, models, serializers
|
||||
from rating.tasks import add_rating
|
||||
from utils.permissions import IsCountryAdmin, IsContentPageManager
|
||||
|
||||
|
||||
class NewsMixinView:
|
||||
"""News mixin."""
|
||||
|
||||
|
|
|
|||
|
|
@ -21,24 +21,22 @@ class EstablishmentDocument(Document):
|
|||
properties={
|
||||
'id': fields.IntegerField(),
|
||||
'name': fields.ObjectField(attr='name_indexing',
|
||||
properties=OBJECT_FIELD_PROPERTIES)
|
||||
properties=OBJECT_FIELD_PROPERTIES),
|
||||
})
|
||||
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',
|
||||
'id': fields.IntegerField(attr='id'),
|
||||
'label': fields.ObjectField(attr='label_indexing',
|
||||
properties=OBJECT_FIELD_PROPERTIES),
|
||||
'category': fields.ObjectField(attr='metadata.category',
|
||||
properties={
|
||||
'id': fields.IntegerField(),
|
||||
})
|
||||
},
|
||||
multi=True)
|
||||
address = fields.ObjectField(
|
||||
|
|
|
|||
|
|
@ -26,11 +26,9 @@ class NewsDocument(Document):
|
|||
web_url = fields.KeywordField(attr='web_url')
|
||||
tags = fields.ObjectField(
|
||||
properties={
|
||||
'id': fields.IntegerField(attr='metadata.id'),
|
||||
'label': fields.ObjectField(attr='metadata.label_indexing',
|
||||
'id': fields.IntegerField(attr='id'),
|
||||
'label': fields.ObjectField(attr='label_indexing',
|
||||
properties=OBJECT_FIELD_PROPERTIES),
|
||||
'category': fields.ObjectField(attr='metadata.category',
|
||||
properties={'id': fields.IntegerField()})
|
||||
},
|
||||
multi=True)
|
||||
|
||||
|
|
|
|||
|
|
@ -40,12 +40,8 @@ def update_document(sender, **kwargs):
|
|||
for establishment in establishments:
|
||||
registry.update(establishment)
|
||||
|
||||
if app_label == 'main':
|
||||
if model_name == 'metadata':
|
||||
establishments = Establishment.objects.filter(tags__metadata=instance)
|
||||
for establishment in establishments:
|
||||
registry.update(establishment)
|
||||
if model_name == 'metadatacontent':
|
||||
if app_label == 'tag':
|
||||
if model_name == 'tag':
|
||||
establishments = Establishment.objects.filter(tags=instance)
|
||||
for establishment in establishments:
|
||||
registry.update(establishment)
|
||||
|
|
@ -70,12 +66,8 @@ def update_news(sender, **kwargs):
|
|||
for news in qs:
|
||||
registry.update(news)
|
||||
|
||||
if app_label == 'main':
|
||||
if model_name == 'metadata':
|
||||
qs = News.objects.filter(tags__metadata=instance)
|
||||
for news in qs:
|
||||
registry.update(news)
|
||||
if model_name == 'metadatacontent':
|
||||
if app_label == 'tag':
|
||||
if model_name == 'tag':
|
||||
qs = News.objects.filter(tags=instance)
|
||||
for news in qs:
|
||||
registry.update(news)
|
||||
|
|
|
|||
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')
|
||||
42
apps/tag/filters.py
Normal file
42
apps/tag/filters.py
Normal file
|
|
@ -0,0 +1,42 @@
|
|||
"""Tag app filters."""
|
||||
from django_filters import rest_framework as filters
|
||||
from establishment.models import EstablishmentType
|
||||
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 = filters.ChoiceFilter(
|
||||
choices=EstablishmentType.INDEX_NAME_TYPES,
|
||||
method='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 by_establishment_type(self, queryset, name, value):
|
||||
return queryset.by_establishment_type(value)
|
||||
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'),
|
||||
),
|
||||
]
|
||||
19
apps/tag/migrations/0003_auto_20191018_0758.py
Normal file
19
apps/tag/migrations/0003_auto_20191018_0758.py
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
# Generated by Django 2.2.4 on 2019-10-18 07:58
|
||||
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('tag', '0002_auto_20191009_1408'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='tag',
|
||||
name='category',
|
||||
field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, 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
85
apps/tag/models.py
Normal file
85
apps/tag/models.py
Normal file
|
|
@ -0,0 +1,85 @@
|
|||
"""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.CASCADE,
|
||||
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 with_base_related(self):
|
||||
"""Select related objects."""
|
||||
return self.prefetch_related('tags')
|
||||
|
||||
def with_extended_related(self):
|
||||
"""Select related objects."""
|
||||
return self.select_related('country')
|
||||
|
||||
def for_news(self):
|
||||
"""Select tag categories for news."""
|
||||
return self.filter(news_types__isnull=True)
|
||||
|
||||
def for_establishments(self):
|
||||
"""Select tag categories for establishments."""
|
||||
return self.filter(models.Q(establishment_types__isnull=False) |
|
||||
models.Q(establishment_subtypes__isnull=False))
|
||||
|
||||
def by_establishment_type(self, index_name):
|
||||
"""Filter by establishment type index name."""
|
||||
return self.filter(establishment_types__index_name=index_name)
|
||||
|
||||
def with_tags(self, switcher=True):
|
||||
"""Filter by existing tags."""
|
||||
return self.filter(tags__isnull=not switcher)
|
||||
|
||||
|
||||
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}'
|
||||
167
apps/tag/serializers.py
Normal file
167
apps/tag/serializers.py
Normal file
|
|
@ -0,0 +1,167 @@
|
|||
"""Tag serializers."""
|
||||
from rest_framework import serializers
|
||||
from establishment.models import (Establishment, EstablishmentType,
|
||||
EstablishmentSubType)
|
||||
from news.models import News, NewsType
|
||||
from tag import models
|
||||
from utils.exceptions import (ObjectAlreadyAdded, BindingObjectNotFound,
|
||||
RemovedBindingObjectNotFound)
|
||||
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_translated',
|
||||
)
|
||||
|
||||
|
||||
class TagBackOfficeSerializer(TagBaseSerializer):
|
||||
"""Serializer for Tag model for Back office users."""
|
||||
|
||||
class Meta(TagBaseSerializer.Meta):
|
||||
"""Meta class."""
|
||||
|
||||
fields = TagBaseSerializer.Meta.fields + (
|
||||
'label',
|
||||
'category'
|
||||
)
|
||||
|
||||
|
||||
class TagCategoryBaseSerializer(serializers.ModelSerializer):
|
||||
"""Serializer for model TagCategory."""
|
||||
|
||||
label_translated = TranslatedField()
|
||||
tags = TagBaseSerializer(many=True, read_only=True)
|
||||
|
||||
class Meta:
|
||||
"""Meta class."""
|
||||
|
||||
model = models.TagCategory
|
||||
fields = (
|
||||
'id',
|
||||
'label_translated',
|
||||
'tags'
|
||||
)
|
||||
|
||||
|
||||
class TagCategoryBackOfficeDetailSerializer(TagCategoryBaseSerializer):
|
||||
"""Tag Category detail serializer for back-office users."""
|
||||
|
||||
country_translated = TranslatedField(source='country.name_translated')
|
||||
|
||||
class Meta(TagCategoryBaseSerializer.Meta):
|
||||
"""Meta class."""
|
||||
|
||||
fields = TagCategoryBaseSerializer.Meta.fields + (
|
||||
'label',
|
||||
'country',
|
||||
'country_translated',
|
||||
)
|
||||
|
||||
|
||||
class TagBindObjectSerializer(serializers.Serializer):
|
||||
"""Serializer for binding tag category and objects"""
|
||||
|
||||
ESTABLISHMENT = 'establishment'
|
||||
NEWS = 'news'
|
||||
|
||||
TYPE_CHOICES = (
|
||||
(ESTABLISHMENT, 'Establishment type'),
|
||||
(NEWS, 'News type'),
|
||||
)
|
||||
|
||||
type = serializers.ChoiceField(TYPE_CHOICES)
|
||||
object_id = serializers.IntegerField()
|
||||
|
||||
def validate(self, attrs):
|
||||
view = self.context.get('view')
|
||||
request = self.context.get('request')
|
||||
|
||||
obj_type = attrs.get('type')
|
||||
obj_id = attrs.get('object_id')
|
||||
|
||||
tag = view.get_object()
|
||||
attrs['tag'] = tag
|
||||
|
||||
if obj_type == self.ESTABLISHMENT:
|
||||
establishment = Establishment.objects.filter(pk=obj_id).first()
|
||||
if not establishment:
|
||||
raise BindingObjectNotFound()
|
||||
if request.method == 'POST' and tag.establishments.filter(
|
||||
pk=establishment.pk).exists():
|
||||
raise ObjectAlreadyAdded()
|
||||
if request.method == 'DELETE' and not tag.establishments.filter(
|
||||
pk=establishment.pk).exists():
|
||||
raise RemovedBindingObjectNotFound()
|
||||
attrs['related_object'] = establishment
|
||||
elif obj_type == self.NEWS:
|
||||
news = News.objects.filter(pk=obj_id).first()
|
||||
if not news:
|
||||
raise BindingObjectNotFound()
|
||||
if request.method == 'POST' and tag.news.filter(pk=news.pk).exists():
|
||||
raise ObjectAlreadyAdded()
|
||||
if request.method == 'DELETE' and not tag.news.filter(
|
||||
pk=news.pk).exists():
|
||||
raise RemovedBindingObjectNotFound()
|
||||
attrs['related_object'] = news
|
||||
return attrs
|
||||
|
||||
|
||||
class TagCategoryBindObjectSerializer(serializers.Serializer):
|
||||
"""Serializer for binding tag category and objects"""
|
||||
|
||||
ESTABLISHMENT_TYPE = 'establishment_type'
|
||||
NEWS_TYPE = 'news_type'
|
||||
|
||||
TYPE_CHOICES = (
|
||||
(ESTABLISHMENT_TYPE, 'Establishment type'),
|
||||
(NEWS_TYPE, 'News type'),
|
||||
)
|
||||
|
||||
type = serializers.ChoiceField(TYPE_CHOICES)
|
||||
object_id = serializers.IntegerField()
|
||||
|
||||
def validate(self, attrs):
|
||||
view = self.context.get('view')
|
||||
request = self.context.get('request')
|
||||
|
||||
obj_type = attrs.get('type')
|
||||
obj_id = attrs.get('object_id')
|
||||
|
||||
tag_category = view.get_object()
|
||||
attrs['tag_category'] = tag_category
|
||||
|
||||
if obj_type == self.ESTABLISHMENT_TYPE:
|
||||
establishment_type = EstablishmentType.objects.filter(pk=obj_id).\
|
||||
first()
|
||||
if not establishment_type:
|
||||
raise BindingObjectNotFound()
|
||||
if request.method == 'POST' and tag_category.establishment_types.\
|
||||
filter(pk=establishment_type.pk).exists():
|
||||
raise ObjectAlreadyAdded()
|
||||
if request.method == 'DELETE' and not tag_category.\
|
||||
establishment_types.filter(pk=establishment_type.pk).\
|
||||
exists():
|
||||
raise RemovedBindingObjectNotFound()
|
||||
attrs['related_object'] = establishment_type
|
||||
elif obj_type == self.NEWS_TYPE:
|
||||
news_type = NewsType.objects.filter(pk=obj_id).first()
|
||||
if not news_type:
|
||||
raise BindingObjectNotFound()
|
||||
if request.method == 'POST' and tag_category.news_types.\
|
||||
filter(pk=news_type.pk).exists():
|
||||
raise ObjectAlreadyAdded()
|
||||
if request.method == 'DELETE' and not tag_category.news_types.\
|
||||
filter(pk=news_type.pk).exists():
|
||||
raise RemovedBindingObjectNotFound()
|
||||
attrs['related_object'] = news_type
|
||||
return attrs
|
||||
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.
|
||||
0
apps/tag/urls/__init__.py
Normal file
0
apps/tag/urls/__init__.py
Normal file
11
apps/tag/urls/back.py
Normal file
11
apps/tag/urls/back.py
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
"""Urlconf for app tag."""
|
||||
from rest_framework.routers import SimpleRouter
|
||||
from tag import views
|
||||
|
||||
app_name = 'tag'
|
||||
|
||||
router = SimpleRouter()
|
||||
router.register(r'categories', views.TagCategoryBackOfficeViewSet)
|
||||
router.register(r'', views.TagBackOfficeViewSet)
|
||||
|
||||
urlpatterns = router.urls
|
||||
16
apps/tag/urls/web.py
Normal file
16
apps/tag/urls/web.py
Normal 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
|
||||
|
||||
111
apps/tag/views.py
Normal file
111
apps/tag/views.py
Normal file
|
|
@ -0,0 +1,111 @@
|
|||
"""Tag views."""
|
||||
from rest_framework import viewsets, mixins, status
|
||||
from rest_framework.decorators import action
|
||||
from rest_framework.response import Response
|
||||
from tag import filters, models, serializers
|
||||
from rest_framework import permissions
|
||||
|
||||
|
||||
# User`s views & viewsets
|
||||
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_tags().with_base_related().\
|
||||
distinct()
|
||||
serializer_class = serializers.TagCategoryBaseSerializer
|
||||
|
||||
|
||||
# BackOffice user`s views & viewsets
|
||||
class BindObjectMixin:
|
||||
"""Bind object mixin."""
|
||||
|
||||
def get_serializer_class(self):
|
||||
if self.action == 'bind_object':
|
||||
return self.bind_object_serializer_class
|
||||
return self.serializer_class
|
||||
|
||||
def perform_binding(self, serializer):
|
||||
raise NotImplemented
|
||||
|
||||
def perform_unbinding(self, serializer):
|
||||
raise NotImplemented
|
||||
|
||||
@action(methods=['post', 'delete'], detail=True, url_path='bind-object')
|
||||
def bind_object(self, request, pk=None):
|
||||
serializer = self.get_serializer(data=request.data)
|
||||
serializer.is_valid(raise_exception=True)
|
||||
if request.method == 'POST':
|
||||
self.perform_binding(serializer)
|
||||
return Response(serializer.data, status=status.HTTP_201_CREATED)
|
||||
elif request.method == 'DELETE':
|
||||
self.perform_unbinding(serializer)
|
||||
return Response(status=status.HTTP_204_NO_CONTENT)
|
||||
|
||||
|
||||
class TagBackOfficeViewSet(mixins.ListModelMixin, mixins.CreateModelMixin,
|
||||
mixins.UpdateModelMixin, mixins.DestroyModelMixin,
|
||||
BindObjectMixin, viewsets.GenericViewSet):
|
||||
"""List/create tag view."""
|
||||
|
||||
pagination_class = None
|
||||
permission_classes = (permissions.IsAuthenticated, )
|
||||
queryset = models.Tag.objects.all()
|
||||
serializer_class = serializers.TagBackOfficeSerializer
|
||||
bind_object_serializer_class = serializers.TagBindObjectSerializer
|
||||
|
||||
def perform_binding(self, serializer):
|
||||
data = serializer.validated_data
|
||||
tag = data.pop('tag')
|
||||
obj_type = data.get('type')
|
||||
related_object = data.get('related_object')
|
||||
if obj_type == self.bind_object_serializer_class.ESTABLISHMENT:
|
||||
tag.establishments.add(related_object)
|
||||
elif obj_type == self.bind_object_serializer_class.NEWS:
|
||||
tag.news.add(related_object)
|
||||
|
||||
def perform_unbinding(self, serializer):
|
||||
data = serializer.validated_data
|
||||
tag = data.pop('tag')
|
||||
obj_type = data.get('type')
|
||||
related_object = data.get('related_object')
|
||||
if obj_type == self.bind_object_serializer_class.ESTABLISHMENT:
|
||||
tag.establishments.remove(related_object)
|
||||
elif obj_type == self.bind_object_serializer_class.NEWS:
|
||||
tag.news.remove(related_object)
|
||||
|
||||
|
||||
class TagCategoryBackOfficeViewSet(mixins.CreateModelMixin,
|
||||
mixins.UpdateModelMixin,
|
||||
mixins.DestroyModelMixin,
|
||||
mixins.RetrieveModelMixin,
|
||||
BindObjectMixin,
|
||||
TagCategoryViewSet):
|
||||
"""ViewSet for TagCategory model for BackOffice users."""
|
||||
|
||||
permission_classes = (permissions.IsAuthenticated, )
|
||||
queryset = TagCategoryViewSet.queryset.with_extended_related()
|
||||
serializer_class = serializers.TagCategoryBackOfficeDetailSerializer
|
||||
bind_object_serializer_class = serializers.TagCategoryBindObjectSerializer
|
||||
|
||||
def perform_binding(self, serializer):
|
||||
data = serializer.validated_data
|
||||
tag_category = data.pop('tag_category')
|
||||
obj_type = data.get('type')
|
||||
related_object = data.get('related_object')
|
||||
if obj_type == self.bind_object_serializer_class.ESTABLISHMENT_TYPE:
|
||||
tag_category.establishment_types.add(related_object)
|
||||
elif obj_type == self.bind_object_serializer_class.NEWS_TYPE:
|
||||
tag_category.news_types.add(related_object)
|
||||
|
||||
def perform_unbinding(self, serializer):
|
||||
data = serializer.validated_data
|
||||
tag_category = data.pop('tag_category')
|
||||
obj_type = data.get('type')
|
||||
related_object = data.get('related_object')
|
||||
if obj_type == self.bind_object_serializer_class.ESTABLISHMENT_TYPE:
|
||||
tag_category.establishment_types.remove(related_object)
|
||||
elif obj_type == self.bind_object_serializer_class.NEWS_TYPE:
|
||||
tag_category.news_types.remove(related_object)
|
||||
18
apps/translation/migrations/0004_auto_20191018_0832.py
Normal file
18
apps/translation/migrations/0004_auto_20191018_0832.py
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
# Generated by Django 2.2.4 on 2019-10-18 08:32
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('translation', '0003_auto_20190901_1032'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='language',
|
||||
name='locale',
|
||||
field=models.CharField(max_length=10, unique=True, verbose_name='Locale identifier'),
|
||||
),
|
||||
]
|
||||
|
|
@ -22,7 +22,7 @@ class Language(models.Model):
|
|||
|
||||
title = models.CharField(max_length=255,
|
||||
verbose_name=_('Language title'))
|
||||
locale = models.CharField(max_length=10,
|
||||
locale = models.CharField(max_length=10, unique=True,
|
||||
verbose_name=_('Locale identifier'))
|
||||
|
||||
objects = LanguageQuerySet.as_manager()
|
||||
|
|
|
|||
|
|
@ -23,14 +23,24 @@ class GMJWTAuthentication(JWTAuthentication):
|
|||
"""
|
||||
|
||||
def authenticate(self, request):
|
||||
token = get_token_from_cookies(request)
|
||||
if token is None:
|
||||
try:
|
||||
token = get_token_from_cookies(request)
|
||||
# Return non-authorized user if token not in cookies
|
||||
assert token
|
||||
|
||||
raw_token = self.get_raw_token(token)
|
||||
# Return non-authorized user if cant get raw token
|
||||
assert raw_token
|
||||
|
||||
validated_token = self.get_validated_token(raw_token)
|
||||
user = self.get_user(validated_token)
|
||||
|
||||
# Check record in DB
|
||||
token_is_valid = user.access_tokens.valid() \
|
||||
.by_jti(jti=validated_token.payload.get('jti'))
|
||||
assert token_is_valid.exists()
|
||||
except:
|
||||
# Return non-authorized user if token is invalid or raised an error when run checks.
|
||||
return None
|
||||
|
||||
raw_token = self.get_raw_token(token)
|
||||
if raw_token is None:
|
||||
return None
|
||||
|
||||
validated_token = self.get_validated_token(raw_token)
|
||||
|
||||
return self.get_user(validated_token), None
|
||||
else:
|
||||
return user, None
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
from django.utils.translation import gettext_lazy as _
|
||||
from rest_framework import exceptions, status
|
||||
from rest_framework import exceptions, serializers, status
|
||||
|
||||
|
||||
class ProjectBaseException(exceptions.APIException):
|
||||
|
|
@ -142,3 +142,24 @@ class PasswordResetRequestExistedError(exceptions.APIException):
|
|||
"""
|
||||
status_code = status.HTTP_400_BAD_REQUEST
|
||||
default_detail = _('Password reset request is already exists and valid.')
|
||||
|
||||
|
||||
class ObjectAlreadyAdded(serializers.ValidationError):
|
||||
"""
|
||||
The exception must be thrown if the object has already been added to the
|
||||
list.
|
||||
"""
|
||||
|
||||
default_detail = _('Object has already been added.')
|
||||
|
||||
|
||||
class BindingObjectNotFound(serializers.ValidationError):
|
||||
"""The exception must be thrown if the object not found."""
|
||||
|
||||
default_detail = _('Binding object not found.')
|
||||
|
||||
|
||||
class RemovedBindingObjectNotFound(serializers.ValidationError):
|
||||
"""The exception must be thrown if the object not found."""
|
||||
|
||||
default_detail = _('Removed binding object not found.')
|
||||
|
|
|
|||
3091
project/locale/ru/LC_MESSAGES/django.po
Normal file
3091
project/locale/ru/LC_MESSAGES/django.po
Normal file
File diff suppressed because it is too large
Load Diff
|
|
@ -73,6 +73,7 @@ PROJECT_APPS = [
|
|||
'comment.apps.CommentConfig',
|
||||
'favorites.apps.FavoritesConfig',
|
||||
'rating.apps.RatingConfig',
|
||||
'tag.apps.TagConfig',
|
||||
]
|
||||
|
||||
EXTERNAL_APPS = [
|
||||
|
|
|
|||
|
|
@ -3,12 +3,15 @@ from django.urls import path, include
|
|||
app_name = 'back'
|
||||
|
||||
urlpatterns = [
|
||||
path('gallery/', include(('gallery.urls', 'gallery'),
|
||||
namespace='gallery')),
|
||||
path('account/', include('account.urls.back')),
|
||||
path('comment/', include('comment.urls.back')),
|
||||
path('establishments/', include('establishment.urls.back')),
|
||||
path('gallery/', include(('gallery.urls', 'gallery'), namespace='gallery')),
|
||||
path('location/', include('location.urls.back')),
|
||||
path('news/', include('news.urls.back')),
|
||||
path('account/', include('account.urls.back')),
|
||||
path('comment/', include('comment.urls.back')),
|
||||
path('review/', include('review.urls.back')),
|
||||
]
|
||||
path('tags/', include(('tag.urls.back', 'tag'), namespace='tag')),
|
||||
]
|
||||
|
||||
|
|
|
|||
|
|
@ -24,11 +24,13 @@ 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.web')),
|
||||
path('recipes/', include('recipe.urls.web')),
|
||||
path('tags/', include('tag.urls.web')),
|
||||
path('translation/', include('translation.urls')),
|
||||
path('comments/', include('comment.urls.web')),
|
||||
path('favorites/', include('favorites.urls')),
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user