【问题标题】:Django notification email to users in ManyToMany relation给多对多关系用户的 Django 通知电子邮件
【发布时间】:2013-06-26 14:58:12
【问题描述】:

我想在创建新帖子时向“观察者”多对多字段中定义的用户列表发送通知电子邮件。

帖子创建时没有错误,并且观察者用户列表已成功添加到其中(它们出现在 post_detail.html 模板中),但通知电子邮件从未发送给观察者用户。

我认为我在下面的 new_post 函数中做错了,我改编自 this code 用于在用户在帖子上发送电子邮件时发送电子邮件,这确实有效。非常感谢任何帮助。

models.py(相关部分):

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")

views.py(相关部分):

@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,但仍然不起作用):

models.py

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")

编辑 2 2013 年 6 月 27 日星期四:11:48:49 意大利时间:

当我使用以下视图编辑/更新帖子时,通知电子邮件确实有效

views.py

@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))

【问题讨论】:

  • 您是否测试过电子邮件在信号之外的工作?
  • 是的,它在信号之外工作。
  • 您使用的是消息而不是通知;我认为您的编辑稍微改变了问题...
  • 上面Edit 2中的代码是views.py代码(我现在添加了views.py标题以使其更清晰),models.py代码没有改变。编辑2中的消息代码是提交表单后出现在页面上的消息,据我所知与电子邮件通知无关。

标签: python django


【解决方案1】:

首先,我认为你的多对多关系不应该有空白或空值,因为理想情况下每个观察者都是用户而不是无。这样可以避免尝试向 None 用户发送电子邮件,这可能会出错。

其次,我认为你可以使用

recipients = instance.observers.all().distinct()

而不是在列表上循环(distinct() 已经只考虑唯一用户)

第三,我不明白为什么你真的需要一个“distinct()”:一个用户可以多次成为观察者吗?

recipients = instance.observers.all()

第四,在您的代码中,您正在通过 instance.observers.all() 循环使用“观察者”,该“观察者”已经是用户。为什么要在收件人中附加observer.user?我认为追加观察者就足够了。

最后,确认收件人不为空。如果你测试了 notification.send(),你的代码看起来是正确的。

【讨论】:

  • 我尝试了你的建议,即上面的编辑代码,但电子邮件通知仍然不起作用:/
  • 感谢您的帮助,我会继续努力(明天回来)
  • 当我使用以下编辑视图编辑/更新帖子时,通知电子邮件确实有效:(请参阅 EDIT 2,2013 年 6 月 27 日星期四:11 :48:49 意大利时间 以上)。也许通知应用需要帖子的ID,而在添加视图中没有传递?
【解决方案2】:

想通了——现在在创建新帖子时,通知电子邮件会发送给观察者。

基本上我需要在设置post.id后call save a second time

views.py:

@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 的帮助)。

这里是肯定的:

models.py

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")

【讨论】:

    猜你喜欢
    • 2016-02-13
    • 1970-01-01
    • 1970-01-01
    • 2017-05-31
    • 1970-01-01
    • 1970-01-01
    • 2016-04-18
    • 2015-02-15
    • 2012-04-11
    相关资源
    最近更新 更多