From 6e2a019d329fd498cbccafecaaabc75e95d0bf90 Mon Sep 17 00:00:00 2001 From: sm4640 Date: Mon, 28 Jul 2025 15:22:15 +0900 Subject: [PATCH] =?UTF-8?q?=E2=9C=A8=20Feat:=20[#84]=20=EB=9E=9C=EB=94=A9?= =?UTF-8?q?=ED=8E=98=EC=9D=B4=EC=A7=80=20=EC=9D=B4=EB=A9=94=EC=9D=BC=20?= =?UTF-8?q?=EC=88=98=EC=A7=91=20=EB=B0=8F=20=EC=A0=95=EC=8B=9D=EB=9F=B0?= =?UTF-8?q?=EC=B9=AD=20=EC=9D=B4=EB=A9=94=EC=9D=BC=20=EB=B0=9C=EC=86=A1=20?= =?UTF-8?q?=EA=B8=B0=EB=8A=A5=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- config/settings.py | 10 +++++++++- homes/models.py | 6 ++++++ homes/serializers.py | 11 ++++++++++- homes/urls.py | 6 ++++++ homes/views.py | 40 +++++++++++++++++++++++++++++++++++++++- 5 files changed, 70 insertions(+), 3 deletions(-) diff --git a/config/settings.py b/config/settings.py index d5a23c2..e34f0e6 100644 --- a/config/settings.py +++ b/config/settings.py @@ -66,7 +66,7 @@ INSTALLED_APPS = [ 'codes', 'notifications', 'nocodetools', - # 'homes', + 'homes', ] MIDDLEWARE = [ @@ -270,6 +270,14 @@ GOOGLE_CLIENT_ID = env('GOOGLE_CLIENT_ID') GITHUB_CLIENT_ID = env('GITHUB_CLIENT_ID') GITHUB_CLIENT_SECRET = env('GITHUB_CLIENT_SECRET') +EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend' +EMAIL_HOST = env('EMAIL_HOST') +EMAIL_USE_TLS = True +EMAIL_PORT = env('EMAIL_PORT') +EMAIL_HOST_USER = env('EMAIL_HOST_USER') +EMAIL_HOST_PASSWORD = env('EMAIL_HOST_PASSWORD') +DEFAULT_FROM_EMAIL = EMAIL_HOST_USER + ##CORS # CSRF_TRUSTED_ORIGINS = [] # CORS_ALLOWED_ORIGINS = ["http://localhost:3000", "https://{프론트주소}.vercel.app/"] diff --git a/homes/models.py b/homes/models.py index e69de29..f3e6588 100644 --- a/homes/models.py +++ b/homes/models.py @@ -0,0 +1,6 @@ +from django.db import models + +from common.models.baseModels import BaseModel + +class PreOrderedEmail(BaseModel): + email = models.EmailField() \ No newline at end of file diff --git a/homes/serializers.py b/homes/serializers.py index ec274bc..e48e16b 100644 --- a/homes/serializers.py +++ b/homes/serializers.py @@ -1 +1,10 @@ -# 포폴, 플젝 주간 랭킹, 광고 등 \ No newline at end of file +# 포폴, 플젝 주간 랭킹, 광고 등 +from .models import * +from rest_framework import serializers + + +class PreOrderedEmailSerializer(serializers.ModelSerializer): + + class Meta: + model = PreOrderedEmail + fields = ['email'] \ No newline at end of file diff --git a/homes/urls.py b/homes/urls.py index 626c39a..cb1bda8 100644 --- a/homes/urls.py +++ b/homes/urls.py @@ -1,9 +1,15 @@ from django.urls import include, path +from rest_framework.routers import DefaultRouter + from .views import * +preorder_router = DefaultRouter(trailing_slash=True) +preorder_router.register(r"email", PreOrderedAPIViewSet, basename="preorder") + app_name = 'homes' urlpatterns = [ path('search/', SearchAPIView.as_view()), + path("preorder/", include(preorder_router.urls)), ] \ No newline at end of file diff --git a/homes/views.py b/homes/views.py index 5aa23e2..f13709a 100644 --- a/homes/views.py +++ b/homes/views.py @@ -1,13 +1,18 @@ from rest_framework.views import APIView from rest_framework.response import Response from rest_framework import status, mixins, viewsets -from rest_framework.permissions import AllowAny, IsAuthenticated +from rest_framework.permissions import AllowAny, IsAuthenticated, IsAdminUser +from rest_framework.decorators import action from django.db import transaction +from django.core.mail import EmailMessage, get_connection + +from .models import * from .serializers import * from .services import * + from projects.models import Project from projects.serializers import ProjectListViewSerializer @@ -51,3 +56,36 @@ class SearchAPIView(APIView): "page": page, "page_size": page_size }, status=status.HTTP_200_OK) + + +class PreOrderedAPIViewSet(viewsets.ViewSet): + + @transaction.atomic + @action(detail=False, methods=["post"], url_path="register", permission_classes=[AllowAny]) + def register(self, request): + serializer = PreOrderedEmailSerializer(data=request.data) + if serializer.is_valid(): + serializer.save() + return Response({"registered": True}, status=status.HTTP_200_OK) + return Response({"registered": False}, status=status.HTTP_400_BAD_REQUEST) + + @transaction.atomic + @action(detail=False, methods=["post"], url_path="send", permission_classes=[IsAdminUser]) + def send(self, request): + try: + title = request.data["title"] + content = request.data["content"] + conn = get_connection() + emails = [] + email_list = PreOrderedEmail.objects.all() + for i, email_obj in enumerate(email_list): + if i >= 0 and i % 20 == 0: + conn.send_messages(emails) + conn.close() + conn = get_connection() + emails = [] + emails.append(EmailMessage(subject=title, body=content, to=[email_obj.email], connection=conn)) + conn.send_messages(emails) + return Response({"success": True}, status=status.HTTP_200_OK) + except Exception as e: + return Response({"success": False, "error": str(e)}, status=status.HTTP_500_INTERNAL_SERVER_ERROR) \ No newline at end of file