如何向django-registration视图传递上下文,为邮件注入全局变量
你找对路子了——子类化确实是避免修改django-registration源码、同时实现需求的最佳方式,而且完全不用给每个视图都写子类,我们可以通过子类化HMAC后端+少量视图定制来实现最小改动,具体分两种情况:
情况1:你的全局变量不依赖request(比如网站名称、从settings读取的配置)
这种情况改动最小,只需要定制后端和一个视图:
- 创建自定义HMAC后端
在你的项目app(比如core)下新建backends.py:
from registration.backends.hmac import HMACBackend from django.template.context_processors import get_context_processors from django.conf import settings class CustomHMACBackend(HMACBackend): def get_email_context(self, activation_key): # 先拿到django-registration默认的邮件上下文(比如激活链接) context = super().get_email_context(activation_key) # 注入所有你注册的上下文处理器的全局变量 for processor in get_context_processors(settings): # 这里传None,适合不依赖request的处理器(比如从settings拿站点名称的) context.update(processor(None)) return context
- 子类化注册视图,绑定自定义后端
在core/views.py里:
from registration.backends.hmac.views import RegistrationView from .backends import CustomHMACBackend class CustomRegistrationView(RegistrationView): # 指定用我们的自定义后端处理注册逻辑 backend_class = CustomHMACBackend
- 微调urls.py
只替换默认的注册视图路径,其他账号相关路由保持不变:
from django.urls import path, include from core.views import CustomRegistrationView urlpatterns = [ path('', include('core.urls')), path('admin/', admin.site.urls), # 替换默认注册视图 path('accounts/register/', CustomRegistrationView.as_view(), name='registration_register'), # 其余账号路由依然用django-registration的默认配置 path('accounts/', include('registration.backends.hmac.urls')), ]
搞定!现在激活邮件模板里就能直接用你上下文处理器里的全局变量了,比如{{ site_name }}。
情况2:你的全局变量依赖request(比如当前请求的域名、用户的语言偏好)
这种情况需要把request传递到邮件上下文里,稍微调整一下:
- 更新自定义后端
修改core/backends.py,让发送邮件的方法支持request参数:
from registration.backends.hmac import HMACBackend from django.template import RequestContext from django.conf import settings class CustomHMACBackend(HMACBackend): def send_activation_email(self, user, request=None): activation_key = self.get_activation_key(user) context = self.get_email_context(activation_key) context.update({'user': user}) # 如果有request,用RequestContext获取完整的全局上下文 if request: context.update(RequestContext(request)) else: # 没有request时的降级处理,兼容不依赖request的场景 from django.template.context_processors import get_context_processors for processor in get_context_processors(settings): context.update(processor(None)) # 下面是原方法的逻辑,完全保留 subject = render_to_string(self.email_subject_template, context) subject = ''.join(subject.splitlines()) message = render_to_string(self.email_body_template, context) user.email_user(subject, message, settings.DEFAULT_FROM_EMAIL)
- 修改自定义注册视图,传递request
在core/views.py里重写发送邮件的方法:
from registration.backends.hmac.views import RegistrationView from .backends import CustomHMACBackend class CustomRegistrationView(RegistrationView): backend_class = CustomHMACBackend def send_activation_email(self, user): # 把当前请求对象传给后端的发送邮件方法 self.backend.send_activation_email(user, request=self.request)
- urls.py的修改和情况1一致
扩展到其他邮件(比如密码变更)
如果需要给密码变更、重置等邮件也注入全局变量,逻辑完全一样:找到对应的视图(比如django-registration的PasswordChangeView),子类化它,重写发送邮件的方法,要么传递request,要么直接注入上下文变量即可。
验证一下
现在你可以在激活邮件模板(比如registration/activation_email.txt)里直接使用全局变量了:
欢迎来到{{ site_name }}!请点击下面的链接激活你的账号: {{ activation_url }}
内容的提问来源于stack exchange,提问作者zerohedge
相关产品推荐
相关产品推荐

