Django - how can I make a cell in a table in the admin *changelist* interface editable only if it is null?

前端 未结 1 408
情书的邮戳
情书的邮戳 2021-01-28 05:08

I would like my data to be editable inline in the Django admin page. However, I only want some fields columns in each row to be editable. These columns will change for each ro

相关标签:
1条回答
  • 2021-01-28 05:43

    If your field uses an input element, such as a TextField, add the readonly attribute to the field's widget's attrs dict in the changelist form's __init__ method. Something like this:

    class PamphletChangeListForm(forms.ModelForm):
    
        def __init__(self, *args, **kwargs):
            super(PamphletChangeListForm, self).__init__(*args, **kwargs)
            instance = kwargs.get('instance')
            if instance:
                self.fields['book'].queryset = Book.objects.filter(
                    size=instance.size
                )
                if instance.size is not None:
                    self.fields['size'].widget.attrs['readonly'] = 'readonly'
    

    That won't protect you against a malicious user faking post data - for that you'd need to customize your admin further. But if you have malicious users on your admin you have bigger problems.

    If your field uses a select element, you have to change it more - select attributes don't have readonly as a supported attribute. Instead, you'll want a hidden input with the unchanging value, and a text representation so the user can see what the setting is. Django does not include such a widget, but you can define your own:

    class LabeledHiddenInput(forms.widgets.HiddenInput):
        def render(self, name, value, attrs=None):
            base_output = super(LabeledHiddenInput, self).render(name, value, attrs)
            if value:
                return base_output + unicode(value)
            else:
                return base_output
    

    You might need more careful escaping or even some HTML formatting, this is just a quick example. Check the source code for the built in widgets if you need more examples.

    Then you can use that widget instead of the default select:

            if instance.size is not None:
                self.fields['size'].widget = LabeledHiddenInput()
    
    0 讨论(0)
提交回复
热议问题