Merge branch 'develop' of ssh://gl.id-east.ru:222/gm/gm-backend into develop
This commit is contained in:
commit
387f96b8bf
|
|
@ -856,6 +856,11 @@ class Establishment(GalleryMixin, ProjectBaseMixin, URLImageMixin,
|
||||||
metadata.append(category_tags)
|
metadata.append(category_tags)
|
||||||
return metadata
|
return metadata
|
||||||
|
|
||||||
|
@property
|
||||||
|
def distillery_types(self):
|
||||||
|
"""Tags from tag category - distillery_type."""
|
||||||
|
return self.tags.filter(category__index_name='distillery_type')
|
||||||
|
|
||||||
|
|
||||||
class EstablishmentNoteQuerySet(models.QuerySet):
|
class EstablishmentNoteQuerySet(models.QuerySet):
|
||||||
"""QuerySet for model EstablishmentNote."""
|
"""QuerySet for model EstablishmentNote."""
|
||||||
|
|
|
||||||
|
|
@ -54,7 +54,6 @@ class SocialNetworkRelatedSerializers(serializers.ModelSerializer):
|
||||||
|
|
||||||
class PlateSerializer(ProjectModelSerializer):
|
class PlateSerializer(ProjectModelSerializer):
|
||||||
name_translated = TranslatedField()
|
name_translated = TranslatedField()
|
||||||
currency = CurrencySerializer(read_only=True)
|
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = models.Plate
|
model = models.Plate
|
||||||
|
|
@ -329,6 +328,7 @@ class EstablishmentBaseSerializer(ProjectModelSerializer):
|
||||||
read_only=True)
|
read_only=True)
|
||||||
tz = serializers.CharField(read_only=True, source='timezone_as_str')
|
tz = serializers.CharField(read_only=True, source='timezone_as_str')
|
||||||
new_image = ImageBaseSerializer(source='crop_main_image', allow_null=True, read_only=True)
|
new_image = ImageBaseSerializer(source='crop_main_image', allow_null=True, read_only=True)
|
||||||
|
distillery_types = TagBaseSerializer(read_only=True, many=True, allow_null=True)
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
"""Meta class."""
|
"""Meta class."""
|
||||||
|
|
@ -354,6 +354,7 @@ class EstablishmentBaseSerializer(ProjectModelSerializer):
|
||||||
'new_image',
|
'new_image',
|
||||||
'tz',
|
'tz',
|
||||||
'wine_regions',
|
'wine_regions',
|
||||||
|
'distillery_types',
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -19,7 +19,7 @@ class EstablishmentMixinViews:
|
||||||
|
|
||||||
def get_queryset(self):
|
def get_queryset(self):
|
||||||
"""Overrided method 'get_queryset'."""
|
"""Overrided method 'get_queryset'."""
|
||||||
return models.Establishment.objects.published().with_base_related()
|
return models.Establishment.objects.with_base_related()
|
||||||
|
|
||||||
|
|
||||||
class EstablishmentListCreateView(EstablishmentMixinViews, generics.ListCreateAPIView):
|
class EstablishmentListCreateView(EstablishmentMixinViews, generics.ListCreateAPIView):
|
||||||
|
|
|
||||||
|
|
@ -232,9 +232,9 @@ class NewsBackOfficeBaseSerializer(NewsBaseSerializer):
|
||||||
|
|
||||||
def create(self, validated_data):
|
def create(self, validated_data):
|
||||||
slugs = validated_data.get('slugs')
|
slugs = validated_data.get('slugs')
|
||||||
|
if slugs:
|
||||||
slugs_list = list(map(lambda x: x.lower(), slugs.values()))
|
slugs_list = list(map(lambda x: x.lower(), slugs.values()))
|
||||||
slugs_set = set(slugs_list)
|
slugs_set = set(slugs_list)
|
||||||
if slugs:
|
|
||||||
if models.News.objects.filter(
|
if models.News.objects.filter(
|
||||||
slugs__values__contains=list(slugs.values())
|
slugs__values__contains=list(slugs.values())
|
||||||
).exists() or len(slugs_list) != len(slugs_set):
|
).exists() or len(slugs_list) != len(slugs_set):
|
||||||
|
|
@ -249,9 +249,9 @@ class NewsBackOfficeBaseSerializer(NewsBaseSerializer):
|
||||||
|
|
||||||
def update(self, instance, validated_data):
|
def update(self, instance, validated_data):
|
||||||
slugs = validated_data.get('slugs')
|
slugs = validated_data.get('slugs')
|
||||||
|
if slugs:
|
||||||
slugs_list = list(map(lambda x: x.lower(), slugs.values()))
|
slugs_list = list(map(lambda x: x.lower(), slugs.values()))
|
||||||
slugs_set = set(slugs_list)
|
slugs_set = set(slugs_list)
|
||||||
if slugs:
|
|
||||||
if models.News.objects.filter(
|
if models.News.objects.filter(
|
||||||
slugs__values__contains=list(slugs.values())
|
slugs__values__contains=list(slugs.values())
|
||||||
).exists() or len(slugs_list) != len(slugs_set):
|
).exists() or len(slugs_list) != len(slugs_set):
|
||||||
|
|
|
||||||
|
|
@ -15,27 +15,35 @@ from notification.models import Subscribe
|
||||||
@shared_task
|
@shared_task
|
||||||
def send_email_with_news(news_ids):
|
def send_email_with_news(news_ids):
|
||||||
subscribes = Subscribe.objects.all() \
|
subscribes = Subscribe.objects.all() \
|
||||||
.prefetch_related('subscriber') \
|
.prefetch_related('subscriber', 'subscription_type') \
|
||||||
.prefetch_related('subscription_type')
|
.active()
|
||||||
|
|
||||||
sent_news = models.News.objects.filter(id__in=news_ids)
|
sent_news = models.News.objects.filter(id__in=news_ids)
|
||||||
|
|
||||||
htmly = get_template(settings.NEWS_EMAIL_TEMPLATE)
|
html_template = get_template(settings.NEWS_EMAIL_TEMPLATE)
|
||||||
year = datetime.now().year
|
year = datetime.now().year
|
||||||
|
|
||||||
socials = list(SiteSettings.objects.with_country().select_related('country'))
|
socials = list(SiteSettings.objects.with_country().select_related('country'))
|
||||||
socials = dict(zip(map(lambda social: social.country.code, socials), socials))
|
socials = dict(zip(map(lambda social: social.country.code, socials), socials))
|
||||||
|
|
||||||
for subscribe in subscribes.filter(unsubscribe_date=None):
|
for subscribe in subscribes:
|
||||||
|
subscriber = subscribe.subscriber
|
||||||
|
|
||||||
country = subscribe.subscription_type.country
|
country = subscribe.subscription_type.country
|
||||||
|
|
||||||
if country is None:
|
if country is None:
|
||||||
continue
|
continue # subscription_type has no country
|
||||||
|
|
||||||
socials_for_subscriber = socials.get(country.code)
|
else:
|
||||||
subscriber = subscribe.subscriber
|
country_code = country.code
|
||||||
|
|
||||||
|
socials_for_subscriber = socials.get(country_code)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
for new in sent_news:
|
for new in sent_news:
|
||||||
|
if new.country.code != country_code:
|
||||||
|
continue
|
||||||
|
|
||||||
context = {
|
context = {
|
||||||
"title": new.title.get(subscriber.locale),
|
"title": new.title.get(subscriber.locale),
|
||||||
"subtitle": new.subtitle.get(subscriber.locale),
|
"subtitle": new.subtitle.get(subscriber.locale),
|
||||||
|
|
@ -43,7 +51,7 @@ def send_email_with_news(news_ids):
|
||||||
"code": subscriber.update_code,
|
"code": subscriber.update_code,
|
||||||
"image_url": new.image_url if new.image_url not in EMPTY_VALUES else None,
|
"image_url": new.image_url if new.image_url not in EMPTY_VALUES else None,
|
||||||
"domain_uri": settings.DOMAIN_URI,
|
"domain_uri": settings.DOMAIN_URI,
|
||||||
"slug": new.slug,
|
"slug": new.slugs.get(subscriber.locale),
|
||||||
"country_code": subscriber.country_code,
|
"country_code": subscriber.country_code,
|
||||||
"twitter_page_url": socials_for_subscriber.twitter_page_url if socials_for_subscriber else '#',
|
"twitter_page_url": socials_for_subscriber.twitter_page_url if socials_for_subscriber else '#',
|
||||||
"instagram_page_url": socials_for_subscriber.instagram_page_url if socials_for_subscriber else '#',
|
"instagram_page_url": socials_for_subscriber.instagram_page_url if socials_for_subscriber else '#',
|
||||||
|
|
@ -52,9 +60,12 @@ def send_email_with_news(news_ids):
|
||||||
"year": year
|
"year": year
|
||||||
}
|
}
|
||||||
send_mail(
|
send_mail(
|
||||||
"G&M News", render_to_string(settings.NEWS_EMAIL_TEMPLATE, context),
|
subject="G&M News",
|
||||||
settings.EMAIL_HOST_USER, [subscriber.send_to], fail_silently=False,
|
message=render_to_string(settings.NEWS_EMAIL_TEMPLATE, context),
|
||||||
html_message=htmly.render(context)
|
from_email=settings.EMAIL_HOST_USER,
|
||||||
|
recipient_list=[subscriber.send_to],
|
||||||
|
fail_silently=False,
|
||||||
|
html_message=html_template.render(context)
|
||||||
)
|
)
|
||||||
except SMTPException:
|
except SMTPException:
|
||||||
continue
|
continue
|
||||||
|
|
|
||||||
|
|
@ -9,6 +9,7 @@ from account.models import User
|
||||||
from location.models import Country
|
from location.models import Country
|
||||||
from utils.methods import generate_string_code
|
from utils.methods import generate_string_code
|
||||||
from utils.models import ProjectBaseMixin, TJSONField, TranslatedFieldsMixin
|
from utils.models import ProjectBaseMixin, TJSONField, TranslatedFieldsMixin
|
||||||
|
from notification.tasks import send_unsubscribe_email
|
||||||
|
|
||||||
|
|
||||||
class SubscriptionType(ProjectBaseMixin, TranslatedFieldsMixin):
|
class SubscriptionType(ProjectBaseMixin, TranslatedFieldsMixin):
|
||||||
|
|
@ -116,6 +117,11 @@ class Subscriber(ProjectBaseMixin):
|
||||||
"""Unsubscribe user."""
|
"""Unsubscribe user."""
|
||||||
self.subscribe_set.update(unsubscribe_date=now())
|
self.subscribe_set.update(unsubscribe_date=now())
|
||||||
|
|
||||||
|
if settings.USE_CELERY:
|
||||||
|
send_unsubscribe_email.delay(self.pk)
|
||||||
|
else:
|
||||||
|
send_unsubscribe_email(self.pk)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def send_to(self):
|
def send_to(self):
|
||||||
"""Actual email."""
|
"""Actual email."""
|
||||||
|
|
@ -135,6 +141,13 @@ class Subscriber(ProjectBaseMixin):
|
||||||
return self.subscription_types.exclude(subscriber__subscribe__unsubscribe_date__isnull=False)
|
return self.subscription_types.exclude(subscriber__subscribe__unsubscribe_date__isnull=False)
|
||||||
|
|
||||||
|
|
||||||
|
class SubscribeQuerySet(models.QuerySet):
|
||||||
|
|
||||||
|
def active(self, switcher=True):
|
||||||
|
"""Fetches active subscriptions."""
|
||||||
|
return self.exclude(unsubscribe_date__isnull=not switcher)
|
||||||
|
|
||||||
|
|
||||||
class Subscribe(ProjectBaseMixin):
|
class Subscribe(ProjectBaseMixin):
|
||||||
"""Subscribe model."""
|
"""Subscribe model."""
|
||||||
|
|
||||||
|
|
@ -144,6 +157,8 @@ class Subscribe(ProjectBaseMixin):
|
||||||
subscriber = models.ForeignKey(Subscriber, on_delete=models.CASCADE)
|
subscriber = models.ForeignKey(Subscriber, on_delete=models.CASCADE)
|
||||||
subscription_type = models.ForeignKey(SubscriptionType, on_delete=models.CASCADE)
|
subscription_type = models.ForeignKey(SubscriptionType, on_delete=models.CASCADE)
|
||||||
|
|
||||||
|
objects = SubscribeQuerySet.as_manager()
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
"""Meta class."""
|
"""Meta class."""
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,11 @@
|
||||||
"""Notification app serializers."""
|
"""Notification app serializers."""
|
||||||
|
from django.conf import settings
|
||||||
from django.utils.translation import ugettext_lazy as _
|
from django.utils.translation import ugettext_lazy as _
|
||||||
from rest_framework import serializers
|
from rest_framework import serializers
|
||||||
|
|
||||||
from location.serializers import CountrySimpleSerializer
|
from location.serializers import CountrySimpleSerializer
|
||||||
from notification import models
|
from notification import models
|
||||||
|
from notification.tasks import send_subscribes_update_email
|
||||||
from utils.methods import get_user_ip
|
from utils.methods import get_user_ip
|
||||||
from utils.serializers import TranslatedField
|
from utils.serializers import TranslatedField
|
||||||
|
|
||||||
|
|
@ -74,7 +75,23 @@ class CreateSubscribeSerializer(serializers.ModelSerializer):
|
||||||
|
|
||||||
def create(self, validated_data):
|
def create(self, validated_data):
|
||||||
"""Create obj."""
|
"""Create obj."""
|
||||||
return models.Subscriber.objects.make_subscriber(**validated_data)
|
|
||||||
|
subscriber = models.Subscriber.objects.make_subscriber(**validated_data)
|
||||||
|
|
||||||
|
if settings.USE_CELERY:
|
||||||
|
send_subscribes_update_email.delay(subscriber.pk)
|
||||||
|
else:
|
||||||
|
send_subscribes_update_email(subscriber.pk)
|
||||||
|
|
||||||
|
return subscriber
|
||||||
|
|
||||||
|
def update(self, instance, validated_data):
|
||||||
|
if settings.USE_CELERY:
|
||||||
|
send_subscribes_update_email.delay(instance.pk)
|
||||||
|
else:
|
||||||
|
send_subscribes_update_email(instance.pk)
|
||||||
|
|
||||||
|
return super().update(instance, validated_data)
|
||||||
|
|
||||||
|
|
||||||
class SubscribeObjectSerializer(serializers.ModelSerializer):
|
class SubscribeObjectSerializer(serializers.ModelSerializer):
|
||||||
|
|
|
||||||
84
apps/notification/tasks.py
Normal file
84
apps/notification/tasks.py
Normal file
|
|
@ -0,0 +1,84 @@
|
||||||
|
from datetime import datetime
|
||||||
|
|
||||||
|
from celery import shared_task
|
||||||
|
from django.conf import settings
|
||||||
|
from django.core.mail import send_mail
|
||||||
|
from django.template.loader import get_template, render_to_string
|
||||||
|
|
||||||
|
from main.models import SiteSettings
|
||||||
|
from notification import models
|
||||||
|
|
||||||
|
|
||||||
|
@shared_task
|
||||||
|
def send_subscribes_update_email(subscriber_id):
|
||||||
|
subscriber = models.Subscriber.objects.get(id=subscriber_id)
|
||||||
|
|
||||||
|
country_code = subscriber.country_code
|
||||||
|
|
||||||
|
html_template = get_template(settings.NOTIFICATION_SUBSCRIBE_TEMPLATE)
|
||||||
|
year = datetime.now().year
|
||||||
|
|
||||||
|
socials = list(SiteSettings.objects.with_country().select_related('country'))
|
||||||
|
socials = dict(zip(map(lambda social: social.country.code, socials), socials))
|
||||||
|
|
||||||
|
socials_for_subscriber = socials.get(country_code)
|
||||||
|
|
||||||
|
context = {
|
||||||
|
"title": "You have subscribed on news G&M",
|
||||||
|
"description": "<br>".join([
|
||||||
|
name.get(subscriber.locale)
|
||||||
|
for name in subscriber.subscription_types.values_list('name', flat=True)
|
||||||
|
]),
|
||||||
|
"code": subscriber.update_code,
|
||||||
|
"link_to_unsubscribe": subscriber.link_to_unsubscribe,
|
||||||
|
"twitter_page_url": socials_for_subscriber.twitter_page_url if socials_for_subscriber else '#',
|
||||||
|
"instagram_page_url": socials_for_subscriber.instagram_page_url if socials_for_subscriber else '#',
|
||||||
|
"facebook_page_url": socials_for_subscriber.facebook_page_url if socials_for_subscriber else '#',
|
||||||
|
"send_to": subscriber.send_to,
|
||||||
|
"year": year
|
||||||
|
}
|
||||||
|
|
||||||
|
send_mail(
|
||||||
|
subject="G&M Subscriptions",
|
||||||
|
message=render_to_string(settings.NOTIFICATION_SUBSCRIBE_TEMPLATE, context),
|
||||||
|
from_email=settings.EMAIL_HOST_USER,
|
||||||
|
recipient_list=[subscriber.send_to],
|
||||||
|
fail_silently=False,
|
||||||
|
html_message=html_template.render(context)
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@shared_task
|
||||||
|
def send_unsubscribe_email(subscriber_id):
|
||||||
|
subscriber = models.Subscriber.objects.get(id=subscriber_id)
|
||||||
|
|
||||||
|
country_code = subscriber.country_code
|
||||||
|
|
||||||
|
html_template = get_template(settings.NOTIFICATION_SUBSCRIBE_TEMPLATE)
|
||||||
|
year = datetime.now().year
|
||||||
|
|
||||||
|
socials = list(SiteSettings.objects.with_country().select_related('country'))
|
||||||
|
socials = dict(zip(map(lambda social: social.country.code, socials), socials))
|
||||||
|
|
||||||
|
socials_for_subscriber = socials.get(country_code)
|
||||||
|
|
||||||
|
context = {
|
||||||
|
"title": "You have successfully unsubscribed from G&M news",
|
||||||
|
"description": "",
|
||||||
|
"code": subscriber.update_code,
|
||||||
|
"link_to_unsubscribe": subscriber.link_to_unsubscribe,
|
||||||
|
"twitter_page_url": socials_for_subscriber.twitter_page_url if socials_for_subscriber else '#',
|
||||||
|
"instagram_page_url": socials_for_subscriber.instagram_page_url if socials_for_subscriber else '#',
|
||||||
|
"facebook_page_url": socials_for_subscriber.facebook_page_url if socials_for_subscriber else '#',
|
||||||
|
"send_to": subscriber.send_to,
|
||||||
|
"year": year
|
||||||
|
}
|
||||||
|
|
||||||
|
send_mail(
|
||||||
|
subject="G&M Subscriptions",
|
||||||
|
message=render_to_string(settings.NOTIFICATION_SUBSCRIBE_TEMPLATE, context),
|
||||||
|
from_email=settings.EMAIL_HOST_USER,
|
||||||
|
recipient_list=[subscriber.send_to],
|
||||||
|
fail_silently=False,
|
||||||
|
html_message=html_template.render(context)
|
||||||
|
)
|
||||||
|
|
@ -85,6 +85,14 @@ class EstablishmentDocument(Document):
|
||||||
'value': fields.KeywordField(),
|
'value': fields.KeywordField(),
|
||||||
},
|
},
|
||||||
multi=True)
|
multi=True)
|
||||||
|
distillery_types = fields.ObjectField(
|
||||||
|
properties={
|
||||||
|
'id': fields.IntegerField(attr='id'),
|
||||||
|
'label': fields.ObjectField(attr='label_indexing',
|
||||||
|
properties=OBJECT_FIELD_PROPERTIES),
|
||||||
|
'value': fields.KeywordField(),
|
||||||
|
},
|
||||||
|
multi=True)
|
||||||
products = fields.ObjectField(
|
products = fields.ObjectField(
|
||||||
properties={
|
properties={
|
||||||
'wine_origins': fields.ListField(
|
'wine_origins': fields.ListField(
|
||||||
|
|
|
||||||
|
|
@ -277,6 +277,7 @@ class EstablishmentDocumentSerializer(InFavoritesMixin, DocumentSerializer):
|
||||||
tags = TagsDocumentSerializer(many=True, source='visible_tags')
|
tags = TagsDocumentSerializer(many=True, source='visible_tags')
|
||||||
restaurant_category = TagsDocumentSerializer(many=True, allow_null=True)
|
restaurant_category = TagsDocumentSerializer(many=True, allow_null=True)
|
||||||
restaurant_cuisine = TagsDocumentSerializer(many=True, allow_null=True)
|
restaurant_cuisine = TagsDocumentSerializer(many=True, allow_null=True)
|
||||||
|
distillery_types = TagsDocumentSerializer(many=True, allow_null=True)
|
||||||
artisan_category = TagsDocumentSerializer(many=True, allow_null=True)
|
artisan_category = TagsDocumentSerializer(many=True, allow_null=True)
|
||||||
schedule = ScheduleDocumentSerializer(many=True, allow_null=True)
|
schedule = ScheduleDocumentSerializer(many=True, allow_null=True)
|
||||||
wine_origins = WineOriginSerializer(many=True)
|
wine_origins = WineOriginSerializer(many=True)
|
||||||
|
|
@ -310,6 +311,16 @@ class EstablishmentDocumentSerializer(InFavoritesMixin, DocumentSerializer):
|
||||||
# 'collections',
|
# 'collections',
|
||||||
'type',
|
'type',
|
||||||
'subtypes',
|
'subtypes',
|
||||||
|
'distillery_types',
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class EstablishmentBackOfficeDocumentSerializer(EstablishmentDocumentSerializer):
|
||||||
|
|
||||||
|
class Meta(EstablishmentDocumentSerializer.Meta):
|
||||||
|
document = EstablishmentDocumentSerializer.Meta.document
|
||||||
|
fields = EstablishmentDocumentSerializer.Meta.fields + (
|
||||||
|
'created',
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
"""Search indexes app views."""
|
"""Search indexes app views."""
|
||||||
from django_elasticsearch_dsl_drf import constants
|
from django_elasticsearch_dsl_drf import constants, pagination
|
||||||
from django_elasticsearch_dsl_drf.filter_backends import (
|
from django_elasticsearch_dsl_drf.filter_backends import (
|
||||||
FilteringFilterBackend,
|
FilteringFilterBackend,
|
||||||
GeoSpatialOrderingFilterBackend,
|
GeoSpatialOrderingFilterBackend,
|
||||||
|
|
@ -321,14 +321,26 @@ class EstablishmentDocumentViewSet(BaseDocumentViewSet):
|
||||||
|
|
||||||
class EstablishmentBackOfficeViewSet(EstablishmentDocumentViewSet):
|
class EstablishmentBackOfficeViewSet(EstablishmentDocumentViewSet):
|
||||||
|
|
||||||
filter_backends = EstablishmentDocumentViewSet.filter_backends + [
|
def get_queryset(self):
|
||||||
OrderingFilterBackend
|
if not self.request.query_params.get('search'):
|
||||||
]
|
self.request.GET._mutable = True
|
||||||
|
self.request.query_params.update({
|
||||||
|
'ordering': '-created',
|
||||||
|
})
|
||||||
|
self.request.GET._mutable = False
|
||||||
|
return super(EstablishmentBackOfficeViewSet, self).get_queryset()
|
||||||
|
|
||||||
|
serializer_class = serializers.EstablishmentBackOfficeDocumentSerializer
|
||||||
|
pagination_class = pagination.PageNumberPagination
|
||||||
|
filter_backends = [
|
||||||
|
FilteringFilterBackend,
|
||||||
|
filters.CustomSearchFilterBackend,
|
||||||
|
filters.CustomGeoSpatialFilteringFilterBackend,
|
||||||
|
GeoSpatialOrderingFilterBackend,
|
||||||
|
OrderingFilterBackend,
|
||||||
|
]
|
||||||
ordering_fields = {
|
ordering_fields = {
|
||||||
'created': {
|
'created': 'created',
|
||||||
'field': 'created'
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
19
apps/tag/migrations/0018_auto_20200113_1357.py
Normal file
19
apps/tag/migrations/0018_auto_20200113_1357.py
Normal file
|
|
@ -0,0 +1,19 @@
|
||||||
|
# Generated by Django 2.2.7 on 2020-01-13 13:57
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
import django.db.models.deletion
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('tag', '0017_auto_20191220_1623'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='tagcategory',
|
||||||
|
name='country',
|
||||||
|
field=models.ForeignKey(blank=True, default=None, null=True, on_delete=django.db.models.deletion.SET_NULL, to='location.Country'),
|
||||||
|
),
|
||||||
|
]
|
||||||
|
|
@ -146,8 +146,8 @@ class TagCategory(models.Model):
|
||||||
(BOOLEAN, _('boolean')),
|
(BOOLEAN, _('boolean')),
|
||||||
)
|
)
|
||||||
country = models.ForeignKey('location.Country',
|
country = models.ForeignKey('location.Country',
|
||||||
on_delete=models.SET_NULL, null=True,
|
on_delete=models.SET_NULL,
|
||||||
default=None)
|
blank=True, null=True, default=None)
|
||||||
public = models.BooleanField(default=False)
|
public = models.BooleanField(default=False)
|
||||||
index_name = models.CharField(max_length=255, blank=True, null=True,
|
index_name = models.CharField(max_length=255, blank=True, null=True,
|
||||||
verbose_name=_('indexing name'), unique=True)
|
verbose_name=_('indexing name'), unique=True)
|
||||||
|
|
|
||||||
|
|
@ -454,6 +454,7 @@ CHANGE_EMAIL_TEMPLATE = 'account/change_email.html'
|
||||||
CONFIRM_EMAIL_TEMPLATE = 'authorization/confirm_email.html'
|
CONFIRM_EMAIL_TEMPLATE = 'authorization/confirm_email.html'
|
||||||
NEWS_EMAIL_TEMPLATE = 'news/news_email.html'
|
NEWS_EMAIL_TEMPLATE = 'news/news_email.html'
|
||||||
NOTIFICATION_PASSWORD_TEMPLATE = 'account/password_change_email.html'
|
NOTIFICATION_PASSWORD_TEMPLATE = 'account/password_change_email.html'
|
||||||
|
NOTIFICATION_SUBSCRIBE_TEMPLATE = 'notification/update_email.html'
|
||||||
|
|
||||||
|
|
||||||
# COOKIES
|
# COOKIES
|
||||||
|
|
|
||||||
|
|
@ -74,3 +74,10 @@ CELERY_RESULT_BACKEND = BROKER_URL
|
||||||
CELERY_BROKER_URL = BROKER_URL
|
CELERY_BROKER_URL = BROKER_URL
|
||||||
|
|
||||||
COOKIE_DOMAIN = '.id-east.ru'
|
COOKIE_DOMAIN = '.id-east.ru'
|
||||||
|
|
||||||
|
# Email settings
|
||||||
|
EMAIL_USE_TLS = True
|
||||||
|
EMAIL_HOST = 'smtp.gmail.com'
|
||||||
|
EMAIL_HOST_USER = 'anatolyfeteleu@gmail.com'
|
||||||
|
EMAIL_HOST_PASSWORD = 'nggrlnbehzksgmbt'
|
||||||
|
EMAIL_PORT = 587
|
||||||
75
project/templates/notification/update_email.html
Normal file
75
project/templates/notification/update_email.html
Normal file
|
|
@ -0,0 +1,75 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en" style="box-sizing: border-box;margin: 0;">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
<meta http-equiv="X-UA-Compatible" content="ie=edge">
|
||||||
|
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Open+Sans:400,400i,700|PT+Serif&display=swap&subset=cyrillic" type="text/css">
|
||||||
|
<title>{{ title }}</title>
|
||||||
|
</head>
|
||||||
|
<body style="box-sizing: border-box;margin: 0;font-family: "Open Sans", sans-serif;font-size: 0.875rem;">
|
||||||
|
<div style="dispaly: none">
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div style="margin: 0 auto; max-width:38.25rem;" class="letter">
|
||||||
|
<div class="letter__wrapper">
|
||||||
|
<div class="letter__inner">
|
||||||
|
<div class="letter__content" style="position: relative;margin: 0 16px 40px;padding: 0 0 1px;">
|
||||||
|
<div class="letter__header" style="margin: 1.875rem 0 2.875rem;text-align: center;">
|
||||||
|
<div class="letter__logo" style="display: block;width: 7.9375rem;height: 4.6875rem;margin: 0 auto 14px auto;">
|
||||||
|
<a href="https://{{ country_code }}.{{ domain_uri }}/" class="letter__logo-photo" style="color: #000;font-weight: 700;text-decoration: none;padding: 0;border-bottom: 1.5px solid #ffee29;cursor: pointer;display: block;border: none;">
|
||||||
|
<img alt="" style="width:100%;" src="https://s3.eu-central-1.amazonaws.com/gm-test.com/manually_uploaded/1.png" />
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
<div class="letter__sublogo" style="font-size: 21px;line-height: 1;letter-spacing: 0;color: #bcbcbc;text-transform: uppercase;">france</div>
|
||||||
|
</div>
|
||||||
|
<div class="letter__title" style="font-family:"Open-Sans",sans-serif; font-size: 1.5rem;margin: 0 0 10px;padding: 0 0 6px;border-bottom: 4px solid #ffee29;">
|
||||||
|
<span class="letter__title-txt">{{ title }}</span>
|
||||||
|
</div>
|
||||||
|
{% if not image_url is None %}
|
||||||
|
<div class="letter__image" style="width: 100%;margin: 0 0 1.25rem;max-height:260px;">
|
||||||
|
<img src="{{ image_url }}" alt="" class="letter__photo" style="display: block; width: 100%;height: 100%;">
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
<div class="letter__text" style="margin: 0 0 30px; font-family:"Open-Sans",sans-serif; font-size: 14px; line-height: 21px;letter-spacing: -0.34px; overflow-x: hidden;">
|
||||||
|
{{ description | safe }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="letter__follow" style="padding: 8px;margin: 0 auto 40px auto;background: #ffee29; max-width: 400px;">
|
||||||
|
<div class="letter__follow-content" style="padding: 1.25rem 0;background: #fff;text-align: center;">
|
||||||
|
<div class="letter__follow-header" style="display: inline-block;margin: 0 0 18px;font-family: "PT Serif", sans-serif;font-size: 1.25rem;text-transform: uppercase;">
|
||||||
|
<img alt="thumb" style="width:30px;vertical-align: sub; display: inline-block" src="https://s3.eu-central-1.amazonaws.com/gm-test.com/manually_uploaded/2.png" />
|
||||||
|
<span class="letter__follow-title">Follow us</span>
|
||||||
|
</div>
|
||||||
|
<div class="letter__follow-text" style="display: block;margin: 0 0 30px;font-size: 12px;font-style: italic;">You can also us on our social network below
|
||||||
|
</div>
|
||||||
|
<div class="letter__follow-social">
|
||||||
|
<a href="{{ facebook_page_url }}" class="letter__follow-link" target="_blank" style="color: #000;font-weight: 700;text-decoration: none;padding: 0;border-bottom: 1.5px solid #ffee29;cursor: pointer;display: inline-block;width: 30px;height: 30px;margin: 0 1rem 0 0;background: #ffee29;border: none;">
|
||||||
|
<img alt="facebook" style="width: 30px; vertical-align: sub; display: inline-block" src="https://s3.eu-central-1.amazonaws.com/gm-test.com/manually_uploaded/3.png" />
|
||||||
|
</a>
|
||||||
|
<a href="{{ instagram_page_url }}" class="letter__follow-link" target="_blank" style="color: #000;font-weight: 700;text-decoration: none;padding: 0;border-bottom: 1.5px solid #ffee29;cursor: pointer;display: inline-block;width: 30px;height: 30px;margin: 0 1rem 0 0;background: #ffee29;border: none;">
|
||||||
|
<img alt="instagram" style="width:30px;vertical-align: sub; display: inline-block" src="https://s3.eu-central-1.amazonaws.com/gm-test.com/manually_uploaded/4.png" />
|
||||||
|
</a>
|
||||||
|
<a href="{{ twitter_page_url }}" class="letter__follow-link" target="_blank" style="color: #000;font-weight: 700;text-decoration: none;padding: 0;border-bottom: 1.5px solid #ffee29;cursor: pointer;display: inline-block;width: 30px;height: 30px;margin: 0;background: #ffee29;border: none;">
|
||||||
|
<img alt="twitter" style="width:30px;vertical-align: sub; display: inline-block" src="https://s3.eu-central-1.amazonaws.com/gm-test.com/manually_uploaded/5.png" />
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="letter__unsubscribe" style="margin: 0 0 1.25rem;font-size: 12px;text-align: center;">
|
||||||
|
<span class="letter__unsubscribe-dscr" style="display: inline-block;">This email has been sent to {{ send_to }} ,</span>
|
||||||
|
<a href="{{ link_to_unsubscribe }}" target="_blank" style="color: #000;font-weight: 700;text-decoration: none;padding: 0;border-bottom: 1.5px solid #ffee29;cursor: pointer;">click here to unsubscribe</a>
|
||||||
|
</div>
|
||||||
|
<div class="letter__footer" style="padding: 24px 0 15px;text-align: center;background: #ffee29;">
|
||||||
|
<div class="letter__footer-logo" style="width: 71px;height: 42px;margin: 0 auto 14px auto;">
|
||||||
|
<a href="#" class="letter__footer-logo-photo" style="color: #000;font-weight: 700;text-decoration: none;padding: 0;border-bottom: 1.5px solid #ffee29;cursor: pointer;">
|
||||||
|
<img alt="" style="width: 100%;" src="https://s3.eu-central-1.amazonaws.com/gm-test.com/manually_uploaded/6.png" /></a>
|
||||||
|
</div>
|
||||||
|
<div class="letter__copyright">GaultMillau © {{ year }}</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
Loading…
Reference in New Issue
Block a user