【问题标题】:Django admin get_readonly_fields inconsistent behaviorDjango admin get_readonly_fields 不一致的行为
【发布时间】:2021-12-22 10:50:13
【问题描述】:

我和this other thread有同样的要求,我用的是Django 3.2.8

对于我的项目,管理页面中的某些字段必须根据同一模型对象的一个​​布尔字段的值变为只读,因此我应用了上面另一个线程中建议的解决方案。

class OrdineAdmin(admin.ModelAdmin):

   inlines = [
       FatturaAdmin
   ]
   readonly_fields = ["data"]

   def get_readonly_fields(self, request, obj=None):
       if obj and obj.pagato == True:
           self.readonly_fields = ['utente', 'abbonamento', 'importo', 'giorni_attivi_abbonamento', 'data']
       return self.readonly_fields

正如我所料,此解决方案会导致管理面板出现一些不一致,因为会在内存中生成一个 OrdineAdmin 实例,但不会在每次请求时更新。因此,当我将字段“pagato”设置为 True 时,此方法会按预期将所有其他字段设置为只读,但如果我将该字段设置回 False,即使通过管理面板的保存过程成功,也不会反转其效果。

这就是为什么我认为需要在 __init__() 方法内完成一些事情,但我阅读了this other thread 的答案,其中关于内联管理元素据说它没有意义,相反我所相信的,因为:

init 中设置类似的值也没有任何意义,因为 Modeladmin 实例只创建一次,并且可能会持续多次请求!

所以现在我完全糊涂了。如何在 ModelAdmin 页面上为每个请求授予更新,以使我的只读字段逻辑的行为保持一致?

就我而言,我尝试使用get_object() 方法获取__init__() 中的对象,但我需要提供我仍然不知道如何访问的对象ID。但是,如果我在上面读到的是真的,那么向构造函数提供逻辑仍然没有用,因为无论如何实例的持续时间都比请求长。

也许我应该使用get_form() 或在我的情况下使用get_formsets_with_inlines() 来处理表单并自定义这些方法?但是我如何确保在每次请求时都重新生成它们?

【问题讨论】:

    标签: django django-models django-forms django-admin init


    【解决方案1】:

    pagato 设置为 True 时,您将使用以下行覆盖 readonly_fields 属性:

    self.readonly_fields = ['utente', 'abbonamento', 'importo', 'giorni_attivi_abbonamento', 'data']
    

    因此,当pagato 再次设置为 False 时,get_readonly_fields 返回更新版本而不是原始版本。

    试试这个:

    class OrdineAdmin(admin.ModelAdmin):
    
       inlines = [
           FatturaAdmin
       ]
       readonly_fields = ["data"]
    
       def get_readonly_fields(self, request, obj=None):
           if obj and obj.pagato == True:
               return ['utente', 'abbonamento', 'importo', 'giorni_attivi_abbonamento', 'data']
           return self.readonly_fields
    

    或者更简洁:

    class OrdineAdmin(admin.ModelAdmin):
    
       inlines = [
           FatturaAdmin
       ]
    
       def get_readonly_fields(self, request, obj=None):
           if obj and obj.pagato == True:
               return ['utente', 'abbonamento', 'importo', 'giorni_attivi_abbonamento', 'data']
           return ["data"]
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2013-12-09
      • 1970-01-01
      • 2014-07-11
      • 1970-01-01
      • 1970-01-01
      • 2020-10-18
      • 2011-08-13
      相关资源
      最近更新 更多