From 1aef1a5bb195aa2d97fe8c4d03576c189480fcc9 Mon Sep 17 00:00:00 2001 From: evgeniy-st Date: Wed, 28 Aug 2019 15:21:28 +0300 Subject: [PATCH] Translation & establishment --- .../migrations/0002_auto_20190828_0909.py | 37 +++++++++++++++++ .../migrations/0003_auto_20190828_1140.py | 37 +++++++++++++++++ .../migrations/0004_auto_20190828_1156.py | 24 +++++++++++ apps/establishment/models.py | 35 ++++++---------- apps/establishment/serializers.py | 16 +++++--- apps/establishment/urls/common.py | 2 +- apps/establishment/views.py | 12 ++++-- apps/location/models.py | 1 - apps/utils/middleware.py | 41 +++++++++++++------ apps/utils/models.py | 28 +++++++++++-- project/settings/base.py | 3 +- project/urls/web.py | 2 +- 12 files changed, 187 insertions(+), 51 deletions(-) create mode 100644 apps/establishment/migrations/0002_auto_20190828_0909.py create mode 100644 apps/establishment/migrations/0003_auto_20190828_1140.py create mode 100644 apps/establishment/migrations/0004_auto_20190828_1156.py diff --git a/apps/establishment/migrations/0002_auto_20190828_0909.py b/apps/establishment/migrations/0002_auto_20190828_0909.py new file mode 100644 index 00000000..2ec44336 --- /dev/null +++ b/apps/establishment/migrations/0002_auto_20190828_0909.py @@ -0,0 +1,37 @@ +# Generated by Django 2.2.4 on 2019-08-28 09:09 + +from django.db import migrations +import utils.models + + + +class Migration(migrations.Migration): + + dependencies = [ + ('establishment', '0001_initial'), + ] + + operations = [ + migrations.RenameField( + model_name='establishmenttype', + old_name='name', + new_name='name_bak', + ), + migrations.AddField( + model_name='establishmenttype', + name='name', + field=utils.models.TJSONField(blank=True, default=None, help_text='{"en":"some text"}', + null=True, verbose_name='Description'), + ), + migrations.RenameField( + model_name='establishmentsubtype', + old_name='name', + new_name='name_bak', + ), + migrations.AddField( + model_name='establishmentsubtype', + name='name', + field=utils.models.TJSONField(blank=True, default=None, help_text='{"en":"some text"}', + null=True, verbose_name='Description'), + ), + ] diff --git a/apps/establishment/migrations/0003_auto_20190828_1140.py b/apps/establishment/migrations/0003_auto_20190828_1140.py new file mode 100644 index 00000000..d0245ee7 --- /dev/null +++ b/apps/establishment/migrations/0003_auto_20190828_1140.py @@ -0,0 +1,37 @@ +# Generated by Django 2.2.4 on 2019-08-28 11:40 + +from django.db import migrations + + +def copy_establishment_type(apps, schemaeditor): + EstablishmentType = apps.get_model('establishment', 'EstablishmentType') + for et in EstablishmentType.objects.all(): + et.name = {'en': str(et.name_bak)} + et.save() + + +def copy_establishment_subtype(apps, schemaeditor): + EstablishmentSubType = apps.get_model('establishment', 'EstablishmentSubType') + for est in EstablishmentSubType.objects.all(): + est.name = {'en': str(est.name_bak)} + est.save() + + +class Migration(migrations.Migration): + + dependencies = [ + ('establishment', '0002_auto_20190828_0909'), + ] + + operations = [ + migrations.RunPython(copy_establishment_type, migrations.RunPython.noop), + migrations.RunPython(copy_establishment_subtype, migrations.RunPython.noop), + migrations.RemoveField( + model_name='establishmentsubtype', + name='name_bak', + ), + migrations.RemoveField( + model_name='establishmenttype', + name='name_bak', + ), + ] diff --git a/apps/establishment/migrations/0004_auto_20190828_1156.py b/apps/establishment/migrations/0004_auto_20190828_1156.py new file mode 100644 index 00000000..81efeb0f --- /dev/null +++ b/apps/establishment/migrations/0004_auto_20190828_1156.py @@ -0,0 +1,24 @@ +# Generated by Django 2.2.4 on 2019-08-28 11:56 + +from django.db import migrations +import utils.models + + +class Migration(migrations.Migration): + + dependencies = [ + ('establishment', '0003_auto_20190828_1140'), + ] + + operations = [ + migrations.AlterField( + model_name='establishment', + name='description', + field=utils.models.TJSONField(blank=True, default=None, help_text='{"en":"some text"}', null=True, verbose_name='Description'), + ), + migrations.AlterField( + model_name='establishment', + name='name', + field=utils.models.TJSONField(blank=True, default=None, help_text='{"en":"some text"}', null=True, verbose_name='Name'), + ), + ] diff --git a/apps/establishment/models.py b/apps/establishment/models.py index 67a6b6ce..176dadbf 100644 --- a/apps/establishment/models.py +++ b/apps/establishment/models.py @@ -1,17 +1,17 @@ """Establishment models.""" -from django.contrib.postgres.fields import JSONField from django.core.exceptions import ValidationError from django.db import models from django.utils.translation import gettext_lazy as _ from location.models import Address -from utils.models import ProjectBaseMixin, ImageMixin, LocaleManagerMixin +from utils.models import ProjectBaseMixin, ImageMixin, TJSONField, TraslatedFieldsMixin # todo: establishment type&subtypes check -class EstablishmentType(ProjectBaseMixin): +class EstablishmentType(ProjectBaseMixin, TraslatedFieldsMixin): """Establishment type model.""" - name = models.CharField(_('Name'), max_length=255, unique=True) + name = TJSONField(blank=True, null=True, default=None, verbose_name=_('Description'), + help_text='{"en":"some text"}') use_subtypes = models.BooleanField(_('Use subtypes'), default=True) class Meta: @@ -20,10 +20,6 @@ class EstablishmentType(ProjectBaseMixin): verbose_name = _('Establishment type') verbose_name_plural = _('Establishment types') - def __str__(self): - """__str__ method.""" - return self.name - class EstablishmentSubTypeManager(models.Manager): """Extended manager for establishment subtype.""" @@ -35,10 +31,11 @@ class EstablishmentSubTypeManager(models.Manager): return obj -class EstablishmentSubType(ProjectBaseMixin): +class EstablishmentSubType(ProjectBaseMixin, TraslatedFieldsMixin): """Establishment type model.""" - name = models.CharField(_('Name'), max_length=255, unique=True) + name = TJSONField(blank=True, null=True, default=None, verbose_name=_('Description'), + help_text='{"en":"some text"}') establishment_type = models.ForeignKey(EstablishmentType, on_delete=models.CASCADE, verbose_name=_('Type')) @@ -60,18 +57,14 @@ class EstablishmentSubType(ProjectBaseMixin): raise ValidationError(_('Establishment type is not use subtypes.')) -class EstablishmentManager(LocaleManagerMixin): - """Extended manager for establishment model.""" - - -class Establishment(ProjectBaseMixin, ImageMixin): +class Establishment(ProjectBaseMixin, ImageMixin, TraslatedFieldsMixin): """Establishment model.""" - name = JSONField(blank=True, null=True, default=None, - verbose_name=_('Name'), help_text='{"en":"some text"}') - description = JSONField(blank=True, null=True, default=None, - verbose_name=_('Description'), - help_text='{"en":"some text"}') + name = TJSONField(blank=True, null=True, default=None, + verbose_name=_('Name'), help_text='{"en":"some text"}') + description = TJSONField(blank=True, null=True, default=None, + verbose_name=_('Description'), + help_text='{"en":"some text"}') public_mark = models.PositiveIntegerField(blank=True, null=True, default=None, verbose_name=_('Public mark'),) @@ -92,8 +85,6 @@ class Establishment(ProjectBaseMixin, ImageMixin): default=None, verbose_name=_('Price level')) - objects = EstablishmentManager() - class Meta: """Meta class.""" diff --git a/apps/establishment/serializers.py b/apps/establishment/serializers.py index 94676027..a8c417ea 100644 --- a/apps/establishment/serializers.py +++ b/apps/establishment/serializers.py @@ -7,28 +7,32 @@ from location.serializers import AddressSerializer 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',) + 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') + fields = ('id', 'name_translated') class EstablishmentSerializer(serializers.ModelSerializer): """Serializer for Establishment model.""" - name_trans = serializers.CharField() - description_trans = serializers.CharField() + name_translated = serializers.CharField(allow_null=True) + description_translated = serializers.CharField(allow_null=True) type = EstablishmentTypeSerializer(source='establishment_type') subtypes = EstablishmentSubTypeSerializer(many=True) address = AddressSerializer() @@ -39,8 +43,8 @@ class EstablishmentSerializer(serializers.ModelSerializer): model = models.Establishment fields = ( 'id', - 'name_trans', - 'description_trans', + 'name_translated', + 'description_translated', 'public_mark', 'price_level', 'type', diff --git a/apps/establishment/urls/common.py b/apps/establishment/urls/common.py index 6542eec9..fc20a9c9 100644 --- a/apps/establishment/urls/common.py +++ b/apps/establishment/urls/common.py @@ -7,5 +7,5 @@ app_name = 'establishment' urlpatterns = [ - path('', views.EstablishmentListView.as_view(), name='establishment-list'), + path('establishments/', views.EstablishmentListView.as_view(), name='establishment-list'), ] \ No newline at end of file diff --git a/apps/establishment/views.py b/apps/establishment/views.py index c8029249..00e1b970 100644 --- a/apps/establishment/views.py +++ b/apps/establishment/views.py @@ -10,7 +10,13 @@ class EstablishmentListView(JWTGenericViewMixin, generics.ListAPIView): pagination_class = None permission_classes = (permissions.AllowAny,) serializer_class = serializers.EstablishmentSerializer + queryset = models.Establishment.objects.all() - def get_queryset(self): - return models.Establishment.objects.annotate_localized_fields( - locale=self.request.locale) + +class EstablishmentTypeListView(JWTGenericViewMixin, generics.ListAPIView): + """Resource for getting a list of establishment types.""" + + pagination_class = None + permission_classes = (permissions.AllowAny,) + serializer_class = serializers.EstablishmentTypeSerializer + queryset = models.EstablishmentType.objects.all() diff --git a/apps/location/models.py b/apps/location/models.py index 1948588c..56bd89f3 100644 --- a/apps/location/models.py +++ b/apps/location/models.py @@ -6,7 +6,6 @@ from django.db.models.signals import post_save from django.db.transaction import on_commit from django.dispatch import receiver from django.utils.translation import gettext_lazy as _ - from utils.models import ProjectBaseMixin, LocaleManagerMixin, SVGImageMixin diff --git a/apps/utils/middleware.py b/apps/utils/middleware.py index 0e59f9eb..8b7540cf 100644 --- a/apps/utils/middleware.py +++ b/apps/utils/middleware.py @@ -1,16 +1,31 @@ -from django.utils.deprecation import MiddlewareMixin +"""Custom middleware.""" +from django.utils import translation -class CookieMiddleware(MiddlewareMixin): - """Middleware to handle cookies""" +def get_locale(cookie_dict): + return cookie_dict.get('locale') + + +def get_country_code(cookie_dict): + return cookie_dict.get('country_code') + + +def parse_cookies(get_response): + """Parse cookies.""" + def middleware(request): + cookie_dict = request.COOKIES + + # processing locale cookie + locale = get_locale(cookie_dict) + if locale: + translation.activate(locale) + request.locale = locale + + # processing country country cookie + country_code = get_country_code(cookie_dict) + request.country_code = country_code + + response = get_response(request) + return response + return middleware - def process_request(self, request): - # Check locale in cookies if locale not exists in DB return 406 - # if 'locale' not in request.COOKIES or \ - # not Language.objects.by_locale(request.COOKIES.get('locale'))\ - # .exists(): - # return HttpResponse(status=status.HTTP_406_NOT_ACCEPTABLE) - # - # Add to request attrs from cookie - for cookie in request.COOKIES: - setattr(request, cookie, request.COOKIES[cookie]) diff --git a/apps/utils/models.py b/apps/utils/models.py index ec7ab2da..815c36fd 100644 --- a/apps/utils/models.py +++ b/apps/utils/models.py @@ -1,15 +1,13 @@ """Utils app models.""" from os.path import exists - from django.contrib.auth.tokens import PasswordResetTokenGenerator from django.contrib.gis.db import models from django.contrib.postgres.fields import JSONField from django.contrib.postgres.fields.jsonb import KeyTextTransform from django.utils import timezone from django.utils.html import mark_safe -from django.utils.translation import ugettext_lazy as _ +from django.utils.translation import ugettext_lazy as _, get_language from easy_thumbnails.fields import ThumbnailerImageField - from utils.methods import image_path, svg_image_path from utils.validators import svg_image_validator @@ -28,6 +26,30 @@ class ProjectBaseMixin(models.Model): abstract = True +class TJSONField(JSONField): + """Overrided JsonField.""" + + +def translate_field(self, field_name): + def translate(self): + field = getattr(self, field_name) + if isinstance(field, dict): + return field.get(get_language()) + return None + return translate + + +class TraslatedFieldsMixin: + def __init__(self, *args, **kwargs): + super(TraslatedFieldsMixin, self).__init__(*args, **kwargs) + cls = self.__class__ + for field in cls._meta.fields: + field_name = field.name + if isinstance(field, TJSONField): + setattr(cls, f'{field.name}_translated', + property(translate_field(self, field_name))) + + class OAuthProjectMixin: """OAuth2 mixin for project GM""" diff --git a/project/settings/base.py b/project/settings/base.py index 8305b637..e628a028 100644 --- a/project/settings/base.py +++ b/project/settings/base.py @@ -85,9 +85,9 @@ INSTALLED_APPS = CONTRIB_APPS + PROJECT_APPS + EXTERNAL_APPS MIDDLEWARE = [ - 'utils.middleware.CookieMiddleware', 'django.middleware.security.SecurityMiddleware', 'django.contrib.sessions.middleware.SessionMiddleware', + 'django.middleware.locale.LocaleMiddleware', 'oauth2_provider.middleware.OAuth2TokenMiddleware', 'corsheaders.middleware.CorsMiddleware', 'django.middleware.common.CommonMiddleware', @@ -95,6 +95,7 @@ MIDDLEWARE = [ 'django.contrib.auth.middleware.AuthenticationMiddleware', 'django.contrib.messages.middleware.MessageMiddleware', 'django.middleware.clickjacking.XFrameOptionsMiddleware', + 'utils.middleware.parse_cookies', ] ROOT_URLCONF = 'project.urls' diff --git a/project/urls/web.py b/project/urls/web.py index 7f4a20c7..21d0f041 100644 --- a/project/urls/web.py +++ b/project/urls/web.py @@ -18,10 +18,10 @@ from django.urls import path, include app_name = 'web' urlpatterns = [ + path('', include('establishment.urls.web')), path('account/', include('account.urls.web')), path('advertisement/', include('advertisement.urls.web')), path('collection/', include('collection.urls.web')), - path('establishments/', include('establishment.urls.web')), path('news/', include('news.urls.web')), path('partner/', include('partner.urls.web')), ]