Readonly for existing items only in Django admin inline

前端 未结 7 1303
长发绾君心
长发绾君心 2020-12-13 14:27

I have a tabular inline model in the Django admin. I need 1 of the fields to not be changeable after it has been created, but setting it as readonly (via readonly_fields) wh

7条回答
  •  佛祖请我去吃肉
    2020-12-13 15:00

    This is possible with a monkey patch.

    The following example will make the "note" field to be read only for existing AdminNote objects. Unlike converting fields to be hidden like suggested in other answers, this will actually remove fields from the submit/validation workflow (which is more secure and uses existing field renderers).

    #
    # app/models.py
    #
    
    class Order(models.Model):
        pass
    
    class AdminNote(models.Model):
        order = models.ForeignKey(Order)
        time = models.DateTimeField(auto_now_add=True)
        note = models.TextField()
    
    
    #
    # app/admin.py
    #
    
    import monkey_patches.admin_fieldset
    
    ...
    
    class AdminNoteForm(forms.ModelForm):
        class Meta:
            model = AdminNote
    
        def __init__(self, *args, **kwargs):
            super().__init__(*args, **kwargs)
            for field in self.get_readonly_fields():
                del self.fields[field]
    
        def get_readonly_fields(self):
            if self.instance.pk:
                return ['note']
            return []
    
    
    class AdminNoteInline(admin.TabularInline):
        model = AdminNote
        form = AdminNoteForm
        extra = 1
        fields = 'note', 'time'
        readonly_fields = 'time',
    
    
    @admin.register(Order)
    class OrderAdmin(admin.ModelAdmin):
        inlines = AdminNoteInline,
    
    
    #
    # monkey_patches/admin_fieldset.py
    #
    
    import django.contrib.admin.helpers
    
    
    class Fieldline(django.contrib.admin.helpers.Fieldline):
        def __init__(self, *args, **kwargs):
            super().__init__(*args, **kwargs)
            if hasattr(self.form, 'get_readonly_fields'):
                self.readonly_fields = list(self.readonly_fields) + list(self.form.get_readonly_fields())
    
    django.contrib.admin.helpers.Fieldline = Fieldline
    

提交回复
热议问题