如何在保存一次后将模型实例设为只读?

时间:2009-01-21 17:11:15

标签: python django django-models django-admin django-signals

我写的Django项目的一个功能是发送简报。我有一个模型,Newsletter和一个函数send_newsletter,我已注册这个函数来收听Newsletter的{​​{1}}信号。通过管理界面保存新闻稿对象时,post_save会检查send_newsletter是否为True,如果是,则实际发送邮件。

然而,由于显而易见的原因,编辑已发送的简报并没有多大意义。有没有办法让created对象在保存后只读它?

编辑:

我知道我可以覆盖对象的Newsletter方法来引发错误,或者如果对象存在则不知道。但是,我没有看到这样做的意义。至于前者,我不知道在哪里捕获该错误以及如何向用户传达该对象未被保存的事实。对于后者,给用户提供错误的反馈(管理界面说保存成功)似乎不是一件好事。

我真正想要的是允许用户使用Admin界面编写新闻稿并发送,然后浏览已发送的新闻稿。我希望管理界面在不可编辑的输入框中显示已发送简报的数据,而不使用“保存”按钮。或者,我希望“保存”按钮不活动。

4 个答案:

答案 0 :(得分:7)

您可以在模型的save方法中检查它是创建还是更新:

def save(self, *args, **kwargs):
    if self.pk:
        raise StandardError('Can\'t modify bla bla bla.')
    super(Payment, self).save(*args, **kwargs)
如果您尝试保存现有对象,

上面的代码将引发异常。 以前未保留的对象没有设置主键。

答案 1 :(得分:1)

建议阅读:chapter 17 of the Django Book中的管理员之禅。

摘要:管理员不是为您要做的事情设计的:(

然而,本书的1.0版本仅涵盖了Django 0.96,自那以后发生了很多事情。

在Django 1.0中,admin site更易于定制。由于我自己没有自定义管理员,因此我必须根据文档进行猜测,但我会说overriding the model form是您最好的选择。

答案 2 :(得分:0)

在ur amdin.py中使用readonlyadmin。列出你想要只读的所有字段。创建对象后,你可以编辑它们然后

使用链接

http://www.djangosnippets.org/snippets/937/

复制该文件,然后在您的admin.py中导入并使用它

答案 3 :(得分:0)

您可以轻松完成的任务是将所有字段设为只读:

class MyModelAdmin(ModelAdmin):
    form = ...
    def get_readonly_fields(self, request, obj=None):
        if obj:
            return MyModelAdmin.form.Meta.fields
        else: # This is an addition
            return []

至于让Save消失,如果

会更容易
  1. has_change_permission返回False将禁用甚至显示表单
  2. 负责呈现管理表单控件的代码段(admin_modify.submit_row templatetag),无法无条件地使用show_save=True
  3. 无论如何,有一种方法可以让那个人不被渲染:

    1. 使用正确的逻辑创建has_change_permission的备用版本:

      class NoSaveModelAdminMixin(object):
          def render_change_form(self, request, context, add=False, change=False, form_url='', obj=None):
              response = super(NoSaveModelAdmin, self).render_change_form(request, context, add, change,form_url, obj)
              response.context_data["has_change_permission"] = self.has_real_change_permission(request, obj)
          def has_real_change_permission(self, request, obj):
              return obj==None
          def change_view(self, request, object_id, extra_context=None):
              obj = self.get_object(request, unquote(object_id))
              if not self.has_real_change_permission(request, obj) and request.method == 'POST':
                  raise PermissionDenied 
              return super(NoSaveModelAdmin, self).change_view(request, object_id, extra_context=extra_context)
      
    2. 覆盖与此类似的submit_row模板标签:

      @admin_modify.register.inclusion_tag('admin/submit_line.html', takes_context=True)
      def submit_row(context):
          ...
              'show_save': context['has_change_permission']
          ...
      
      admin_modify.submit_row = submit_row
      
相关问题