Django:忽略 ManytoManyField 的只读表单控件

Django: Ignores read-only form-control of a ManytoManyField

我需要一些帮助来理解问题以便尝试修复它。

目前,对于链接到 ManytoManyfield 的多个 select 字段,我的表单忽略 readonly=True 或 readonly="readonly"。

但是,在同一表单中,readonly=True 按预期作用于 CharField(查看但不保存)

如果我使用 ignore=True,它适用于两个字段,但会保存一个空列表来替换原始值。

因此我认为问题与多个 select 字段结合只读有关,也许是因为我使用的是 Crispy 表单

问:什么组件决定了只读字段的行为为什么它似乎接受一种类型的字段而不接受另一种类型的字段? 感谢和问候

class Product(models.Model):
    product_type = models.CharField(max_length=22, blank=True)

class Package(models.Model):
    product_code = models.CharField(max_length=3)
    products = models.ManyToManyField('product.Product', blank=True)


class ProductModelForm(ModelForm):
    class Meta:
        model = Package
        fields = '__all__'


class ProductFieldsForm(ProductModelForm):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.helper = FormHelper()
        self.helper.form_class = 'form-horizontal'
        self.helper.label_class = 'col-sm-4'
        self.helper.field_class = 'col-sm-7'
        self.helper.form_tag = False

        prd_code = 'product_code'
        prds = 'products'

        self.helper.layout = Layout (
            Field(prd_code, readonly=True), # WORKS FINE, as intended
            Field(prds, readonly=True), # **CAN CHANGE and SAVE (gray area)**
        )

结果 html(我也尝试过使用 readonly="readonly",但结果相同。使用 Firefox 69)

<div class="col-sm-7"><select name="product" readonly="True" class="selectmultiple form-control" id="id_product"
                              multiple>
    <option value="4">Product 4</option>
    <option value="5">Product 5</option>
    <option value="6">Product 6</option>
    <option value="3" selected>Product 3</option>

</select></div>

经过一番研究,这似乎是一个普遍问题。

看来问题是只读一个值很容易,但很难只读一列值。

我找到的解决方案是变通方法,例如脚本。

下面效果很好,这意味着您添加了一个 disabled = "true" 但在提交表单之前,您通过脚本将其删除,我将此脚本称为: onsubmit="form" 在模板的表单标记中.

    $('form').submit(function () {
      $('[disabled]').removeAttr('disabled');
      })

('disable' 给出了一个被截断和锁定的列表,但是这个列表没有保存,而是保存了一个空列表)。

我在这里找到了答案: