From a450b1e2dfe0bc25bb19b9f3b29b078dfb569d3a Mon Sep 17 00:00:00 2001
From: ZUS666
Date: Wed, 25 Oct 2023 00:50:49 +0500
Subject: [PATCH 01/16] add user fields
---
...005_user_have_orders_user_is_subscribed.py | 23 +++++++++++++++++++
api_spot/users/models.py | 8 +++++++
2 files changed, 31 insertions(+)
create mode 100644 api_spot/users/migrations/0005_user_have_orders_user_is_subscribed.py
diff --git a/api_spot/users/migrations/0005_user_have_orders_user_is_subscribed.py b/api_spot/users/migrations/0005_user_have_orders_user_is_subscribed.py
new file mode 100644
index 00000000..f2dd11d6
--- /dev/null
+++ b/api_spot/users/migrations/0005_user_have_orders_user_is_subscribed.py
@@ -0,0 +1,23 @@
+# Generated by Django 4.2.5 on 2023-10-24 19:49
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('users', '0004_alter_user_email'),
+ ]
+
+ operations = [
+ migrations.AddField(
+ model_name='user',
+ name='have_orders',
+ field=models.BooleanField(default=False, verbose_name='Имеет заказы'),
+ ),
+ migrations.AddField(
+ model_name='user',
+ name='is_subscribed',
+ field=models.BooleanField(default=False, verbose_name='Подписан на рассылку'),
+ ),
+ ]
diff --git a/api_spot/users/models.py b/api_spot/users/models.py
index 7de28196..115d81b1 100644
--- a/api_spot/users/models.py
+++ b/api_spot/users/models.py
@@ -103,6 +103,14 @@ class User(AbstractBaseUser, PermissionsMixin):
blank=True,
default='',
)
+ is_subscribed = models.BooleanField(
+ 'Подписан на рассылку',
+ default=False,
+ )
+ have_orders = models.BooleanField(
+ 'Имеет заказы',
+ default=False,
+ )
EMAIL_FIELD = 'email'
USERNAME_FIELD = 'email'
From 2c2054aea393203db4ed1559ab17930006101d67 Mon Sep 17 00:00:00 2001
From: ZUS666
Date: Wed, 25 Oct 2023 17:43:36 +0500
Subject: [PATCH 02/16] promo
---
api_spot/promo/__init__.py | 0
api_spot/promo/admin.py | 12 ++
api_spot/promo/apps.py | 6 +
api_spot/promo/constants.py | 4 +
api_spot/promo/migrations/0001_initial.py | 46 +++++++
.../0002_alter_emailnews_promo_code.py | 19 +++
api_spot/promo/migrations/__init__.py | 0
api_spot/promo/models.py | 68 +++++++++
api_spot/promo/services.py | 73 ++++++++++
api_spot/promo/tasks.py | 38 ++++++
api_spot/promo/tests.py | 4 +
api_spot/promo/validators.py | 16 +++
api_spot/promo/views.py | 4 +
api_spot/templates/news_email.html | 129 ++++++++++++++++++
api_spot/templates/promocode_email.html | 0
api_spot/users/admin.py | 2 +-
16 files changed, 420 insertions(+), 1 deletion(-)
create mode 100644 api_spot/promo/__init__.py
create mode 100644 api_spot/promo/admin.py
create mode 100644 api_spot/promo/apps.py
create mode 100644 api_spot/promo/constants.py
create mode 100644 api_spot/promo/migrations/0001_initial.py
create mode 100644 api_spot/promo/migrations/0002_alter_emailnews_promo_code.py
create mode 100644 api_spot/promo/migrations/__init__.py
create mode 100644 api_spot/promo/models.py
create mode 100644 api_spot/promo/services.py
create mode 100644 api_spot/promo/tasks.py
create mode 100644 api_spot/promo/tests.py
create mode 100644 api_spot/promo/validators.py
create mode 100644 api_spot/promo/views.py
create mode 100644 api_spot/templates/news_email.html
create mode 100644 api_spot/templates/promocode_email.html
diff --git a/api_spot/promo/__init__.py b/api_spot/promo/__init__.py
new file mode 100644
index 00000000..e69de29b
diff --git a/api_spot/promo/admin.py b/api_spot/promo/admin.py
new file mode 100644
index 00000000..397e41f6
--- /dev/null
+++ b/api_spot/promo/admin.py
@@ -0,0 +1,12 @@
+from django.contrib import admin
+from promo.models import EmailNews, Promocode
+
+
+@admin.register(Promocode)
+class PromcodeAdmin(admin.ModelAdmin):
+ pass
+
+
+@admin.register(EmailNews)
+class EmailNewsAdmin(admin.ModelAdmin):
+ pass
diff --git a/api_spot/promo/apps.py b/api_spot/promo/apps.py
new file mode 100644
index 00000000..9c8ef8cc
--- /dev/null
+++ b/api_spot/promo/apps.py
@@ -0,0 +1,6 @@
+from django.apps import AppConfig
+
+
+class PromoConfig(AppConfig):
+ default_auto_field = 'django.db.models.BigAutoField'
+ name = 'promo'
diff --git a/api_spot/promo/constants.py b/api_spot/promo/constants.py
new file mode 100644
index 00000000..2c9db078
--- /dev/null
+++ b/api_spot/promo/constants.py
@@ -0,0 +1,4 @@
+MAX_PROMO_DISCOUNT = 50
+MAX_PROMO_DISCOUNT_MESSAGE = f'Скидка не может превышать {MAX_PROMO_DISCOUNT}%'
+NEWS_EMAIL_TEMPLATE = 'news_email.html'
+PROMOCE_EMAIL_TEMPLATE = 'promocode_email.html'
diff --git a/api_spot/promo/migrations/0001_initial.py b/api_spot/promo/migrations/0001_initial.py
new file mode 100644
index 00000000..a118425c
--- /dev/null
+++ b/api_spot/promo/migrations/0001_initial.py
@@ -0,0 +1,46 @@
+# Generated by Django 4.2.5 on 2023-10-25 09:19
+
+from django.db import migrations, models
+import django.db.models.deletion
+import promo.validators
+
+
+class Migration(migrations.Migration):
+
+ initial = True
+
+ dependencies = [
+ ]
+
+ operations = [
+ migrations.CreateModel(
+ name='Promocode',
+ fields=[
+ ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
+ ('name', models.CharField(max_length=64, unique=True, verbose_name='Название промокода')),
+ ('percent_discount', models.PositiveSmallIntegerField(validators=[promo.validators.MaxDiscountValidator(50)], verbose_name='Процент скидки')),
+ ('expiry_date', models.DateField(validators=[promo.validators.validate_datetime_less_present], verbose_name='Дата истечения')),
+ ('balance', models.PositiveIntegerField(verbose_name='Количество использований')),
+ ],
+ options={
+ 'verbose_name': 'Промокод',
+ 'verbose_name_plural': 'Промокоды',
+ 'ordering': ('expiry_date',),
+ },
+ ),
+ migrations.CreateModel(
+ name='EmailNews',
+ fields=[
+ ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
+ ('subject_message', models.CharField(max_length=128, verbose_name='Тема письма')),
+ ('text_message', models.TextField(verbose_name='Текст письма')),
+ ('send_datetime', models.DateTimeField(unique=True, validators=[promo.validators.validate_datetime_less_present], verbose_name='Дата и время отправки')),
+ ('promo_code', models.ForeignKey(blank=True, on_delete=django.db.models.deletion.CASCADE, related_name='promocode', to='promo.promocode')),
+ ],
+ options={
+ 'verbose_name': 'Email',
+ 'verbose_name_plural': 'Emails',
+ 'ordering': ('send_datetime',),
+ },
+ ),
+ ]
diff --git a/api_spot/promo/migrations/0002_alter_emailnews_promo_code.py b/api_spot/promo/migrations/0002_alter_emailnews_promo_code.py
new file mode 100644
index 00000000..51c4cb03
--- /dev/null
+++ b/api_spot/promo/migrations/0002_alter_emailnews_promo_code.py
@@ -0,0 +1,19 @@
+# Generated by Django 4.2.5 on 2023-10-25 09:30
+
+from django.db import migrations, models
+import django.db.models.deletion
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('promo', '0001_initial'),
+ ]
+
+ operations = [
+ migrations.AlterField(
+ model_name='emailnews',
+ name='promo_code',
+ field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='promocode', to='promo.promocode'),
+ ),
+ ]
diff --git a/api_spot/promo/migrations/__init__.py b/api_spot/promo/migrations/__init__.py
new file mode 100644
index 00000000..e69de29b
diff --git a/api_spot/promo/models.py b/api_spot/promo/models.py
new file mode 100644
index 00000000..be3eff95
--- /dev/null
+++ b/api_spot/promo/models.py
@@ -0,0 +1,68 @@
+from django.db import models
+
+from promo.constants import MAX_PROMO_DISCOUNT
+from promo.validators import (
+ MaxDiscountValidator, validate_datetime_less_present,
+)
+from promo.services import create_task_after_save_promo_email
+
+
+class Promocode(models.Model):
+ name = models.CharField(
+ 'Название промокода',
+ max_length=64,
+ unique=True,
+ )
+ percent_discount = models.PositiveSmallIntegerField(
+ 'Процент скидки',
+ validators=(MaxDiscountValidator(MAX_PROMO_DISCOUNT),)
+ )
+ expiry_date = models.DateField(
+ 'Дата истечения',
+ validators=(validate_datetime_less_present,),
+ )
+ balance = models.PositiveIntegerField(
+ 'Количество использований',
+ )
+
+ def __str__(self):
+ return self.name
+
+ class Meta:
+ verbose_name = 'Промокод'
+ verbose_name_plural = 'Промокоды'
+ ordering = ('expiry_date',)
+
+
+class EmailNews(models.Model):
+ subject_message = models.CharField(
+ 'Тема письма',
+ max_length=128
+ )
+ text_message = models.TextField(
+ 'Текст письма'
+ )
+ send_datetime = models.DateTimeField(
+ 'Дата и время отправки',
+ validators=(validate_datetime_less_present,),
+ unique=True,
+ )
+ promo_code = models.ForeignKey(
+ Promocode,
+ related_name='promocode',
+ on_delete=models.CASCADE,
+ blank=True,
+ null=True,
+ )
+
+ def __str__(self):
+ return self.subject_message[:20]
+
+ class Meta:
+ verbose_name = 'Email'
+ verbose_name_plural = 'Emails'
+ ordering = ('send_datetime',)
+
+ def save(self, *args, **kwargs):
+ super().save(*args, **kwargs)
+ create_task_after_save_promo_email(self)
diff --git a/api_spot/promo/services.py b/api_spot/promo/services.py
new file mode 100644
index 00000000..8a3847b8
--- /dev/null
+++ b/api_spot/promo/services.py
@@ -0,0 +1,73 @@
+from django.contrib.auth import get_user_model
+from django_celery_beat.models import ClockedSchedule, PeriodicTask
+
+from promo.constants import NEWS_EMAIL_TEMPLATE, PROMOCE_EMAIL_TEMPLATE
+
+
+User = get_user_model()
+
+
+def get_list_emails():
+ """
+ Возращает список пользователей подписанных на рассылку.
+ """
+ return [User.objects.filter(
+ is_subscribed=True).values_list('email', flat=True)
+ ]
+
+
+def get_data_news(text):
+ """
+ Создание контекста для новостного письма.
+ """
+ context = {
+ 'text_message': text
+ }
+ return context
+
+
+def get_data_promo(promocode):
+ """
+ Создание контекста для письма с промокодом.
+ """
+ context = {
+ 'promocode': promocode.name,
+ 'percent_discount': promocode.percent_discount,
+ 'expiry_data': promocode.expiry_date
+ }
+ return context
+
+
+def create_task_after_save_promo_email(obj):
+ """
+ Принимает объект письма
+ """
+ import json
+ from promo.tasks import create_chunk_task_send_mails
+
+ context = get_data_news(obj.text_message)
+ template = NEWS_EMAIL_TEMPLATE
+ if obj.promo_code:
+ context = {**context, **get_data_promo(obj.promocode)}
+ template = PROMOCE_EMAIL_TEMPLATE
+ time = ClockedSchedule.objects.create(clocked_time=obj.send_datetime)
+ task = PeriodicTask.objects.create(
+ name=f'отправка письма {obj.subject_message}',
+ task='promo.tasks.create_chunk_task_send_mails',
+ clocked=time,
+ start_time=obj.send_datetime,
+ one_off=True,
+ enabled=True,
+ args=json.dumps([
+ obj.subject_message,
+ template,
+ context,
+ ])
+ )
+ # task.run_tasks()
+ # tasks = [(self.celery_app.tasks.get(task.task),
+ # loads(task.args),
+ # loads(task.kwargs),
+ # task.queue,
+ # task.name)
+ # for task in queryset]
\ No newline at end of file
diff --git a/api_spot/promo/tasks.py b/api_spot/promo/tasks.py
new file mode 100644
index 00000000..875dfb7b
--- /dev/null
+++ b/api_spot/promo/tasks.py
@@ -0,0 +1,38 @@
+# from celery
+# from django.conf import settings
+from django.core.mail import EmailMultiAlternatives
+from django.template.loader import render_to_string
+
+from api_spot.celery import app
+from promo.services import get_list_emails
+
+
+@app.task
+def send_mail_news(user_email, subject, template, data, *args, **kwargs):
+ """
+ Формирует и отправляет эл. письмо.
+ """
+ html_body = render_to_string(template, data)
+ msg = EmailMultiAlternatives(
+ subject=subject,
+ to=[user_email]
+ )
+ msg.attach_alternative(html_body, 'text/html')
+ msg.send()
+ return f'email {subject} sent to {user_email}'
+
+
+@app.task
+def create_chunk_task_send_mails(*args, **kwargs):
+ from information.models import Question
+ Question.objects.create(question='asdsad', answer='asdasd')
+ # list_emails = get_list_emails()
+ # send_mail_news.chunks(
+ # {
+ # 'user_email': email,
+ # # ''
+ # } for email in list_emails
+ # )
+ # print(subject)
+ print(*args)
+ print(**kwargs)
diff --git a/api_spot/promo/tests.py b/api_spot/promo/tests.py
new file mode 100644
index 00000000..7c72b39d
--- /dev/null
+++ b/api_spot/promo/tests.py
@@ -0,0 +1,4 @@
+from django.test import TestCase
+
+
+# Create your tests here.
diff --git a/api_spot/promo/validators.py b/api_spot/promo/validators.py
new file mode 100644
index 00000000..5abbd95a
--- /dev/null
+++ b/api_spot/promo/validators.py
@@ -0,0 +1,16 @@
+import datetime as dt
+
+from django.utils import timezone
+from django.core.exceptions import ValidationError
+from django.core.validators import MaxValueValidator
+
+from promo.constants import MAX_PROMO_DISCOUNT_MESSAGE
+
+
+def validate_datetime_less_present(value):
+ if value < dt.datetime.now():
+ raise ValidationError('Значение должно быть в будущем')
+
+
+class MaxDiscountValidator(MaxValueValidator):
+ message = MAX_PROMO_DISCOUNT_MESSAGE
diff --git a/api_spot/promo/views.py b/api_spot/promo/views.py
new file mode 100644
index 00000000..dc1ba72f
--- /dev/null
+++ b/api_spot/promo/views.py
@@ -0,0 +1,4 @@
+from django.shortcuts import render
+
+
+# Create your views here.
diff --git a/api_spot/templates/news_email.html b/api_spot/templates/news_email.html
new file mode 100644
index 00000000..bb091bd5
--- /dev/null
+++ b/api_spot/templates/news_email.html
@@ -0,0 +1,129 @@
+
+
+
+
+ Успешный сброс пароля
+
+
+
+
+
+
+
+
+
+
+
+
+ |
+
+
+
+ Новостная рассылка
+ |
+
+
+
+
+ {{ text_message }}
+
+ |
+
+
+
+
+ Связаться с нами
+
+ |
+
+
+
+ Информационное взаимодействие
+
+ press@itcoworking.com
+
+
+ |
+
+
+ |
+
+
+
+
+ |
+
+
+
+
diff --git a/api_spot/templates/promocode_email.html b/api_spot/templates/promocode_email.html
new file mode 100644
index 00000000..e69de29b
diff --git a/api_spot/users/admin.py b/api_spot/users/admin.py
index 25bf2a68..6e1b728c 100644
--- a/api_spot/users/admin.py
+++ b/api_spot/users/admin.py
@@ -13,7 +13,7 @@ class UserAdmin(DjangoUserAdmin):
(None, {'fields': ('email', 'password')}),
(_('Personal info'),
{'fields': ('first_name', 'last_name', 'phone',
- 'birth_date', 'occupation')}),
+ 'birth_date', 'occupation', 'is_subscribed')}),
(
_('Permissions'),
{
From 6384d78ac8604cc6fac6ac609010a1199777bcc1 Mon Sep 17 00:00:00 2001
From: ZUS666
Date: Fri, 27 Oct 2023 03:51:07 +0500
Subject: [PATCH 03/16] should work
---
api_spot/api_spot/celery.py | 4 +
api_spot/api_spot/settings.py | 1 +
api_spot/promo/admin.py | 17 ++-
api_spot/promo/migrations/0001_initial.py | 9 +-
.../0002_alter_emailnews_promo_code.py | 19 ---
api_spot/promo/models.py | 19 ++-
api_spot/promo/services.py | 54 ++------
api_spot/promo/tasks.py | 49 ++++---
api_spot/templates/promocode_email.html | 129 ++++++++++++++++++
9 files changed, 205 insertions(+), 96 deletions(-)
delete mode 100644 api_spot/promo/migrations/0002_alter_emailnews_promo_code.py
diff --git a/api_spot/api_spot/celery.py b/api_spot/api_spot/celery.py
index f67ba4b7..0b692be8 100644
--- a/api_spot/api_spot/celery.py
+++ b/api_spot/api_spot/celery.py
@@ -16,4 +16,8 @@
'task': 'spots.tasks.repeat_orders_finish',
'schedule': crontab(hour='*/1', minute=1),
},
+ 'every_day_check_email': {
+ 'task': 'promo.tasks.every_day_check_today_email_task',
+ 'schedule': crontab(hour=15, minute=30),
+ },
}
diff --git a/api_spot/api_spot/settings.py b/api_spot/api_spot/settings.py
index 6b346b24..b19979d3 100644
--- a/api_spot/api_spot/settings.py
+++ b/api_spot/api_spot/settings.py
@@ -38,6 +38,7 @@
'spots',
'information',
'api',
+ 'promo',
'django_cleanup.apps.CleanupConfig',
]
diff --git a/api_spot/promo/admin.py b/api_spot/promo/admin.py
index 397e41f6..9e8a0e3c 100644
--- a/api_spot/promo/admin.py
+++ b/api_spot/promo/admin.py
@@ -1,12 +1,25 @@
from django.contrib import admin
+
from promo.models import EmailNews, Promocode
@admin.register(Promocode)
class PromcodeAdmin(admin.ModelAdmin):
- pass
+ list_display = (
+ 'name',
+ 'percent_discount',
+ 'expiry_date',
+ 'balance',
+ )
@admin.register(EmailNews)
class EmailNewsAdmin(admin.ModelAdmin):
- pass
+ list_display = (
+ 'subject_message',
+ 'send_date',
+ 'promocode',
+ 'is_sent',
+ 'text_message',
+ )
+ exclude = ('is_sent',)
diff --git a/api_spot/promo/migrations/0001_initial.py b/api_spot/promo/migrations/0001_initial.py
index a118425c..ff6d956c 100644
--- a/api_spot/promo/migrations/0001_initial.py
+++ b/api_spot/promo/migrations/0001_initial.py
@@ -1,4 +1,4 @@
-# Generated by Django 4.2.5 on 2023-10-25 09:19
+# Generated by Django 4.2.5 on 2023-10-26 22:45
from django.db import migrations, models
import django.db.models.deletion
@@ -34,13 +34,14 @@ class Migration(migrations.Migration):
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('subject_message', models.CharField(max_length=128, verbose_name='Тема письма')),
('text_message', models.TextField(verbose_name='Текст письма')),
- ('send_datetime', models.DateTimeField(unique=True, validators=[promo.validators.validate_datetime_less_present], verbose_name='Дата и время отправки')),
- ('promo_code', models.ForeignKey(blank=True, on_delete=django.db.models.deletion.CASCADE, related_name='promocode', to='promo.promocode')),
+ ('send_date', models.DateField(unique=True, validators=[promo.validators.validate_datetime_less_present], verbose_name='Дата отправки')),
+ ('is_sent', models.BooleanField(default=False, verbose_name='Отправлен')),
+ ('promocode', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='promocodes', to='promo.promocode')),
],
options={
'verbose_name': 'Email',
'verbose_name_plural': 'Emails',
- 'ordering': ('send_datetime',),
+ 'ordering': ('send_date',),
},
),
]
diff --git a/api_spot/promo/migrations/0002_alter_emailnews_promo_code.py b/api_spot/promo/migrations/0002_alter_emailnews_promo_code.py
deleted file mode 100644
index 51c4cb03..00000000
--- a/api_spot/promo/migrations/0002_alter_emailnews_promo_code.py
+++ /dev/null
@@ -1,19 +0,0 @@
-# Generated by Django 4.2.5 on 2023-10-25 09:30
-
-from django.db import migrations, models
-import django.db.models.deletion
-
-
-class Migration(migrations.Migration):
-
- dependencies = [
- ('promo', '0001_initial'),
- ]
-
- operations = [
- migrations.AlterField(
- model_name='emailnews',
- name='promo_code',
- field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='promocode', to='promo.promocode'),
- ),
- ]
diff --git a/api_spot/promo/models.py b/api_spot/promo/models.py
index be3eff95..ed9150d6 100644
--- a/api_spot/promo/models.py
+++ b/api_spot/promo/models.py
@@ -4,7 +4,6 @@
from promo.validators import (
MaxDiscountValidator, validate_datetime_less_present,
)
-from promo.services import create_task_after_save_promo_email
class Promocode(models.Model):
@@ -42,18 +41,22 @@ class EmailNews(models.Model):
text_message = models.TextField(
'Текст письма'
)
- send_datetime = models.DateTimeField(
- 'Дата и время отправки',
+ send_date = models.DateField(
+ 'Дата отправки',
validators=(validate_datetime_less_present,),
unique=True,
)
- promo_code = models.ForeignKey(
+ promocode = models.ForeignKey(
Promocode,
- related_name='promocode',
+ related_name='promocodes',
on_delete=models.CASCADE,
blank=True,
null=True,
)
+ is_sent = models.BooleanField(
+ 'Отправлен',
+ default=False,
+ )
def __str__(self):
return self.subject_message[:20]
@@ -61,8 +64,4 @@ def __str__(self):
class Meta:
verbose_name = 'Email'
verbose_name_plural = 'Emails'
- ordering = ('send_datetime',)
-
- def save(self, *args, **kwargs):
- super().save(*args, **kwargs)
- create_task_after_save_promo_email(self)
+ ordering = ('send_date',)
diff --git a/api_spot/promo/services.py b/api_spot/promo/services.py
index 8a3847b8..5507b9b6 100644
--- a/api_spot/promo/services.py
+++ b/api_spot/promo/services.py
@@ -1,7 +1,6 @@
from django.contrib.auth import get_user_model
-from django_celery_beat.models import ClockedSchedule, PeriodicTask
-from promo.constants import NEWS_EMAIL_TEMPLATE, PROMOCE_EMAIL_TEMPLATE
+from promo.models import Promocode
User = get_user_model()
@@ -11,63 +10,28 @@ def get_list_emails():
"""
Возращает список пользователей подписанных на рассылку.
"""
- return [User.objects.filter(
- is_subscribed=True).values_list('email', flat=True)
- ]
+ return list(User.objects.filter(
+ is_subscribed=True).values_list('email', flat=True))
-def get_data_news(text):
+def get_data_news(text_message):
"""
Создание контекста для новостного письма.
"""
context = {
- 'text_message': text
+ 'text_message': text_message
}
return context
-def get_data_promo(promocode):
+def get_data_promo(promocode_id):
"""
Создание контекста для письма с промокодом.
"""
+ promocode = Promocode.objects.get(id=promocode_id)
context = {
- 'promocode': promocode.name,
+ 'promocode_name': promocode.name,
'percent_discount': promocode.percent_discount,
- 'expiry_data': promocode.expiry_date
+ 'expiry_date': promocode.expiry_date
}
return context
-
-
-def create_task_after_save_promo_email(obj):
- """
- Принимает объект письма
- """
- import json
- from promo.tasks import create_chunk_task_send_mails
-
- context = get_data_news(obj.text_message)
- template = NEWS_EMAIL_TEMPLATE
- if obj.promo_code:
- context = {**context, **get_data_promo(obj.promocode)}
- template = PROMOCE_EMAIL_TEMPLATE
- time = ClockedSchedule.objects.create(clocked_time=obj.send_datetime)
- task = PeriodicTask.objects.create(
- name=f'отправка письма {obj.subject_message}',
- task='promo.tasks.create_chunk_task_send_mails',
- clocked=time,
- start_time=obj.send_datetime,
- one_off=True,
- enabled=True,
- args=json.dumps([
- obj.subject_message,
- template,
- context,
- ])
- )
- # task.run_tasks()
- # tasks = [(self.celery_app.tasks.get(task.task),
- # loads(task.args),
- # loads(task.kwargs),
- # task.queue,
- # task.name)
- # for task in queryset]
\ No newline at end of file
diff --git a/api_spot/promo/tasks.py b/api_spot/promo/tasks.py
index 875dfb7b..056a5f49 100644
--- a/api_spot/promo/tasks.py
+++ b/api_spot/promo/tasks.py
@@ -1,18 +1,22 @@
# from celery
# from django.conf import settings
from django.core.mail import EmailMultiAlternatives
+from django.forms.models import model_to_dict
from django.template.loader import render_to_string
+from django.utils import timezone
from api_spot.celery import app
-from promo.services import get_list_emails
+from promo.constants import NEWS_EMAIL_TEMPLATE, PROMOCE_EMAIL_TEMPLATE
+from promo.models import EmailNews
+from promo.services import get_data_news, get_data_promo, get_list_emails
@app.task
-def send_mail_news(user_email, subject, template, data, *args, **kwargs):
+def send_mail_news(user_email, subject, template, context):
"""
Формирует и отправляет эл. письмо.
"""
- html_body = render_to_string(template, data)
+ html_body = render_to_string(template, context)
msg = EmailMultiAlternatives(
subject=subject,
to=[user_email]
@@ -23,16 +27,29 @@ def send_mail_news(user_email, subject, template, data, *args, **kwargs):
@app.task
-def create_chunk_task_send_mails(*args, **kwargs):
- from information.models import Question
- Question.objects.create(question='asdsad', answer='asdasd')
- # list_emails = get_list_emails()
- # send_mail_news.chunks(
- # {
- # 'user_email': email,
- # # ''
- # } for email in list_emails
- # )
- # print(subject)
- print(*args)
- print(**kwargs)
+def create_chunk_task_send_mail(email):
+ subject_message = email.get('subject_message')
+ text_message = email.get('text_message')
+ promocode_id = email.get('promocode')
+ context = get_data_news(text_message)
+ template = NEWS_EMAIL_TEMPLATE
+ if promocode_id:
+ context = {**context, **get_data_promo(promocode_id)}
+ template = PROMOCE_EMAIL_TEMPLATE
+ emails = get_list_emails()
+ chunk = [(email, subject_message, template, context) for email in emails]
+ send_mail_news.chunks((chunk), 5).apply_async()
+
+
+@app.task
+def every_day_check_today_email_task():
+ email = EmailNews.objects.filter(
+ send_date=timezone.now()
+ ).first()
+ dict_email = model_to_dict(email)
+ if email:
+ create_chunk_task_send_mail(dict_email)
+ email.is_sent = True
+ email.save()
+ return f'{email.subject_message} sent'
+ return 'There are no emails to send today'
diff --git a/api_spot/templates/promocode_email.html b/api_spot/templates/promocode_email.html
index e69de29b..ced19aaf 100644
--- a/api_spot/templates/promocode_email.html
+++ b/api_spot/templates/promocode_email.html
@@ -0,0 +1,129 @@
+
+
+
+
+ Успешный сброс пароля
+
+
+
+
+
+
+
+
+
+
+
+
+ |
+
+
+
+ Промокод
+ |
+
+
+
+
+ {{ text_message }} Промокод: {{ promocode_name }} на {{ percent_discount }}% до {{ expiry_date }}
+
+ |
+
+
+
+
+ Связаться с нами
+
+ |
+
+
+
+ Информационное взаимодействие
+
+ press@itcoworking.com
+
+
+ |
+
+
+ |
+
+
+
+
+ |
+
+
+
+
From f3f474e884afa2343d97bfd86fa3fb259b9910a2 Mon Sep 17 00:00:00 2001
From: ZUS666
Date: Fri, 27 Oct 2023 03:55:55 +0500
Subject: [PATCH 04/16] fix
---
api_spot/promo/tasks.py | 2 --
api_spot/promo/validators.py | 3 +--
2 files changed, 1 insertion(+), 4 deletions(-)
diff --git a/api_spot/promo/tasks.py b/api_spot/promo/tasks.py
index 056a5f49..0848eec9 100644
--- a/api_spot/promo/tasks.py
+++ b/api_spot/promo/tasks.py
@@ -1,5 +1,3 @@
-# from celery
-# from django.conf import settings
from django.core.mail import EmailMultiAlternatives
from django.forms.models import model_to_dict
from django.template.loader import render_to_string
diff --git a/api_spot/promo/validators.py b/api_spot/promo/validators.py
index 5abbd95a..5c0c2f34 100644
--- a/api_spot/promo/validators.py
+++ b/api_spot/promo/validators.py
@@ -1,6 +1,5 @@
import datetime as dt
-from django.utils import timezone
from django.core.exceptions import ValidationError
from django.core.validators import MaxValueValidator
@@ -8,7 +7,7 @@
def validate_datetime_less_present(value):
- if value < dt.datetime.now():
+ if value < dt.date.today():
raise ValidationError('Значение должно быть в будущем')
From 0fc143d6a217d2b7aa3f5a0cd00af5f3f22d2e4f Mon Sep 17 00:00:00 2001
From: ZUS666
Date: Fri, 27 Oct 2023 03:58:42 +0500
Subject: [PATCH 05/16] delete empty files
---
api_spot/promo/tests.py | 4 ----
api_spot/promo/views.py | 4 ----
2 files changed, 8 deletions(-)
delete mode 100644 api_spot/promo/tests.py
delete mode 100644 api_spot/promo/views.py
diff --git a/api_spot/promo/tests.py b/api_spot/promo/tests.py
deleted file mode 100644
index 7c72b39d..00000000
--- a/api_spot/promo/tests.py
+++ /dev/null
@@ -1,4 +0,0 @@
-from django.test import TestCase
-
-
-# Create your tests here.
diff --git a/api_spot/promo/views.py b/api_spot/promo/views.py
deleted file mode 100644
index dc1ba72f..00000000
--- a/api_spot/promo/views.py
+++ /dev/null
@@ -1,4 +0,0 @@
-from django.shortcuts import render
-
-
-# Create your views here.
From 1178bc25974b0dd449022b20e3b0dd8fb3766359 Mon Sep 17 00:00:00 2001
From: ZUS666
Date: Fri, 27 Oct 2023 04:10:09 +0500
Subject: [PATCH 06/16] add exclude is_sent
---
api_spot/promo/tasks.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/api_spot/promo/tasks.py b/api_spot/promo/tasks.py
index 0848eec9..17853fc3 100644
--- a/api_spot/promo/tasks.py
+++ b/api_spot/promo/tasks.py
@@ -43,7 +43,7 @@ def create_chunk_task_send_mail(email):
def every_day_check_today_email_task():
email = EmailNews.objects.filter(
send_date=timezone.now()
- ).first()
+ ).exclude(is_sent=True).first()
dict_email = model_to_dict(email)
if email:
create_chunk_task_send_mail(dict_email)
From 6c4ccbf9b136ea482ead62d062508b99236ce8cc Mon Sep 17 00:00:00 2001
From: Arseny
Date: Fri, 27 Oct 2023 09:52:17 +0300
Subject: [PATCH 07/16] fix
---
api_spot/spots/admin.py | 13 ++++++++++++-
api_spot/spots/constants.py | 12 ++++++------
.../0013_alter_location_days_open.py | 18 ++++++++++++++++++
api_spot/templates/order_confirmation.html | 3 +--
4 files changed, 37 insertions(+), 9 deletions(-)
create mode 100644 api_spot/spots/migrations/0013_alter_location_days_open.py
diff --git a/api_spot/spots/admin.py b/api_spot/spots/admin.py
index 2fbf7df3..32b7a10c 100644
--- a/api_spot/spots/admin.py
+++ b/api_spot/spots/admin.py
@@ -18,8 +18,19 @@ def preview(self, obj):
)
+@admin.register(PlanPhoto)
+class PlanPhotoAdmin(admin.ModelAdmin):
+ list_display = ('id', 'location', 'preview')
+ readonly_fields = ('preview', )
+
+ def preview(self, obj):
+ return mark_safe(
+ f''
+ )
+
+
@admin.register(ExtraPhoto)
-class ImageAdmin(admin.ModelAdmin):
+class ExtraPhotoAdmin(admin.ModelAdmin):
list_display = ('id', 'location', 'preview')
def preview(self, obj):
diff --git a/api_spot/spots/constants.py b/api_spot/spots/constants.py
index 47736038..e62a9026 100644
--- a/api_spot/spots/constants.py
+++ b/api_spot/spots/constants.py
@@ -62,14 +62,14 @@
NAME_CACHE_WORKSPACE = 'workspace'
NAME_CACHE_MEETING_ROOM = 'meeting_room'
DAYS_CHOICES: tuple[str, str] = (
- ('пн-вс', 'пн-вс'),
- ('пн-сб', 'пн-сб'),
- ('пн-пт', 'пн-пт'),
+ ('Пн-Вс', 'Пн-Вс'),
+ ('Пн-Сб', 'Пн-Сб'),
+ ('Пн-Пт', 'Пн-Пт'),
)
DAYS_DICT = {
- 'вс': 6,
- 'сб': 5,
- 'пт': 4,
+ 'Вс': 6,
+ 'Сб': 5,
+ 'Пт': 4,
}
# Spot
WORK_SPACE = 'Рабочее место'
diff --git a/api_spot/spots/migrations/0013_alter_location_days_open.py b/api_spot/spots/migrations/0013_alter_location_days_open.py
new file mode 100644
index 00000000..baed74e8
--- /dev/null
+++ b/api_spot/spots/migrations/0013_alter_location_days_open.py
@@ -0,0 +1,18 @@
+# Generated by Django 4.2.5 on 2023-10-27 06:48
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('spots', '0012_alter_review_options'),
+ ]
+
+ operations = [
+ migrations.AlterField(
+ model_name='location',
+ name='days_open',
+ field=models.CharField(choices=[('Пн-Вс', 'Пн-Вс'), ('Пн-Сб', 'Пн-Сб'), ('Пн-Пт', 'Пн-Пт')], default=('Пн-Вс', 'Пн-Вс'), max_length=32, verbose_name='Дни недели через -'),
+ ),
+ ]
diff --git a/api_spot/templates/order_confirmation.html b/api_spot/templates/order_confirmation.html
index fd6fe88f..daf47754 100644
--- a/api_spot/templates/order_confirmation.html
+++ b/api_spot/templates/order_confirmation.html
@@ -43,8 +43,7 @@
Здравствуйте, {{ first_name }} {{ last_name }}!
- Это письмо подтверждает ваше бронирование места в нашем коворкинге {{ location_name
- }}. Не забудьте захватить документ удостоверяющий личность.
+ Это письмо подтверждает ваше бронирование места в нашем коворкинге {{ location_name }}. Не забудьте захватить документ удостоверяющий личность.
Date: Fri, 27 Oct 2023 12:20:53 +0500
Subject: [PATCH 10/16] subscribe
---
api_spot/api/exceptions.py | 14 +++++++++++++
api_spot/api/serializers/users.py | 3 ++-
api_spot/api/services/subscribe.py | 6 ++++++
api_spot/api/urls.py | 5 ++++-
api_spot/api/views/__init__.py | 2 ++
api_spot/api/views/subscribe.py | 33 ++++++++++++++++++++++++++++++
6 files changed, 61 insertions(+), 2 deletions(-)
create mode 100644 api_spot/api/services/subscribe.py
create mode 100644 api_spot/api/views/subscribe.py
diff --git a/api_spot/api/exceptions.py b/api_spot/api/exceptions.py
index 60f56401..c99642ff 100644
--- a/api_spot/api/exceptions.py
+++ b/api_spot/api/exceptions.py
@@ -34,3 +34,17 @@ class AddSpotsError(exceptions.ValidationError):
default_detail = {
'error': 'Название уже есть в локации'
}
+
+
+class SubscribedUserError(exceptions.ValidationError):
+ default_code = 'subscribe exists'
+ default_detail = {
+ 'error': 'Вы уже подписаны.'
+ }
+
+
+class NotSubscribedUserError(exceptions.ValidationError):
+ default_code = 'subscribe does not exists'
+ default_detail = {
+ 'error': 'Вы не подписаны.'
+ }
diff --git a/api_spot/api/serializers/users.py b/api_spot/api/serializers/users.py
index 98d5aa16..68e0b3f4 100644
--- a/api_spot/api/serializers/users.py
+++ b/api_spot/api/serializers/users.py
@@ -66,8 +66,9 @@ class Meta:
'phone',
'birth_date',
'occupation',
+ 'is_subscribed'
)
- read_only_fields = ('email',)
+ read_only_fields = ('email', 'is_subscribed')
class EmailSerializer(serializers.Serializer):
diff --git a/api_spot/api/services/subscribe.py b/api_spot/api/services/subscribe.py
new file mode 100644
index 00000000..57262774
--- /dev/null
+++ b/api_spot/api/services/subscribe.py
@@ -0,0 +1,6 @@
+def subscribe_service(self, error, bool):
+ user = self.request.user
+ if user.is_subscribed is bool:
+ return error
+ user.is_subscribed = bool
+ user.save(update_fields='is_subscribed')
diff --git a/api_spot/api/urls.py b/api_spot/api/urls.py
index 62301eb4..cb92d1d8 100644
--- a/api_spot/api/urls.py
+++ b/api_spot/api/urls.py
@@ -6,7 +6,7 @@
LocationMapListAPIView, LocationShortListAPIView, LocationViewSet,
OrderGetViewSet, OrderViewSet, PayView, PlanPhotoAPIView, QuestionViewSet,
ReviewCreateViewSet, ReviewGetViewSet, RuleViewSet, SpotViewSet,
- UserViewSet,
+ SubscireAPIView, UserViewSet,
)
@@ -77,6 +77,9 @@
),
path('short_locations/', LocationShortListAPIView.as_view()),
path('map_locations/', LocationMapListAPIView.as_view()),
+ path('subscribe', SubscireAPIView.as_view(
+ {'post': 'post', 'delete': 'delete'}
+ )),
re_path(
r'locations/(?P\d+)/plan_photo/',
PlanPhotoAPIView.as_view()
diff --git a/api_spot/api/views/__init__.py b/api_spot/api/views/__init__.py
index 8289cdde..fe8b443d 100644
--- a/api_spot/api/views/__init__.py
+++ b/api_spot/api/views/__init__.py
@@ -12,6 +12,7 @@
from .review import ReviewCreateViewSet, ReviewGetViewSet
from .rule import RuleViewSet
from .spot import SpotViewSet
+from .subscribe import SubscireAPIView
from .users import UserViewSet
@@ -31,4 +32,5 @@
ReviewGetViewSet
RuleViewSet
SpotViewSet
+SubscireAPIView
UserViewSet
diff --git a/api_spot/api/views/subscribe.py b/api_spot/api/views/subscribe.py
new file mode 100644
index 00000000..6bca15e5
--- /dev/null
+++ b/api_spot/api/views/subscribe.py
@@ -0,0 +1,33 @@
+from django.contrib.auth import get_user_model
+from drf_spectacular.utils import extend_schema
+from rest_framework import status
+from rest_framework.permissions import IsAuthenticated
+from rest_framework.response import Response
+from rest_framework.views import APIView
+
+from api.exceptions import NotSubscribedUserError, SubscribedUserError
+from api.services.subscribe import subscribe_service
+
+User = get_user_model()
+
+
+@extend_schema(
+ tags=('subscribe',)
+)
+class SubscireAPIView(APIView):
+ """
+ Представление подписки и отписки на новостную рассылку.
+ """
+ permission_classes = (IsAuthenticated,)
+
+ def post(self):
+ subscribe_service(self, SubscribedUserError, True)
+ return Response(
+ {'message': 'Вы успешно подписались'}, status=status.HTTP_200_OK
+ )
+
+ def delete(self):
+ subscribe_service(self, NotSubscribedUserError, False)
+ return Response(
+ {'message': 'Вы успешно отписались'}, status=status.HTTP_200_OK
+ )
From 66aef7cf783175404c10b46ceaf58d1805cd6ded Mon Sep 17 00:00:00 2001
From: Arseny
Date: Fri, 27 Oct 2023 10:28:55 +0300
Subject: [PATCH 11/16] fix/image
---
.../migrations/0006_alter_avatar_image.py | 19 +++++++++++++++++++
api_spot/users/models.py | 3 ++-
api_spot/users/service.py | 9 +++++++++
3 files changed, 30 insertions(+), 1 deletion(-)
create mode 100644 api_spot/users/migrations/0006_alter_avatar_image.py
create mode 100644 api_spot/users/service.py
diff --git a/api_spot/users/migrations/0006_alter_avatar_image.py b/api_spot/users/migrations/0006_alter_avatar_image.py
new file mode 100644
index 00000000..0125169f
--- /dev/null
+++ b/api_spot/users/migrations/0006_alter_avatar_image.py
@@ -0,0 +1,19 @@
+# Generated by Django 4.2.5 on 2023-10-27 07:26
+
+from django.db import migrations, models
+import users.service
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('users', '0005_avatar'),
+ ]
+
+ operations = [
+ migrations.AlterField(
+ model_name='avatar',
+ name='image',
+ field=models.ImageField(blank=True, null=True, upload_to=users.service.get_avatar_path, verbose_name='Аватар'),
+ ),
+ ]
diff --git a/api_spot/users/models.py b/api_spot/users/models.py
index 1c3761ab..5cbdb018 100644
--- a/api_spot/users/models.py
+++ b/api_spot/users/models.py
@@ -5,6 +5,7 @@
from django.utils import timezone
from phonenumber_field import modelfields
+from users.service import get_avatar_path
from users.validators import NamesValidator, validate_birth_day
@@ -132,7 +133,7 @@ class Avatar(models.Model):
'Аватар',
blank=True,
null=True,
- upload_to='images/users/',
+ upload_to=get_avatar_path,
)
class Meta:
diff --git a/api_spot/users/service.py b/api_spot/users/service.py
new file mode 100644
index 00000000..3919eaf2
--- /dev/null
+++ b/api_spot/users/service.py
@@ -0,0 +1,9 @@
+import uuid
+import os
+
+
+def get_avatar_path(instance, filename):
+ """Загрузка с уникальным именем."""
+ ext = filename.split('.')[-1]
+ filename = "%s.%s" % (uuid.uuid4(), ext)
+ return os.path.join('images/users', filename)
From c4f6f33874196c9ffaabb44bde25bd0dc0e78c8a Mon Sep 17 00:00:00 2001
From: ZUS666
Date: Fri, 27 Oct 2023 14:23:56 +0500
Subject: [PATCH 12/16] fix unused import
---
api_spot/api/views/subscribe.py | 3 ---
1 file changed, 3 deletions(-)
diff --git a/api_spot/api/views/subscribe.py b/api_spot/api/views/subscribe.py
index 6bca15e5..223902b5 100644
--- a/api_spot/api/views/subscribe.py
+++ b/api_spot/api/views/subscribe.py
@@ -1,4 +1,3 @@
-from django.contrib.auth import get_user_model
from drf_spectacular.utils import extend_schema
from rest_framework import status
from rest_framework.permissions import IsAuthenticated
@@ -8,8 +7,6 @@
from api.exceptions import NotSubscribedUserError, SubscribedUserError
from api.services.subscribe import subscribe_service
-User = get_user_model()
-
@extend_schema(
tags=('subscribe',)
From 168e03bb561c8582a29cb9bd07c5a52f7302b296 Mon Sep 17 00:00:00 2001
From: ZUS666
Date: Fri, 27 Oct 2023 14:40:46 +0500
Subject: [PATCH 13/16] migrations
---
api_spot/api/urls.py | 4 +---
...scribed.py => 0006_user_have_orders_user_is_subscribed.py} | 4 ++--
2 files changed, 3 insertions(+), 5 deletions(-)
rename api_spot/users/migrations/{0005_user_have_orders_user_is_subscribed.py => 0006_user_have_orders_user_is_subscribed.py} (85%)
diff --git a/api_spot/api/urls.py b/api_spot/api/urls.py
index 7f6f32df..a9443de5 100644
--- a/api_spot/api/urls.py
+++ b/api_spot/api/urls.py
@@ -77,9 +77,7 @@
),
path('short_locations/', LocationShortListAPIView.as_view()),
path('map_locations/', LocationMapListAPIView.as_view()),
- path('subscribe', SubscireAPIView.as_view(
- {'post': 'post', 'delete': 'delete'}
- )),
+ path('subscribe/', SubscireAPIView.as_view(), name='subscribe'),
re_path(
r'locations/(?P\d+)/plan_photo/',
PlanPhotoAPIView.as_view()
diff --git a/api_spot/users/migrations/0005_user_have_orders_user_is_subscribed.py b/api_spot/users/migrations/0006_user_have_orders_user_is_subscribed.py
similarity index 85%
rename from api_spot/users/migrations/0005_user_have_orders_user_is_subscribed.py
rename to api_spot/users/migrations/0006_user_have_orders_user_is_subscribed.py
index f2dd11d6..5abee837 100644
--- a/api_spot/users/migrations/0005_user_have_orders_user_is_subscribed.py
+++ b/api_spot/users/migrations/0006_user_have_orders_user_is_subscribed.py
@@ -1,4 +1,4 @@
-# Generated by Django 4.2.5 on 2023-10-24 19:49
+# Generated by Django 4.2.5 on 2023-10-27 09:39
from django.db import migrations, models
@@ -6,7 +6,7 @@
class Migration(migrations.Migration):
dependencies = [
- ('users', '0004_alter_user_email'),
+ ('users', '0005_avatar'),
]
operations = [
From 94d435005cb5cb9594e1d874f429855951a4c2ce Mon Sep 17 00:00:00 2001
From: Arseny
Date: Fri, 27 Oct 2023 13:09:02 +0300
Subject: [PATCH 14/16] fix/nginx
---
infra/nginx/default.conf | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/infra/nginx/default.conf b/infra/nginx/default.conf
index 74252f2e..38b9c2c4 100644
--- a/infra/nginx/default.conf
+++ b/infra/nginx/default.conf
@@ -1,7 +1,7 @@
server {
listen 80;
server_name spotit.acceleratorpracticum.ru;
- client_max_body_size 10m;
+ client_max_body_size 3m;
server_tokens off;
location /.well-known/acme-challenge/ {
@@ -17,6 +17,7 @@ server {
server {
listen 443 ssl;
server_name spotit.acceleratorpracticum.ru;
+ client_max_body_size 3m;
server_tokens off;
ssl_certificate /etc/letsencrypt/live/spotit.acceleratorpracticum.ru/fullchain.pem;
From 0c75032a89949cfcae44e5a5f89b7055a3b4e349 Mon Sep 17 00:00:00 2001
From: ZUS666
Date: Fri, 27 Oct 2023 15:12:29 +0500
Subject: [PATCH 15/16] fix mistakes
---
api_spot/api/services/subscribe.py | 4 ++--
api_spot/api/urls.py | 2 +-
api_spot/api/views/subscribe.py | 4 ++--
3 files changed, 5 insertions(+), 5 deletions(-)
diff --git a/api_spot/api/services/subscribe.py b/api_spot/api/services/subscribe.py
index 57262774..26a7aea1 100644
--- a/api_spot/api/services/subscribe.py
+++ b/api_spot/api/services/subscribe.py
@@ -1,6 +1,6 @@
def subscribe_service(self, error, bool):
user = self.request.user
if user.is_subscribed is bool:
- return error
+ raise error
user.is_subscribed = bool
- user.save(update_fields='is_subscribed')
+ user.save(update_fields=['is_subscribed'])
diff --git a/api_spot/api/urls.py b/api_spot/api/urls.py
index a9443de5..89f259c1 100644
--- a/api_spot/api/urls.py
+++ b/api_spot/api/urls.py
@@ -77,7 +77,7 @@
),
path('short_locations/', LocationShortListAPIView.as_view()),
path('map_locations/', LocationMapListAPIView.as_view()),
- path('subscribe/', SubscireAPIView.as_view(), name='subscribe'),
+ path('subscribe/', SubscireAPIView.as_view(),),
re_path(
r'locations/(?P\d+)/plan_photo/',
PlanPhotoAPIView.as_view()
diff --git a/api_spot/api/views/subscribe.py b/api_spot/api/views/subscribe.py
index 223902b5..fd6ab5e1 100644
--- a/api_spot/api/views/subscribe.py
+++ b/api_spot/api/views/subscribe.py
@@ -17,13 +17,13 @@ class SubscireAPIView(APIView):
"""
permission_classes = (IsAuthenticated,)
- def post(self):
+ def post(self, request):
subscribe_service(self, SubscribedUserError, True)
return Response(
{'message': 'Вы успешно подписались'}, status=status.HTTP_200_OK
)
- def delete(self):
+ def delete(self, request):
subscribe_service(self, NotSubscribedUserError, False)
return Response(
{'message': 'Вы успешно отписались'}, status=status.HTTP_200_OK
From 7f134427d1a7053240b54b877beb0d11ef19a3f3 Mon Sep 17 00:00:00 2001
From: ZUS666
Date: Fri, 27 Oct 2023 15:47:38 +0500
Subject: [PATCH 16/16] fix
---
...scribed.py => 0007_user_have_orders_user_is_subscribed.py} | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
rename api_spot/users/migrations/{0006_user_have_orders_user_is_subscribed.py => 0007_user_have_orders_user_is_subscribed.py} (85%)
diff --git a/api_spot/users/migrations/0006_user_have_orders_user_is_subscribed.py b/api_spot/users/migrations/0007_user_have_orders_user_is_subscribed.py
similarity index 85%
rename from api_spot/users/migrations/0006_user_have_orders_user_is_subscribed.py
rename to api_spot/users/migrations/0007_user_have_orders_user_is_subscribed.py
index 5abee837..bf13a082 100644
--- a/api_spot/users/migrations/0006_user_have_orders_user_is_subscribed.py
+++ b/api_spot/users/migrations/0007_user_have_orders_user_is_subscribed.py
@@ -1,4 +1,4 @@
-# Generated by Django 4.2.5 on 2023-10-27 09:39
+# Generated by Django 4.2.5 on 2023-10-27 10:47
from django.db import migrations, models
@@ -6,7 +6,7 @@
class Migration(migrations.Migration):
dependencies = [
- ('users', '0005_avatar'),
+ ('users', '0006_alter_avatar_image'),
]
operations = [