Django - modal 창에 form error 출력

Django - modal 창에 form error 출력
Photo by Kai Pilger / Unsplash

Django model forms (https://github.com/trco/django-bootstrap-modal-forms/blob/master/README.rst) 이용하고 있는데, 모달 창이 뜬 상태에서 form submit 을 수행하고, 에러가 발생하면 해당 모달창에 바로 띄워주고 싶어서 시도!

원래 제공되는 기능인데, 그냥 쓴 방법을 정리해 둔다.

모달창 템플릿 코드는 아래와 유사하게 되어 있다. 여기서 div class="invalid" 부분이 중요하다. 여기서 class invalid 부분을 빼 버리면, 모달창에 표시되는게 아니라 전체 페이지가 모달 창을 띄우는 페이지로 바뀌어 버려 브라우저 전체에 모달창 템플릿만 표기되는 문제가 있다.


  <div class="modal-body">
        <div class="invalid mb-2">
          {% for error in form.non_field_errors %}
          <p class="help-block text-sm text-danger mb-2">{{ error }}</p>
          {% endfor %}
        </div>
        {% for field in form %}
        <div class="row mb-1 align-middle">
          <div class="col-3">
            <div class="text-sm text-right" for="{{ field.id_for_label }}">{{ field.label }}</div>
          </div>
          <div class="col-auto">
            {{field}}
            <div class="{% if field.errors %}invalid{% endif %}">
              {% for error in field.errors %}
                <p class="help-block text-sm text-danger mb-2">{{ error }}</p>
              {% endfor %}
            </div>
          </div>
        </div>
        {% endfor %}
  </div>

설명이 어려워서 그림으로 남겨둔다.

이렇게 표기되기를 원하는데, 빨간색 표기는 <p> 태그에 의해서 표기되는 것이라 div class invalid 를 빼고 실행했더니, 쩝 모달창이 사라지고 전체페이지를 잡아 먹는 모양새가 되버리네.  class css 에 먼가가 정리되어 있나 보다.

일단 그럼 에러를 띄워주는 부분의 코드는 아래를 참고

class ShippingProductUpdateForm(BSModalModelForm):
    class Meta:
        model = ShippingProduct
        fields = ["shipping_company", "product", "serial", "status", "date_shipping"]
        labels = {
            "shipping_company": _("출고회사"),
            "product": _("*상품"),
            "serial": _("*시리얼"),
            "status": _("*상태"),
            "date_shipping": _("*출고일"),
        }
        widgets = {
            "shipping_company": forms.Select(attrs={"class": ""}),
            "product": forms.Select(attrs={"class": "", "placeholder": "상품"}),
            "serial": forms.TextInput(attrs={"class": ""}),
            "status": forms.Select(attrs={"class": ""}),
            "date_shipping": forms.DateInput(attrs={"type": "date"}),
        }

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        print("ShippingProductUpdateForm init", self.request.user.profile.level, self.request.user.profile.company)
        self.fields["product"].queryset = Product.objects.filter(company_id=self.request.user.profile.company, is_deleted=0)

    def clean(self):
        cd = self.cleaned_data
        print("ShippingProductUpdateForm", cd)
        raise ValidationError(
            _("첨부파일을 입력하세요: %(value)s"),
            code="invalid",
            params={"value": cd.get("product")},
        )
        # return cd
  • clean 부분에 강제로 에러를 띄워 줬더니 잘 동작하는 것을 확인했다.

그리고, form submit 할 때 Validation check 를 미리 하지 않고 view, form function 에서 걸러내고 싶다면, 템플릿에서 아래와 같은 키워드를 submit 부분에 추가해 준다. formnovalidate="formnovalidate"

<button id="update" type="submit" formnovalidate="formnovalidate" >
      

참고 사이트