Django – ModelForm field 에 data- 속성 추가하기

Form field 가 html 로 렌더링 될 때 원하는 속성값을 부가 하고 싶은데, 장고 코드에서 자동으로 하고 싶다.

이래 저래 찾다가 코드가 발견

class CompanySelect(forms.Select):
    def create_option(self, name, value, label, selected, index, subindex=None, attrs=None):
        option = super().create_option(name, value, label, selected, index, subindex, attrs)
        if value:
            option["attrs"]["data-company"] = value.instance.company_id
        return option


class ProductProfileForm(forms.ModelForm):
    class Meta:
        model = ProductProfile
        fields = ["company", "name", "product", "fwver1", "fwver2", "fwver3", "fwver4", "testset", "boxlabel", "boxpq"]
        # exclude = ["order", "status", "date_done", "elapsed_time", "mode", "desc", "is_deleted", "updated_at", "created_at"]
        # fields = ["order", "product", "workline", "fwver", "testset", "quantity", "date_due", "box", "boxpq", "status"]
        labels = {
            "company": _("*회사명"),
            "product": _("상품명"),
...}

        widgets = {
            "company": forms.Select(attrs={"class": "form-select"}),
            # "product": forms.Select(attrs={"class": "form-select flex-fill", "required": True, "style": "width: 100px;"}),
            "product": CompanySelect(attrs={"class": "form-select flex-fill companyselect", "required": True}),
...

원래 그냥 forms.Select 만 쓰면 특별히 해당 필드 값을 가지고 속성을 별도로 주는 것이 어렵다. 클래스 처럼 한꺼번에 줄 수 는 있어도 해당 값에 맞는 값을 DB 에서 가져와서 넣어주는게 힘들다. 예를 들면 해당 레코드별로 있는 ID 값을 data-code 속성에 넣어주는 그런것은 하기 어렵다.

이때는 forms.Select 를 오버라이딩 해서 사용하면 된다.

CompanySelect 클래스를 참고하면 된다. 원하는 DB instance 의 값을 바로 쓸 수 있다.

아래 처럼 data-company 값이 떡 하니 적혀져서 렌더링 된다. 이값을 이용해서 코드를 작성하면 편리하게 활용할 수 있다.

<select name="form-0-product" class="form-select companyselect" required="" id="id_form-0-product">
  <option value="" selected="" style="display: none;">---------</option>

  <option value="200" data-company="1" style="display: none;">test1 (twareLAB)</option>

  <option value="208" data-company="1" style="display: none;">test11 (twareLAB)</option>

  <option value="221" data-company="1" style="display: none;">TJ100 (twareLAB)</option>

  <option value="244" data-company="1" style="display: none;">TW100XR (twareLAB)</option>

  <option value="222" data-company="9" style="">Product1 (WIZnet)</option>

  <option value="3" data-company="9" style="">Test (WIZnet)</option>

  <option value="210" data-company="10" style="display: none;">Product1-1 (TEST Company)</option>

  <option value="219" data-company="10" style="display: none;">Product1-111 (TEST Company)</option>

  <option value="220" data-company="10" style="display: none;">Product1-123 (TEST Company)</option>
</select>