管理员中的 Django ModelForm 多次保存

Django ModelForm in admin saving multiple times

我正在尝试实现一个简单的功能,如果您在保存时在管理员中选中了一个复选框,它会发送一封电子邮件。例如:将一篇简单的文章输入到管理员中,当我点击保存时,它会发送文章的内容(如果选中该复选框)。得到了工作,但由于某种原因它发送了 3 次! 这里 post 的代码太多了,但这应该足以了解发生了什么,如果它对夹层博客管理部分(我已经克隆)有帮助的话。

class YourModelForm(forms.ModelForm):
    send_email = forms.BooleanField(required=False)
    def save(self, commit=True):
        send_email = self.cleaned_data.get('send_email', None)
        content = self.cleaned_data.get('content', None)
        if send_email == True:
            print 'sending' #email stuff here 
        return super(YourModelForm, self).save(commit=commit)

    class Meta:
        model = Ite
        fields = '__all__'

class IteAdmin(TweetableAdminMixin, DisplayableAdmin, OwnableAdmin):
    form = YourModelForm
    readonly_fields=('email_sent',)
    fieldsets = ite_fieldsets 


    def save_form(self, request, forms, change):
        """
        Super class ordering is important here - user must get saved first.
        """
        OwnableAdmin.save_form(self, request, forms, change)
        return DisplayableAdmin.save_form(self, request, forms, change)

我认为 admin ModelForm 不是触发邮件发送的好地方。 我建议使用这样的信号:

from django.db.models.signals import post_save

class MyModel(models.Model):
    ...


def send_mail_for_my_model(sender, instance, created, **kwargs):
    if created:
        print "send mail"
        #email stuff

post_save.connect(send_mail_for_my_model, sender=MyModel)

我猜你的情况是: OwnableAdmin.save_form() 调用 YourModelForm.save,从而发送邮件。 比 DisplayableAdmin.save_form() 调用 YourModelForm.save,再次发送邮件。 发生这种情况是因为 save_form(self) 的第一个参数是 IteAdmin 的实例,其 form 属性设置为 YourModelForm 并且每个 class subclasses ModelAdmin。

我想如果你想使用 ModelForm,你应该使用这样的方法:

class OwnableAdmin(ModelAdmin):
    def save_form(self, request, forms, change):
        #do your actions
        return super(OwnableAdmin, self).save_form(request, forms, change)


class DisplayableAdmin(ModelAdmin):
    def save_form(self, request, forms, change):
        #do your actions
        return super(DisplayableAdmin, self).save_form(request, forms, change)


class TweetableAdminMixin(object):
    ...    


class IteAdmin(OwnableAdmin, DisplayableAdmin, TweetableAdminMixin):
    form = YourModelForm
    readonly_fields=('email_sent',)
    fieldsets = ite_fieldsets 

    def save_form(self, request, forms, change):
        #do your actions
        return super(IteAdmin, self).save_form(request, forms, change)

顺便说一句,在 python3 中,您可以使用不带参数的 super()。

也许在您的情况下,每个模型都可以从另一个模型继承,例如:

class TweetableAdmin(ModelAdmin):
    ...

class DisplayableAdmin(TweetableAdmin):
    ...


class OwnableAdmin(DisplayableAdmin):
    ...

class IteAdmin(OwnableAdmin):
    ...

无论如何,我建议阅读这篇关于 python super 的文章:

http://www.artima.com/weblogs/viewpost.jsp?thread=236275