我想在创建新帖子时将通知电子邮件发送到“观察者”ManyToMany字段中定义的用户列表。
创建的帖子没有错误,并且观察者用户列表已成功添加(它们显示在post_detail.html模板中),但通知电子邮件永远不会发送给观察者用户。
我认为我在下面的new_post函数中做错了,我在this code改编后用于在用户对帖子发表评论时发送电子邮件。任何帮助非常感谢。
from django.db import models
from django.contrib.auth.models import User
from django.contrib.sites.models import Site
from django.db.models import signals
from notification import models as notification
class Post(models.Model):
author = models.ForeignKey(User, related_name="added_posts")
observers = models.ManyToManyField(User, verbose_name=_("Observers"), related_name='observers+', blank=True, null=True)
# send notification to Post observers
def create_notice_types(app, created_models, verbosity, **kwargs):
notification.create_notice_type("new_post", "New post created", "A new post has been created")
signals.post_syncdb.connect(create_notice_types, sender=notification)
def new_post(sender, instance, created, **kwargs):
context = {
'observer': instance,
'site': Site.objects.get_current(),
}
recipients = []
pk=instance._get_pk_val()
for observer in instance.observers.all().distinct():
if observer.user not in recipients:
recipients.append(observer.user)
notification.send(recipients, 'new_post', context)
signals.post_save.connect(
new_post, sender=models.get_model(
'blog', 'Post'), dispatch_uid="pkobservers")
@login_required
def add(request, form_class=PostForm, template_name="blog/post_add.html"):
post_form = form_class(request)
if request.method == "POST" and post_form.is_valid():
post = post_form.save(commit=False)
post.author = request.user
post_form.save()
post_form.save_m2m()
return redirect("blog_user_post_detail",
username=request.user.username, slug=post.slug)
return render_to_response(template_name,
{"post_form": post_form}, context_instance=RequestContext(request))
还试过这个(删除blog_post和blog_post_observers表,然后再次运行manage.py syncdb
,但仍然无效):
class Post(models.Model):
# ....
observers = models.ManyToManyField(User, verbose_name=_("Observers"), related_name='observers+')
def new_post(sender, instance, created, **kwargs):
context = {
'observer': instance,
'site': Site.objects.get_current(),
}
recipients = instance.observers.all()
pk=instance._get_pk_val()
notification.send(recipients, 'new_post', context)
signals.post_save.connect(new_post, sender=models.get_model('blog', 'Post'), dispatch_uid="pkobservers")
当我编辑/更新帖子时,使用以下视图,通知电子邮件可以正常工作:
@login_required
def edit(request, id, form_class=PostForm, template_name="blog/post_edit.html"):
post = get_object_or_404(Post, id=id)
if post.author != request.user:
request.user.message_set.create(message="You can't edit items that aren't yours")
return redirect("desk")
post_form = form_class(request, instance=post)
if request.method == "POST" and post_form.is_valid():
post = post_form.save(commit=False)
post.updated_at = datetime.now()
post_form.save()
post_form.save_m2m()
messages.add_message(request, messages.SUCCESS, message=_("Successfully updated post '%s'") % post.title)
return redirect("blog_user_post_detail", username=request.user.username, slug=post.slug)
return render_to_response(template_name, {"post_form": post_form, "post": post}, context_instance=RequestContext(request))
答案 0 :(得分:2)
首先,我认为您的多对多关系不应该为空或空,因为每个观察者理想情况下都是用户而不是无。这样可以避免尝试向无用户发送电子邮件,这可能会导致错误。
其次,我认为你可以使用
recipients = instance.observers.all().distinct()
而不是在列表上循环(distinct()已经只考虑了唯一用户)
第三,我不明白为什么你真的需要一个“distinct()”:用户能不止一次成为观察者吗?
recipients = instance.observers.all()
第四,在你的代码中,你通过一个“观察者”(已经是一个用户)循环使用instance.observers.all()。为什么要将observer.user附加到收件人?我认为附加观察者就足够了。
最后,确认收件人不是空的。如果您已经测试了notification.send(),那么您的代码似乎是正确的。
答案 1 :(得分:0)
想出来 - 通知电子邮件现在在创建新帖子时发送给观察者。
基本上我在设置post.id后需要call save a second time:
@login_required
def add(request, form_class=PostForm, template_name="blog/post_add.html"):
post_form = form_class(request)
if request.method == "POST" and post_form.is_valid():
post = post_form.save(commit=False)
post.author = request.user
post_form.save()
post.id = post.id # set post id
post_form.save() # save a second time for notifications to be sent to observers
return redirect("blog_user_post_detail",
username=request.user.username, slug=post.slug)
return render_to_response(template_name,
{"post_form": post_form}, context_instance=RequestContext(request))
models.py与第一次编辑没有变化:在问题中(感谢J. C. Leitão的帮助)。
这是确定的:
class Post(models.Model):
observers = models.ManyToManyField(User, verbose_name=_("Observers"), related_name='observers+')
def new_post(sender, instance, created, **kwargs):
context = {
'observer': instance,
'site': Site.objects.get_current(),
}
recipients = instance.observers.all()
pk=instance._get_pk_val()
notification.send(recipients, 'new_post', context)
signals.post_save.connect(new_post, sender=models.get_model('blog', 'Post'), dispatch_uid="pkobservers")