From dbb0cbc05e6740e86b73a8de5db1391e8b342fa4 Mon Sep 17 00:00:00 2001 From: Anatoly Date: Wed, 28 Aug 2019 17:18:52 +0300 Subject: [PATCH 1/3] refactored endpoint to upload an image --- apps/gallery/serializers.py | 9 +++++++++ apps/gallery/views.py | 2 ++ 2 files changed, 11 insertions(+) diff --git a/apps/gallery/serializers.py b/apps/gallery/serializers.py index a3176b79..112ca432 100644 --- a/apps/gallery/serializers.py +++ b/apps/gallery/serializers.py @@ -5,6 +5,10 @@ from . import models class ImageSerializer(serializers.ModelSerializer): """Serializer for model Image.""" + # REQUEST + image = serializers.ImageField(write_only=True) + # RESPONSE + file = serializers.SerializerMethodField() class Meta: """Meta class""" @@ -12,4 +16,9 @@ class ImageSerializer(serializers.ModelSerializer): fields = ( 'id', 'image', + 'file' ) + + def get_file(self, obj): + """Get absolute URL path""" + return obj.get_full_image_url(request=self.context.get('request')) diff --git a/apps/gallery/views.py b/apps/gallery/views.py index 8a9195c3..31c08084 100644 --- a/apps/gallery/views.py +++ b/apps/gallery/views.py @@ -1,10 +1,12 @@ from rest_framework import generics +from rest_framework.permissions import AllowAny from . import models, serializers class ImageUploadView(generics.CreateAPIView): """Upload image to gallery""" + permission_classes = (AllowAny, ) model = models.Image queryset = models.Image.objects.all() serializer_class = serializers.ImageSerializer From 7a1d5e269c6876308392f68e57ba148406c95a8a Mon Sep 17 00:00:00 2001 From: Anatoly Date: Wed, 28 Aug 2019 17:25:16 +0300 Subject: [PATCH 2/3] refactored ImageSerializer --- apps/gallery/serializers.py | 13 ++++++++----- apps/gallery/views.py | 4 ++-- 2 files changed, 10 insertions(+), 7 deletions(-) diff --git a/apps/gallery/serializers.py b/apps/gallery/serializers.py index 112ca432..9efe2911 100644 --- a/apps/gallery/serializers.py +++ b/apps/gallery/serializers.py @@ -6,19 +6,22 @@ from . import models class ImageSerializer(serializers.ModelSerializer): """Serializer for model Image.""" # REQUEST - image = serializers.ImageField(write_only=True) + file = serializers.ImageField(source='image', + write_only=True) + # RESPONSE - file = serializers.SerializerMethodField() + url = serializers.SerializerMethodField() + class Meta: """Meta class""" model = models.Image fields = ( 'id', - 'image', - 'file' + 'file', + 'url' ) - def get_file(self, obj): + def get_url(self, obj): """Get absolute URL path""" return obj.get_full_image_url(request=self.context.get('request')) diff --git a/apps/gallery/views.py b/apps/gallery/views.py index 31c08084..a3b61727 100644 --- a/apps/gallery/views.py +++ b/apps/gallery/views.py @@ -1,12 +1,12 @@ from rest_framework import generics -from rest_framework.permissions import AllowAny +from utils.permissions import IsAuthenticatedAndTokenIsValid from . import models, serializers class ImageUploadView(generics.CreateAPIView): """Upload image to gallery""" - permission_classes = (AllowAny, ) + permission_classes = (IsAuthenticatedAndTokenIsValid, ) model = models.Image queryset = models.Image.objects.all() serializer_class = serializers.ImageSerializer From cb1ff8e4101e4edf0f1e9a8cdd5e09990a014c39 Mon Sep 17 00:00:00 2001 From: Dmitriy Kuzmenko Date: Wed, 28 Aug 2019 17:53:52 +0300 Subject: [PATCH 3/3] add configuration --- apps/configuration/__init__.py | 0 apps/configuration/admin.py | 8 +++++++ apps/configuration/apps.py | 7 ++++++ apps/configuration/migrations/0001_initial.py | 24 +++++++++++++++++++ apps/configuration/migrations/__init__.py | 0 apps/configuration/models.py | 9 +++++++ apps/configuration/tests.py | 3 +++ apps/configuration/views.py | 3 +++ apps/establishment/models.py | 6 ++--- apps/utils/middleware.py | 7 +++--- apps/utils/models.py | 18 +++++++++++++- project/settings/base.py | 5 ++++ 12 files changed, 82 insertions(+), 8 deletions(-) create mode 100644 apps/configuration/__init__.py create mode 100644 apps/configuration/admin.py create mode 100644 apps/configuration/apps.py create mode 100644 apps/configuration/migrations/0001_initial.py create mode 100644 apps/configuration/migrations/__init__.py create mode 100644 apps/configuration/models.py create mode 100644 apps/configuration/tests.py create mode 100644 apps/configuration/views.py diff --git a/apps/configuration/__init__.py b/apps/configuration/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/apps/configuration/admin.py b/apps/configuration/admin.py new file mode 100644 index 00000000..2bd3fab1 --- /dev/null +++ b/apps/configuration/admin.py @@ -0,0 +1,8 @@ +from django.contrib import admin +from solo.admin import SingletonModelAdmin +from configuration.models import TranslationSettings + + +@admin.register(TranslationSettings) +class TranslationAdmin(SingletonModelAdmin): + """Translation admin""" diff --git a/apps/configuration/apps.py b/apps/configuration/apps.py new file mode 100644 index 00000000..9bbd6730 --- /dev/null +++ b/apps/configuration/apps.py @@ -0,0 +1,7 @@ +from django.apps import AppConfig +from django.utils.translation import gettext_lazy as _ + + +class ConfigurationConfig(AppConfig): + name = 'configuration' + verbose_name = _('configuration') diff --git a/apps/configuration/migrations/0001_initial.py b/apps/configuration/migrations/0001_initial.py new file mode 100644 index 00000000..17d4cff4 --- /dev/null +++ b/apps/configuration/migrations/0001_initial.py @@ -0,0 +1,24 @@ +# Generated by Django 2.2.4 on 2019-08-28 13:33 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + initial = True + + dependencies = [ + ] + + operations = [ + migrations.CreateModel( + name='TranslationSettings', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('default_language', models.CharField(default='en-GB', max_length=10, verbose_name='default language')), + ], + options={ + 'abstract': False, + }, + ), + ] diff --git a/apps/configuration/migrations/__init__.py b/apps/configuration/migrations/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/apps/configuration/models.py b/apps/configuration/models.py new file mode 100644 index 00000000..a9abd689 --- /dev/null +++ b/apps/configuration/models.py @@ -0,0 +1,9 @@ +from django.db import models +from django.utils.translation import ugettext_lazy as _ +from solo.models import SingletonModel + + +class TranslationSettings(SingletonModel): + """Translation settings solo model.""" + default_language = models.CharField( + _('default language'), max_length=10, default='en-GB') diff --git a/apps/configuration/tests.py b/apps/configuration/tests.py new file mode 100644 index 00000000..7ce503c2 --- /dev/null +++ b/apps/configuration/tests.py @@ -0,0 +1,3 @@ +from django.test import TestCase + +# Create your tests here. diff --git a/apps/configuration/views.py b/apps/configuration/views.py new file mode 100644 index 00000000..91ea44a2 --- /dev/null +++ b/apps/configuration/views.py @@ -0,0 +1,3 @@ +from django.shortcuts import render + +# Create your views here. diff --git a/apps/establishment/models.py b/apps/establishment/models.py index a895e97b..74982565 100644 --- a/apps/establishment/models.py +++ b/apps/establishment/models.py @@ -49,9 +49,9 @@ class EstablishmentSubType(ProjectBaseMixin, TraslatedFieldsMixin): verbose_name = _('Establishment subtype') verbose_name_plural = _('Establishment subtypes') - def __str__(self): - """__str__ method.""" - return self.name + # def __str__(self): + # """__str__ method.""" + # return self.name def clean_fields(self, exclude=None): if not self.establishment_type.use_subtypes: diff --git a/apps/utils/middleware.py b/apps/utils/middleware.py index 8b7540cf..855c4f9e 100644 --- a/apps/utils/middleware.py +++ b/apps/utils/middleware.py @@ -1,6 +1,6 @@ """Custom middleware.""" from django.utils import translation - +from configuration.models import TranslationSettings def get_locale(cookie_dict): return cookie_dict.get('locale') @@ -16,9 +16,8 @@ def parse_cookies(get_response): cookie_dict = request.COOKIES # processing locale cookie - locale = get_locale(cookie_dict) - if locale: - translation.activate(locale) + locale = get_locale(cookie_dict) or TranslationSettings.get_solo().default_language + translation.activate(locale) request.locale = locale # processing country country cookie diff --git a/apps/utils/models.py b/apps/utils/models.py index 815c36fd..b9ed82a6 100644 --- a/apps/utils/models.py +++ b/apps/utils/models.py @@ -30,11 +30,27 @@ class TJSONField(JSONField): """Overrided JsonField.""" +def to_locale(language): + """Turn a language name (en-us) into a locale name (en_US).""" + language, _, country = language.lower().partition('-') + if not country: + return language + # A language with > 2 characters after the dash only has its first + # character after the dash capitalized; e.g. sr-latn becomes sr_Latn. + # A language with 2 characters after the dash has both characters + # capitalized; e.g. en-us becomes en_US. + country, _, tail = country.partition('-') + country = country.title() if len(country) > 2 else country.upper() + if tail: + country += '-' + tail + return language + '-' + country + + def translate_field(self, field_name): def translate(self): field = getattr(self, field_name) if isinstance(field, dict): - return field.get(get_language()) + return field.get(to_locale(get_language())) return None return translate diff --git a/project/settings/base.py b/project/settings/base.py index 45dbb693..0f040f94 100644 --- a/project/settings/base.py +++ b/project/settings/base.py @@ -63,6 +63,7 @@ PROJECT_APPS = [ 'news.apps.NewsConfig', 'partner.apps.PartnerConfig', 'translation.apps.TranslationConfig', + 'configuration.apps.ConfigurationConfig', ] EXTERNAL_APPS = [ @@ -78,6 +79,7 @@ EXTERNAL_APPS = [ 'rest_framework_social_oauth2', 'django_extensions', 'rest_framework_simplejwt.token_blacklist', + 'solo', ] @@ -381,3 +383,6 @@ DATA_UPLOAD_MAX_MEMORY_SIZE = 5242880 # 5MB # Maximum uploaded file size FILE_UPLOAD_MAX_MEMORY_SIZE = 5242880 # 5MB FILE_UPLOAD_PERMISSIONS = 0o644 + + +SOLO_CACHE_TIMEOUT = 300