Django 管理员 get_readonly_fields 不一致的行为

Django admin get_readonly_fields inconsistent behavior

我有与 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 的答案,其中关于内联管理元素据说它不会'与我所相信的相反,这没有道理,因为:

It also makes no sense to set values like that in init, since the Modeladmin instance is created once and may persist for a lot more than one request!

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

在我这边,我尝试使用 get_object() 方法获取 __init__() 中的对象,但我需要提供对象 ID,但我仍未弄清楚如何访问.但是如果我在上面读到的是真的,那么向构造函数提供逻辑仍然是无用的,因为无论如何实例都会比请求持续更长时间。

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

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

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

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

试试这个:

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