From d4e993abee95434d08986898cef4046c7d82cc45 Mon Sep 17 00:00:00 2001 From: dormantman Date: Tue, 31 Dec 2019 05:13:36 +0300 Subject: [PATCH 1/3] Added country field --- .../0009_subscriptiontype_country.py | 20 +++++++++++++++++++ .../migrations/0010_auto_20191231_0135.py | 19 ++++++++++++++++++ apps/notification/models.py | 9 ++++----- apps/notification/serializers/common.py | 9 +++++---- 4 files changed, 48 insertions(+), 9 deletions(-) create mode 100644 apps/notification/migrations/0009_subscriptiontype_country.py create mode 100644 apps/notification/migrations/0010_auto_20191231_0135.py diff --git a/apps/notification/migrations/0009_subscriptiontype_country.py b/apps/notification/migrations/0009_subscriptiontype_country.py new file mode 100644 index 00000000..9af323dc --- /dev/null +++ b/apps/notification/migrations/0009_subscriptiontype_country.py @@ -0,0 +1,20 @@ +# Generated by Django 2.2.7 on 2019-12-31 01:31 + +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('location', '0033_merge_20191224_0920'), + ('notification', '0008_remove_subscribe_state'), + ] + + operations = [ + migrations.AddField( + model_name='subscriptiontype', + name='country', + field=models.ForeignKey(default=None, null=True, on_delete=django.db.models.deletion.CASCADE, to='location.Country', verbose_name='Country'), + ), + ] diff --git a/apps/notification/migrations/0010_auto_20191231_0135.py b/apps/notification/migrations/0010_auto_20191231_0135.py new file mode 100644 index 00000000..7b83a738 --- /dev/null +++ b/apps/notification/migrations/0010_auto_20191231_0135.py @@ -0,0 +1,19 @@ +# Generated by Django 2.2.7 on 2019-12-31 01:35 + +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('notification', '0009_subscriptiontype_country'), + ] + + operations = [ + migrations.AlterField( + model_name='subscriptiontype', + name='country', + field=models.ForeignKey(blank=True, default=None, null=True, on_delete=django.db.models.deletion.PROTECT, to='location.Country', verbose_name='country'), + ), + ] diff --git a/apps/notification/models.py b/apps/notification/models.py index 3a9dbbf2..2f0ba500 100644 --- a/apps/notification/models.py +++ b/apps/notification/models.py @@ -6,6 +6,7 @@ from django.utils.timezone import now from django.utils.translation import ugettext_lazy as _ from account.models import User +from location.models import Country from utils.methods import generate_string_code from utils.models import ProjectBaseMixin, TJSONField, TranslatedFieldsMixin @@ -15,7 +16,9 @@ class SubscriptionType(ProjectBaseMixin, TranslatedFieldsMixin): name = TJSONField(blank=True, null=True, default=None, verbose_name=_('name'), help_text='{"en-GB":"some text"}') - # TODO: не хватает связи со страной. ForeignKey + country = models.ForeignKey(Country, on_delete=models.PROTECT, + blank=True, null=True, default=None, + verbose_name=_('country')) # todo: associate user & subscriber after users registration @@ -127,10 +130,6 @@ class Subscriber(ProjectBaseMixin): query = f'?code={self.update_code}' return f'{schema}://{site_domain}{url}{query}' - @property - def subscribe_objects(self): - return Subscribe.objects.filter(subscriber=self) - class Subscribe(ProjectBaseMixin): """Subscribe model.""" diff --git a/apps/notification/serializers/common.py b/apps/notification/serializers/common.py index 036d8929..4a9e64f5 100644 --- a/apps/notification/serializers/common.py +++ b/apps/notification/serializers/common.py @@ -2,6 +2,7 @@ from django.utils.translation import ugettext_lazy as _ from rest_framework import serializers +from location.serializers import CountrySimpleSerializer from notification import models from utils.methods import get_user_ip from utils.serializers import TranslatedField @@ -11,6 +12,7 @@ class SubscriptionTypeSerializer(serializers.ModelSerializer): """Subscription type serializer.""" name_translated = TranslatedField() + country = CountrySimpleSerializer() class Meta: """Meta class.""" @@ -20,6 +22,7 @@ class SubscriptionTypeSerializer(serializers.ModelSerializer): 'id', 'index_name', 'name_translated', + 'country', ) @@ -80,7 +83,7 @@ class SubscribeObjectSerializer(serializers.ModelSerializer): """Meta class.""" model = models.Subscriber - fields = () + fields = ('subscriber', ) read_only_fields = ('subscribe_date', 'unsubscribe_date',) @@ -88,8 +91,7 @@ class SubscribeSerializer(serializers.ModelSerializer): """Subscribe serializer.""" email = serializers.EmailField(required=False, source='send_to') - subscription_types = SubscriptionTypeSerializer(read_only=True, source='subscription_types_set') - subscribe_objects = SubscribeObjectSerializer(read_only=True) + subscription_types = SubscriptionTypeSerializer(many=True, read_only=True) class Meta: """Meta class.""" @@ -99,5 +101,4 @@ class SubscribeSerializer(serializers.ModelSerializer): 'email', 'subscription_types', 'link_to_unsubscribe', - 'subscribe_objects', ) From 241012da424217f4dff895e352e8312ea1a0a58f Mon Sep 17 00:00:00 2001 From: dormantman Date: Tue, 31 Dec 2019 05:29:48 +0300 Subject: [PATCH 2/3] Added prefetch optimize --- apps/news/tasks.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/news/tasks.py b/apps/news/tasks.py index c08ee8c7..4a980144 100644 --- a/apps/news/tasks.py +++ b/apps/news/tasks.py @@ -20,7 +20,7 @@ def send_email_with_news(news_ids): htmly = get_template(settings.NEWS_EMAIL_TEMPLATE) year = datetime.now().year - socials = list(SiteSettings.objects.with_country()) + socials = list(SiteSettings.objects.with_country().select_related('country')) socials = dict(zip(map(lambda social: social.country.code, socials), socials)) for subscriber in subscribers: From 140cc6cfa5f63e56aae42bcf592cddf63d33a8ad Mon Sep 17 00:00:00 2001 From: dormantman Date: Tue, 31 Dec 2019 16:09:04 +0300 Subject: [PATCH 3/3] Reformat sending mail structure --- apps/news/tasks.py | 19 +++++++++++++------ apps/notification/tests.py | 10 ++++++++-- apps/notification/views/common.py | 1 - 3 files changed, 21 insertions(+), 9 deletions(-) diff --git a/apps/news/tasks.py b/apps/news/tasks.py index 4a980144..0267fcf4 100644 --- a/apps/news/tasks.py +++ b/apps/news/tasks.py @@ -9,12 +9,14 @@ from django.template.loader import get_template, render_to_string from main.models import SiteSettings from news import models -from notification.models import Subscriber +from notification.models import Subscribe @shared_task def send_email_with_news(news_ids): - subscribers = Subscriber.objects.all() + subscribes = Subscribe.objects.all() \ + .prefetch_related('subscriber') \ + .prefetch_related('subscription_type') sent_news = models.News.objects.filter(id__in=news_ids) htmly = get_template(settings.NEWS_EMAIL_TEMPLATE) @@ -23,11 +25,16 @@ def send_email_with_news(news_ids): socials = list(SiteSettings.objects.with_country().select_related('country')) socials = dict(zip(map(lambda social: social.country.code, socials), socials)) - for subscriber in subscribers: - socials_for_subscriber = socials.get(subscriber.country_code) + for subscribe in subscribes.filter(unsubscribe_date=None): + country = subscribe.subscription_type.country + + if country is None: + continue + + socials_for_subscriber = socials.get(country.code) + subscriber = subscribe.subscriber + try: - # TODO: вот тут надо учесть, подписки на какие страны есть у юзера активные (нулл время отписки) и не посылать лишнего - # TODO: обрати внимание на кол-во запросов в БД плс. они пишутся в консоль for new in sent_news: context = { "title": new.title.get(subscriber.locale), diff --git a/apps/notification/tests.py b/apps/notification/tests.py index 410365ff..cf380410 100644 --- a/apps/notification/tests.py +++ b/apps/notification/tests.py @@ -80,7 +80,7 @@ class NotificationSubscribeInfoTestCase(APITestCase): class NotificationUnsubscribeAuthUserTestCase(BaseTestCase): def test_unsubscribe_auth_user(self): - Subscriber.objects.create(user=self.user, email=self.email, state=1) + Subscriber.objects.create(user=self.user, email=self.email) self.test_data = { "email": self.email @@ -174,7 +174,7 @@ class NotificationManySubscribeTestCase(APITestCase): test_data = { 'email': self.email, 'subscription_types_pk': [ - self.test_subscribe_type + self.test_subscribe_type.id ] } @@ -183,6 +183,12 @@ class NotificationManySubscribeTestCase(APITestCase): self.assertEqual(response.json()["email"], test_data["email"]) def test_unsubscribe(self): + self.username = 'sedragurda' + self.password = 'sedragurdaredips19' + self.email = 'sedragurda@desoz.com' + self.user = User.objects.create_user( + username=self.username, email=self.email, password=self.password) + test_data = { "email": self.email } diff --git a/apps/notification/views/common.py b/apps/notification/views/common.py index 257c3286..f7fbf9fe 100644 --- a/apps/notification/views/common.py +++ b/apps/notification/views/common.py @@ -28,7 +28,6 @@ class SubscribeInfoView(generics.RetrieveAPIView): class SubscribeInfoAuthUserView(generics.ListAPIView): """Subscribe info auth user view.""" - # TODO: тут пользователь должен видеть свои подписки. проверь плс, что работает permission_classes = (permissions.IsAuthenticated,) serializer_class = serializers.SubscribeSerializer