如何在Django中为用户实现邮件退订功能?
在Django中实现邮件退订功能
我来帮你一步步搞定这个邮件退订功能,结合你现有的代码,咱们分这几个步骤来做:
1. 更新用户模型,添加订阅状态字段
首先得在你的User模型里加一个字段,用来标记用户是否愿意接收邮件。修改models.py:
from django.db import models from django.contrib.auth.models import AbstractUser, UnicodeUsernameValidator from django.utils.translation import gettext_lazy as _ class User(AbstractUser): username_validator = UnicodeUsernameValidator() username = models.CharField( _('username'), max_length=150, unique=True, help_text=_('Required. 150 characters or fewer. Letters, digits and @/./+/-/_ only.'), validators=[username_validator], error_messages={ 'unique': _("A user with that username already exists."), }, ) first_name = models.CharField(_('first name'), max_length=30, blank=True) last_name = models.CharField(_('last name'), max_length=150, blank=True) email = models.EmailField(_('email address'), unique=True) # 新增订阅状态字段,默认开启订阅 email_subscribed = models.BooleanField(_('email subscribed'), default=True)
然后执行迁移命令更新数据库:
python manage.py makemigrations python manage.py migrate
2. 修改邮件发送视图,只给订阅用户发邮件
接下来修改你views.py里的email_users_date函数,只给email_subscribed=True的用户发送邮件,同时修正原代码里msg未定义的问题:
@csrf_exempt def email_users_date(request): if not request.method == 'POST': return HttpResponse(status=400) json_data = json.loads(json.loads(request.body)[0]) date = json_data.get('date') # 只筛选订阅了邮件的用户 subscribed_users = User.objects.filter(email_subscribed=True) for user in subscribed_users: subject = 'Data updated' template = get_template('interface/emaildata.html') context = {'user': user, 'date': date} # 渲染HTML邮件内容 html_msg = template.render(context) text_msg = strip_tags(html_msg) send_mail(subject, text_msg, settings.DEFAULT_FROM_EMAIL, [user.email], html_message=html_msg) return HttpResponse(status=200)
3. 创建安全的退订视图和URL
我们用Django的signing模块生成带签名的URL,防止恶意篡改用户订阅状态。
3.1 编写退订视图
在views.py里添加:
from django.core import signing from django.shortcuts import render from django.contrib import messages def unsubscribe(request, signed_user_id): try: # 验证签名,链接30天内有效 user_id = signing.loads(signed_user_id, max_age=30*86400) user = User.objects.get(id=user_id) user.email_subscribed = False user.save() messages.success(request, '你已成功退订邮件,感谢你的支持!') except (signing.BadSignature, User.DoesNotExist): messages.error(request, '退订链接无效或已过期,请尝试重新获取') return render(request, 'interface/unsubscribe_confirm.html')
3.2 配置URL
在你的应用urls.py里添加:
from django.urls import path from . import views urlpatterns = [ # 其他URL... path('unsubscribe/<str:signed_user_id>/', views.unsubscribe, name='unsubscribe'), ]
4. 在邮件模板中添加退订链接
最后,在邮件模板里添加安全的退订链接。首先修改邮件发送视图的context,生成签名后的用户ID:
# 在email_users_date函数的context中新增签名ID from django.core import signing context = { 'user': user, 'date': date, 'signed_user_id': signing.dumps(user.id) }
然后在interface/emaildata.html邮件模板的底部添加:
<p>不想再收到此类邮件?<a href="{{ request.scheme }}://{{ request.get_host }}{% url 'unsubscribe' signed_user_id %}">点击这里退订</a></p>
这个链接会生成一个安全的、带签名的退订地址,用户点击后就能直接取消订阅。
可选:添加重新订阅入口
如果需要支持用户重新订阅,可以在个人中心页面添加一个开关,或者创建类似的重新订阅视图,逻辑和退订一致,只是将email_subscribed设为True即可。
内容的提问来源于stack exchange,提问作者user8427236
相关产品推荐
相关产品推荐

