Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add unsubscribe functionality at backend (#236) #237

Open
wants to merge 12 commits into
base: main
Choose a base branch
from
7 changes: 6 additions & 1 deletion backend/djangoindia/api/urls/communication.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,14 @@
from django.urls import path

from djangoindia.api.views.communication import ContactUsAPIView, SubscriberAPIView
from djangoindia.api.views.communication import (
ContactUsAPIView,
SubscriberAPIView,
UnsubscribeAPIView,
)


urlpatterns = [
path("subscriber/", SubscriberAPIView.as_view(), name="subscriber"),
path("unsubscribe/<uuid:token>/", UnsubscribeAPIView.as_view(), name="unsubscribe"),
path("contact-us/", ContactUsAPIView.as_view(), name="contact-us"),
]
25 changes: 25 additions & 0 deletions backend/djangoindia/api/views/communication.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
from rest_framework.mixins import CreateModelMixin
from rest_framework.response import Response

from django.shortcuts import get_object_or_404

from djangoindia.api.serializers.communication import (
ContactUsSerializer,
SubscriberSerializer,
Expand Down Expand Up @@ -33,6 +35,29 @@ def post(self, request, *args, **kwargs):
)


class UnsubscribeAPIView(generics.GenericAPIView):
def delete(self, request, token=None):
try:
unsubscribe_token = token
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@prakkhar03, we should avoid using try-except unless there’s code where we’re uncertain about how it might fail. Also you can use token directly to check condition no need to store at another variable

if not unsubscribe_token:
return Response(
{"message": "Unsubscribe token is required."},
status=status.HTTP_400_BAD_REQUEST,
)
subscriber = get_object_or_404(
Subscriber, unsubscribe_token=unsubscribe_token
)
subscriber.delete()
return Response(
{"message": "You have been unsubscribed. We're sad to see you go. 😢"},
status=status.HTTP_200_OK,
)
except Exception as e:
return Response(
{"message": str(e)}, status=status.HTTP_500_INTERNAL_SERVER_ERROR
)


class ContactUsAPIView(generics.GenericAPIView, CreateModelMixin):
def post(self, request):
try:
Expand Down
9 changes: 8 additions & 1 deletion backend/djangoindia/bg_tasks/send_update.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import logging
import os

from celery import shared_task

Expand Down Expand Up @@ -31,9 +32,15 @@ def send_mass_update_email_task(update_id):

for recipient in recipients:
try:
if not recipient.unsubscribe_token:
recipient.generate_unsubscribe_token()

api_url = os.environ.get("API_URL")
unsubscribe_url = f"{api_url}{recipient.unsubscribe_token}/"

html_content = render_to_string(
"admin/update_mail.html",
{"body": mark_safe(update.email_body), "subscriber": recipient},
{"body": mark_safe(update.email_body), "subscriber": recipient, "unsubscribe_url": unsubscribe_url},
)
plain_text_content = strip_tags(html_content)

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# Generated by Django 5.1.2 on 2024-12-10 16:07

from django.db import migrations, models


class Migration(migrations.Migration):

dependencies = [
('db', '0012_rename_html_template_update_email_body_and_more'),
]

operations = [
migrations.AddField(
model_name='subscriber',
name='unsubscribe_token',
field=models.CharField(blank=True, max_length=255, null=True, unique=True),
),
]
9 changes: 9 additions & 0 deletions backend/djangoindia/db/models/communication.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import uuid

from django.db import models

from .base import BaseModel
Expand All @@ -6,10 +8,17 @@
class Subscriber(BaseModel):
name = models.CharField(max_length=100)
email = models.EmailField()
unsubscribe_token = models.CharField(
max_length=255, unique=True, blank=True, null=True
)

def __str__(self):
return self.email

def generate_unsubscribe_token(self):
self.unsubscribe_token = uuid.uuid4().hex
self.save()


class ContactUs(BaseModel):
first_name = models.CharField(max_length=100)
Expand Down
1 change: 1 addition & 0 deletions backend/templates/admin/update_mail.html
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@
</div>
<div class="footer">
<p>&copy; 2024 Django India Community. All rights reserved.</p>
<a href={{unsubscribe_url}}>Unsubscribe</a>
<div class="social-links-container">
<ul class="social-links">
<li><a href="https://www.twitter.com/djangoindiaa" target="_blank">Twitter</a></li>
Expand Down