Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/solr/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在Django的post save信号中发送电子邮件时出现问题_Django_Django Signals_Django Email - Fatal编程技术网

在Django的post save信号中发送电子邮件时出现问题

在Django的post save信号中发送电子邮件时出现问题,django,django-signals,django-email,Django,Django Signals,Django Email,在post_save信号中保存某个模型后,我试图发送一封电子邮件,但当我第一次保存模型时,电子邮件未发送,如果我在第二次发送电子邮件时保存模型 笔记 该模型有一个manytomy字段,因此我无法使用pre_save信号,因为它引发了一个错误:“需要为字段“id”设置一个值才能使用此多对多关系。 我所拥有的 模型 类消息(TimeStampedModel,models.Model): “”“消息的表示形式。”“” 收件人=models.ManyToManyField( to=settings.AU

post_save
信号中保存某个模型后,我试图发送一封电子邮件,但当我第一次保存模型时,电子邮件未发送,如果我在第二次发送电子邮件时保存模型

笔记 该模型有一个
manytomy
字段,因此我无法使用
pre_save
信号,因为它引发了一个错误:
“需要为字段“id”设置一个值才能使用此多对多关系。

我所拥有的 模型 类消息(TimeStampedModel,models.Model): “”“消息的表示形式。”“” 收件人=models.ManyToManyField( to=settings.AUTH\u USER\u MODEL,verbose\u name=\u(“收件人”) ) 主题=models.CharField( 详细名称=uu(“主题”), 帮助文本=_( “150个数字/字母或更少。只允许字母和数字。” ), 最大长度=150, 验证器=[字母、重音和数字], ) content=models.TextField(详细名称=uu(“消息”)) 信号
@receiver(信号=post\u save,发送方=Message)
def send_消息(发送方,实例,**kwargs):
“”“如果创建了新邮件,请发送电子邮件或Whatsapp。”“”
收件人\电子邮件=[recipient.email for recipient in instance.recipients.all()]
附件=[]
如果设置了instance.messagefile\u:
对于instance.messagefile_set.all()中的message_文件:
附件.append((message\u file.file.name,message\u file.file.read())
寄信(
subject=instance.subject,
message=instance.content,
收件人列表=收件人电子邮件,
附件=附件,
)
发送邮件包装器以发送电子邮件 这是用于发送电子邮件的信号中的功能

def发送电子邮件(
主题:str,
信息:str,
收件人列表:列表[str],
from_电子邮件:可选[str]=无,
**夸尔斯,
)->int:
“”“在send_mail()中完成Django电子邮件的包装()。
自定义from_电子邮件处理和特殊自动提交标题。
"""
如果不是通过电子邮件:
如果hasattr(设置,“来自电子邮件的默认值”):
from_email=settings.DEFAULT_from_email
其他:
从_电子邮件=”webmaster@localhost"
connection=kwargs.get(“connection”,False)或get\u connection(
username=kwargs.get(“auth_user”,无),
password=kwargs.get(“auth_password”,无),
静默失败=kwargs.get(“静默失败”,无),
)
多个备选方案={
“连接”:连接,
“标题”:{“自动提交”:“自动生成”},
}
邮件=电子邮件(
主语,
body=消息,
from_email=from_email,
收件人=收件人列表,
**多个备选方案,
)
附件=kwargs.get(“附件”,无)
如有附件:
附件中的附件:
如果存在(附件,MIMEBase):
邮件。附件(附件)
其他:
邮件。附件(*附件)
返回邮件。发送()

在创建
消息时,以及在创建(而不是更新)
消息后(因此当调用
post_save
信号时),所有
ManyToManyField
s均为空,与所有
ForeignKey
s相反)。这很有意义,因为在创建两个记录之间的多对多关系之前,需要将这些记录保存到数据库中,否则这些记录没有主键,因此无法链接

我建议不要为此使用信号。严格来说,您可以尝试使用,例如:

从django.contrib.auth导入get\u user\u模型
从django.db.models.signals导入m2m_已更改
添加了def收件人(发件人、实例、操作、主键集,**kwargs):
如果操作=='post_add':
收件人\电子邮件=列表(获取\用户\模型().objects.filter(pk\uu-in=pk\u集))
“m2m_已更改”。连接(已添加收件人,发件人=Message.recipients.through)
但是,现在有可能以后保存
messagefile\u set
,因此仍然存在问题

我建议将发送电子邮件的逻辑封装在函数中,然后在创建对象后在视图中调用该函数

例如,如果您有一个带有
MessageForm
的视图:

def发送消息(请求):
如果request.method==“POST”:
form=MessageForm(request.POST、request.FILES)
如果form.is_有效():
message=form.save()
发送消息(消息)
在这里,
form
不仅会保存对象,还会保存它处理的多对多字段。因此,在
form.save()
之后,对象的保存就完全完成了

ModelAdmin
中,您可以使用:

来自django.contrib导入管理
类MessageAdmin(admin.ModelAdmin):
def保存相关(自我、请求、表单、表单集、更改):
super().save_相关(请求、表单、表单集、更改)
发送邮件(form.instance)

当然可以修改它。首先调用
.save\u related()
超级方法非常重要,因为这将调用
表单.save()
这将再次处理多对多关系等。

创建对象时,m2m关系中没有对象。只有在对象保存到数据库后,才能填充m2m关系,因为它需要链接对象的pks,因此
实例。messagefile\u set
为空。我建议不要使用signals,但只调用视图中的函数创建
Message
s的地方。视图有一定的用途,但经常被过度使用,而且往往是反模式@WillemVanOnsem我有一些问题;
instance.messagefile\u set
只检查模型是否有附件,如果有,它会将附件添加到atachm中,它不会控制任何消息的发送。但是