본문 바로가기
Sundry/Python

How to Render Django Form Manually

by phpdoumi 2018. 12. 2.

[원본] How to Render Django Form Manually By Vitor Freitas - 필요해서 동의 없이 구글 번역함.


장고 양식을 수동으로 렌더링하는 방법


웹 응용 프로그램이나 웹 사이트에서 사용자 입력을 처리하는 것은 매우 일반적인 작업입니다. HTML 양식을 사용하는 표준 방법은 사용자가 일부 데이터를 입력하여 서버에 제출한 다음 서버가 HTML 형식을 사용하는 것입니다. 이제, 당신이 이미 그 인용문을 들었을 가능성이 있습니다 : "모든 입력은 악합니다!"나는 누가 먼저 그 말을 했는지는 모르지만 그것은 매우 잘 말했습니다. 사실, 응용 프로그램의 모든 입력은 잠재적 인 공격 경로인 문입니다. 그럼 모든 문을 안전하게 지켜주세요! Django는 여러분의 삶을 편하게 하고 마음의 평화를 주기 위해 매우 풍부하고 안정적이며 안전한 폼 API를 제공합니다. HTML 양식이 얼마나 간단한지간에 반드시 사용해야 합니다.


사용자 입력을 관리하면 양식 처리는 응용 프로그램의 여러 계층과 상호 작용하기 때문에 상당히 복잡한 작업입니다. 데이터베이스에 액세스해야합니다. 데이터의 무결성을 청소, 검증, 변형 및 보장합니다. 때로는 여러 모델과 상호 작용하고 사람이 읽을 수있는 오류 메시지를 전달해야 하며 마지막으로 모델을 나타내는 모든 Python 코드를 HTML 입력으로 변환해야 합니다. 경우에 따라 이러한 HTML 입력에는 JavaScript 및 CSS 코드(예 : 맞춤 날짜 선택 도구 또는 자동 완성 필드)가 포함될 수 있습니다.


문제는 Django가 서버 측 부분을 잘 처리한다는 것입니다. 그러나 그것은 클라이언트 쪽 부분을 많이 엉망으로 만들지 않습니다. Django에 의해 자동으로 생성된 HTML 양식은 완전한 기능을 하며 그대로 사용할 수 있습니다. 그러나 그것은 매우 미숙한데, 단순한 HTML, CSS 및 JavaScript가 아닙니다. 그렇게 하여 양식을 제시하여 응용 프로그램의 웹 디자인과 일치시킬 수 있는 방법을 완전히 제어할 수 있습니다. 서버 측에서는 좀 더 표준화되어 있으므로 양식 API가 제공하는 대부분의 기능이 기본적으로 작동합니다. 특수한 경우에는 사용자 정의할 수 있는 여러 가지 방법을 제공합니다.


이 튜토리얼에서는 렌더링 파트로 작업하고, 사용자 정의 CSS를 사용하여 양식을 더 예쁘게 만드는 방법을 설명합니다.


이 기사의 목차는 다음과 같습니다.


실례

렌더링 프로세스 이해

양식 필드에 개별적으로 액세스하기

양식 필드 확장

사용자 정의 HTML 속성 사용

장고 위젯 비틀기 사용하기

렌더링 부트 스트랩 4 가지 양식

양식 컴포넌트 재사용하기

결론


전체 튜토리얼에서 예제를 설명하기 위해 다음 양식 정의를 사용합니다.


forms.py


from django import forms


class ContactForm(forms.Form):

    name = forms.CharField(max_length=30)

    email = forms.EmailField(max_length=254)

    message = forms.CharField(

        max_length=2000,

        widget=forms.Textarea(),

        help_text='Write here your message!'

    )

    source = forms.CharField(       # A hidden input for internal use

        max_length=50,              # tell from which page the user sent the message

        widget=forms.HiddenInput()

    )


    def clean(self):

        cleaned_data = super(ContactForm, self).clean()

        name = cleaned_data.get('name')

        email = cleaned_data.get('email')

        message = cleaned_data.get('message')

        if not name and not email and not message:

            raise forms.ValidationError('You have to write something!')


다음 보기는 양식을 로드하고 유효성 검사 프로세스를 트리거하여 다른 상태의 양식을 가질 수 있습니다.


views.py


from django.shortcuts import render

from .forms import ContactForm


def home(request):

    if request.method == 'POST':

        form = ContactForm(request.POST)

        if form.is_valid():

            pass  # does nothing, just trigger the validation

    else:

        form = ContactForm()

    return render(request, 'home.html', {'form': form})


렌더링 프로세스 이해


많은 자습서 또는 공식 Django 문서에서 다음과 같은 양식 템플릿을 보는 것이 일반적입니다.


<form method="post" novalidate>

  {% csrf_token %}

  {{ form }}

  <button type="submit">Submit</button>

</form>


참고 : 양식의 novalidate 속성에 대해 궁금할 것입니다. 실제 사례에서는 아마 그것을 사용하고 싶지 않을 것입니다. 브라우저가 서버에 제출하기 전에 데이터를 "검증"하지 못하게 합니다. 탐색할 예제에서와 같이 "필수"필드 오류 만 있으면 서버 측 실제 데이터 유효성 검사를 보고 양식 렌더링의 오류 상태를 탐색할 수 없습니다.


마술 같아, 그렇지? 이 특정 양식에는 50 개의 필드가 포함될 수 있으며 간단한 명령 {{ form }}을 사용하면 템플릿에 모두 표시됩니다.


템플릿에 {{ form }}을 쓸 때 실제로 BaseForm 클래스에서 __str__ 메소드에 액세스합니다. __str__ 메서드는 객체의 문자열 표현을 제공하는 데 사용됩니다. 소스 코드를 살펴보면 as_table() 메서드를 반환한다는 것을 알 수 있습니다. 그래서, 기본적으로 {{ form }}과 {{ form.as_table }}은 같은 것입니다.


양식 API는 자동으로 HTML 양식을 렌더링하는 세 가지 메소드를 제공합니다.


as_table()

as_ul()

as_p()


그들은 모두 같은 방식으로 더 많거나 적게 작동합니다. 차이점은 입력을 래핑하는 HTML 코드입니다.


아래는 이전 코드 스니펫의 결과입니다.

Contact Form


그러나 {{ form }}과 {{ form.as_table }}이 같은 경우 결과는 분명히 테이블처럼 보이지 않습니다. 맞습니까? 왜냐하면 as_table()과 as_ul()은 <table> 태그와 <ul> 태그를 생성하지 않기 때문에 직접 추가해야합니다.


따라서 올바른 방법은 다음과 같습니다.


<form method="post" novalidate>

  {% csrf_token %}

  <table border="1">

    {{ form }}

  </table>

  <button type="submit">Submit</button>

</form>


Contact Form

이제 그 말이 맞습니까? <table> 태그가 없으면 브라우저는 HTML 출력을 렌더링하는 방법을 모르기 때문에 아직 CSS가 없기 때문에 보이는 모든 필드를 줄에 표시합니다.


모든 as_*() 메소드에서 사용하는 BaseForm에 정의된 _html_output private 메소드를 보면 76 줄의 코드로 구성된 매우 복잡한 메소드이고 많은 일을 합니다. 이 방법은 잘 테스트되었으며 양식 API의 핵심 부분인데, 이는 작동 원리가 되는 기본 메커니즘입니다. 자신만의 폼 렌더링 논리로 작업할 때 파이썬 코드를 작성하지 않아도 됩니다. Django 템플릿 엔진을 사용하면 코드를 더 깨끗하고 쉽게 유지할 수 있으므로 훨씬 더 좋습니다.


_html_output 메소드는 생성되는 코드의 종류, 실제로 수행중인 코드를 분석할 때 사용할 수 있으므로 템플릿 엔진을 사용하여 이를 모방할 수 있으므로 여기에서 _html_output 메소드를 언급합니다. 소스 코드를 읽고 그것에 익숙해지는 것도 좋은 연습입니다. 그것은 훌륭한 정보 원입니다. Django의 문서가 매우 상세하고 광범위하지만 여기 저기에 숨겨진 비트가 항상 있습니다. 또한 스마트 코더가 특정 문제를 해결하는 방법을 예제로 볼 기회를 얻습니다. 결국 많은 사람들이 기여한 성숙한 개발 프로세스를 갖춘 오픈 소스 프로젝트이기 때문에 최적의 코드를 읽을 가능성이 있습니다.


어쨌든, 여기 요컨대, _html_output의 기능은 다음과 같습니다.


특정 필드 (비 필드 오류) 및 숨겨진 필드의 오류에 첨부되지 않은 오류를 집계하십시오.

양식 위에 비 필드 오류 및 숨겨진 필드 오류를 배치하십시오.

모든 양식 필드를 반복합니다.

양식 필드를 하나씩 렌더링하십시오.

label 태그의 필드명을 렌더링합니다.

필드 오류가 있으면 먼저 오류가 있는 HTML 목록을 렌더링하십시오.

필드의 HTML 입력을 렌더링합니다.

움말 텍스트가 있으면 필드 뒤에 렌더링하십시오.


다음은 폼의 두 번째 상태가 모든 유효성 검사 오류를 트리거하는 모습입니다.


Contact Form With Errors

이제 그 일이 무엇인지 알았으므로 템플릿 엔진을 사용하여 동일한 동작을 모방하려고 할 수 있습니다. 이렇게 하면 렌더링 프로세스를 훨씬 더 강력하게 제어할 수 있습니다.


<form method="post" novalidate>

  {% csrf_token %}


  {{ form.non_field_errors }}


  {% for hidden_field in form.hidden_fields %}

    {{ hidden_field.errors }}

    {{ hidden_field }}

  {% endfor %}


  <table border="1">

    {% for field in form.visible_fields %}

      <tr>

        <th>{{ field.label_tag }}</th>

        <td>

          {{ field.errors }}

          {{ field }}

          {{ field.help_text }}

        </td>

      </tr>

    {% endfor %}

  </table>


  <button type="submit">Submit</button>

</form>


결과는 약간 다르지만 모든 요소가 있음을 알 수 있습니다. 것은, {{form}}을 사용하는 HTML의 자동 생성은 파이썬 언어를 이용하기 때문에 문자열 연결, 목록 결합 (필드 오류가 아닌 + 필드 오류 숨김), 그리고 이런 종류의 것들을 사용할 수 있습니다 . 템플릿 엔진은 더 제한적이고 제한적이지만 문제는 아닙니다. 장고 템플릿 엔진은 템플릿에서 많은 코드 로직을 할 수 없기 때문에 좋아합니다.

Contact Form With Errors


유일한 진짜 문제는 소스 필드를 참조하는 상단에 임의의 "This field is required"입니다. 그러나 우리는 그것을 향상시킬 수 있습니다. 폼 렌더링을 계속 확장시켜 더 많은 제어권을 얻을 수 있습니다.


<form method="post" novalidate>

  {% csrf_token %}


  {% if form.non_field_errors %}

    <ul>

      {% for error in form.non_field_errors %}

        <li>{{ error }}</li>

      {% endfor %}

    </ul>

  {% endif %}


  {% for hidden_field in form.hidden_fields %}

    {% if hidden_field.errors %}

      <ul>

        {% for error in hidden_field.errors %}

          <li>(Hidden field {{ hidden_field.name }}) {{ error }}</li>

        {% endfor %}

      </ul>

    {% endif %}

    {{ hidden_field }}

  {% endfor %}


  <table border="1">

    {% for field in form.visible_fields %}

      <tr>

        <th>{{ field.label_tag }}</th>

        <td>

          {% if field.errors %}

            <ul>

              {% for error in field.errors %}

                <li>{{ error }}</li>

              {% endfor %}

            </ul>

          {% endif %}

          {{ field }}

          {% if field.help_text %}

            <br />{{ field.help_text }}

          {% endif %}

        </td>

      </tr>

    {% endfor %}

  </table>


  <button type="submit">Submit</button>

</form>


Contact Form With Errors


훨씬 더 가까이?


{{ form }} 마크 업을 "확장"하는 방법을 알았으니 이제는 더 예쁘게 보이도록 노력합시다. 아마도 부트 스트랩 4 라이브러리를 사용했을 것입니다.



양식 필드에 개별적으로 액세스하기

양식 필드를 노출하기 위해 for 루프가 필요하지 않습니다. 그러나 요소 배치에 대한 특별한 요구 사항이 없는 경우 이를 수행하는 것이 매우 편리한 방법입니다.


양식 필드를 하나씩 참조할 수 있는 방법은 다음과 같습니다.


<form method="post" novalidate>

  {% csrf_token %}


  {{ form.non_field_errors }}


  {{ form.source.errors }}

  {{ form.source }}


  <table border="1">


      <tr>

        <th>{{ form.name.label_tag }}</th>

        <td>

          {{ form.name.errors }}

          {{ form.name }}

        </td>

      </tr>


      <tr>

        <th>{{ form.email.label_tag }}</th>

        <td>

          {{ form.email.errors }}

          {{ form.email }}

        </td>

      </tr>


      <tr>

        <th>{{ form.message.label_tag }}</th>

        <td>

          {{ form.message.errors }}

          {{ form.message }}

          <br />

          {{ form.message.help_text }}

        </td>

      </tr>


  </table>


  <button type="submit">Submit</button>

</form>


그것은 매우 건조한 해결책이 아닙니다. 그러나 그것을 하는 방법을 아는 것이 좋다. 때로는 HTML에서 필드를 직접 배치해야 하는 매우 구체적인 사용 사례가 있을 수 있습니다.



양식 필드 확장


우리는 여전히 더 깊이 파고 {{ field }} 마크 업을 확장할 수 있습니다 (또는 개별적으로 수행하는 경우 예를 들어 {{ form.name }} 또는 {{ form.email }} 필드가 될 수 있습니다). 그러나 이제 우리는 위젯에 대해 이야기하기 때문에 좀 더 복잡해집니다. 예를 들어 전자 메일 필드는 <input type = "email"> 태그로 변환되는 반면 name 필드는 <input type = "text"> 태그로 변환되며 더 문제가 되는 메시지 필드는 <textarea></textarea> 태그가 있습니다.


이 시점에서 Django는 작은 HTML 템플릿을 사용하여 필드의 출력 HTML을 생성합니다.


그럼 장고가 어떻게하는지 봅시다. 위젯 폴더에서 text.html 또는 email.html 템플릿을 열면 input.html 템플릿 파일만 포함됩니다.


{% include "django/forms/widgets/input.html" %}


이것은 input.html 템플릿이 아마도 가장 일반적인 템플릿일 것임을 암시합니다. 렌더링의 세부 사항이 내부에 있을 수 있습니다. 자, 살펴 보겠습니다.


<input type="{{ widget.type }}"

       name="{{ widget.name }}"

       {% if widget.value != None %} value="{{ widget.value|stringformat:'s' }}"{% endif %}

       {% include "django/forms/widgets/attrs.html" %} />


기본적으로이 작은 템플리트는 입력 유형을 설정하며, 요청 오브젝트의 데이터에 액세스하는 데 사용되는 이름입니다. 예를 들어 이름이 "message"인 입력은 서버에 게시된 경우 request.POST['message']를 통해 액세스할 수 있습니다.


여전히 input.html 템플릿 스니펫에서 필드의 현재 값을 설정하거나 데이터가 없는 경우 빈 상태로 둡니다. 그것은 템플릿의 중요한 부분입니다. 그 이유는 그것이 제출되고 성공적으로 처리되지 않은 양식의 상태를 유지하기 때문입니다 (양식이 유효하지 않습니다).


마지막으로, maxlength, required, placeholder, style 또는 기타 HTML 속성과 같은 속성을 설정하는 attrs.html 템플리트가 포함됩니다. 양식 정의에서 사용자 정의가 가능합니다.


attrs.html에 대해 궁금하신 분은 다음과 같습니다.


{% for name, value in widget.attrs.items %}

  {% if value is not False %}

    {{ name }}{% if value is not True %}="{{ value|stringformat:'s' }}"{% endif %}

  {% endif %}

{% endfor %}


이제 직접 입력을 만들고 싶다면 다음과 같이 할 수 있습니다 (간단히 하기 위해 이름 필드).


<input type="text"

       name="name"

       id="id_name"

       {% if form.name.value != None %}value="{{ form.name.value|stringformat:'s' }}"{% endif %}

       maxlength="30"

       required>


또는 조금 더 :


<input type="text"

       name="{{ form.name.name }}"

       id="{{ form.name.id_for_label }}"

       {% if form.name.value != None %}value="{{ form.name.value|stringformat:'s' }}"{% endif %}

       maxlength="{{ form.name.field.max_length }}"

       {% if form.name.field.required %}required{% endif %}>


이미 양식으로 작업하는 것이 최선의 방법이 아니라는 것을 이미 알고 있을 것입니다. 그리고 어쩌면 우리는 때때로 특정 속성을 {{ form.name.<something> }}으로 참조하고 다른 상황에서는 {{ form.name.field.<something> }}을 사용하는 이유를 스스로에게 묻고 있습니다.


지금 당장은 자세하게 설명하고 싶지는 않지만 기본적으로 form.name은 BoundField (field + data) 인스턴스이고 form.name.field는 필드 정의입니다. 이 필드 정의는 forms.CharField라고 합니다. 그래서 바운드 필드 인스턴스에서 일부 값을 사용할 수 있으며 다른 필드는 char 필드 정의에 있습니다.


양식 정의에서 양식의 __iter__은 BoundField 인스턴스 목록을 반환하며, 비슷한 방법으로 visible_fields() 및 hidden_fields() 메서드는 BoundField 인스턴스도 반환합니다. 이제 form.fields에 액세스하면 CharField, EmailField 및 기타 모든 필드 정의 목록을 참조합니다. 이 정보가 너무 많은 정보라면 지금 당장 괜찮습니다. 지금.


사용자 정의 HTML 속성 사용

클래스, 스타일 또는 자리 표시자 같은 추가 HTML 특성만 추가하려는 경우가 있습니다. 앞의 예에서와 같이 입력 필드를 확장할 필요는 없습니다. 양식 정의에서 직접할 수 있습니다.


forms.py


class ColorfulContactForm(forms.Form):

    name = forms.CharField(

        max_length=30,

        widget=forms.TextInput(

            attrs={

                'style': 'border-color: blue;',

                'placeholder': 'Write your name here'

            }

        )

    )

    email = forms.EmailField(

        max_length=254,

        widget=forms.EmailInput(attrs={'style': 'border-color: green;'})

    )

    message = forms.CharField(

        max_length=2000,

        widget=forms.Textarea(attrs={'style': 'border-color: orange;'}),

        help_text='Write here your message!'

    )

Colorful Contact Form

다음으로, 우리는 당신의 삶을 편하게 할 수 있는 써드 파티 라이브러리를 탐험할 것입니다.


장고 위젯 비틀기(Django Widget Tweaks) 사용하기

양식 정의에서 사용자 정의 HTML 속성을 제어 할 수는 있지만 템플릿에서 직접 설정할 수 있으면 훨씬 더 좋습니다. 결국 HTML 속성은 입력 내용을 나타냅니다.


django-widget-tweaks 라이브러리는 작업에 적합한 도구입니다. 양식 기본값을 유지하고 필요한 것을 추가할 수 있습니다. 특별히 ModelForms로 작업할 때 매우 편리합니다. 간단한 작업을 수행하기 위해 작성해야 하는 코드의 양을 줄여줍니다.


django-widget-tweaks에 대한 자세한 내용은 다루지 않을 것입니다.


다음은 빠른 시작 안내서입니다.


먼저 pip를 사용하여 설치하십시오.


pip install django-widget-tweaks


INSTALLED_APPS에 추가하십시오.


INSTALLED_APPS = [

    'django.contrib.auth',

    'django.contrib.contenttypes',

    'django.contrib.sessions',

    'django.contrib.messages',

    'django.contrib.staticfiles',


    'widget_tweaks',

]


템플릿에 로드 :


{% load widget_tweaks %}

<!DOCTYPE html>

<html>

<head>

  <meta charset="utf-8">

  <title>Simple is Better Than Complex</title>

</head>

<body>

  ...

</body>


그리고 우리는 그것을 사용할 준비가 되었습니다! 기본적으로 {% render_field %} 템플릿 태그를 사용합니다. 다음 예제에서 원시 HTML과 마찬가지로 단순히 속성을 넣을 수 있습니다.


<form method="post" novalidate>

  {% csrf_token %}


  {{ form.non_field_errors }}


  {% for hidden_field in form.hidden_fields %}

    {{ hidden_field.errors }}

    {{ hidden_field }}

  {% endfor %}


  <table border="1">

    {% for field in form.visible_fields %}

      <tr>

        <th>{{ field.label_tag }}</th>

        <td>

          {{ field.errors }}

          {% render_field field style="border: 2px dashed red;" placeholder=field.name %}

          {{ field.help_text }}

        </td>

      </tr>

    {% endfor %}

  </table>


  <button type="submit">Submit</button>

</form>

Django Widget Tweaks Form

특히 CSS 클래스를 추가해야 하는 경우에 매우 편리합니다. 부트 스트랩 4 양식 서식 파일을 사용하는 경우입니다.


렌더링 부트 스트랩 4 가지 양식


기본적으로 부트 스트랩 4 라이브러리를 사용하기 위해 템플릿에 CDN 링크가 포함되어 있습니다.


<head>

  <meta charset="utf-8">

  <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">

  <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-beta/css/bootstrap.min.css" integrity="sha384-/Y6pD6FV/Vv2HJnA6t+vslU6fwYXjCFtcEpHbNJ0lyAFsXTsjBbfaDjzALeQsN6M" crossorigin="anonymous">

  <title>Simple is Better Than Complex</title>

</head>


부트 스트랩 4 구현의 특수성에 대해 살펴 보지 않으므로 이 기사의 일부는 더 중요한 시점이 될 것입니다. 그들의 문서는 훌륭하고 예제가 풍부합니다. 익숙하지 않은 경우 Documentation/Components/Forms 섹션으로 이동하여 자세한 정보를 얻을 수 있습니다.


먼저 입력의 표현에 중점을 두자. 나중에 오류 부분을 보게 될 것이다. Bootstrap 4 태그를 사용하여 동일한 양식을 표현하는 방법은 다음과 같습니다.


<form method="post" novalidate>

  {% csrf_token %}


  {% for hidden_field in form.hidden_fields %}

    {{ hidden_field }}

  {% endfor %}


  {% for field in form.visible_fields %}

    <div class="form-group">

      {{ field.label_tag }}

      {{ field }}

      {% if field.help_text %}

        <small class="form-text text-muted">{{ field.help_text }}</small>

      {% endif %}

    </div>

  {% endfor %}


  <button type="submit" class="btn btn-primary">Submit</button>

</form>

Bootstrap 4 Contact Form

입력 필드가 깨져 보입니다. 부트 스트랩 4 양식은 HTML 입력에서 CSS 클래스 양식 제어를 기대하기 때문입니다. 이 기사의 마지막 섹션에서 배운 내용으로 해결해 보겠습니다.


{% load widget_tweaks %}


<form method="post" novalidate>

  {% csrf_token %}


  {% for hidden_field in form.hidden_fields %}

    {{ hidden_field }}

  {% endfor %}


  {% for field in form.visible_fields %}

    <div class="form-group">

      {{ field.label_tag }}

      {% render_field field class="form-control" %}

      {% if field.help_text %}

        <small class="form-text text-muted">{{ field.help_text }}</small>

      {% endif %}

    </div>

  {% endfor %}


  <button type="submit" class="btn btn-primary">Submit</button>

</form>

Bootstrap 4 Contact Form

훨씬 낫다. 이제 검증 및 오류 상황을 살펴 보겠습니다. 비 필드 오류에 대한 경고 구성 요소를 사용하고, 부트 스트랩 4에서 제공하는 올바른 CSS 클래스로 재생할 필드에 대해서만 설명할 것입니다.


{% load widget_tweaks %}


<form method="post" novalidate>

  {% csrf_token %}


  {% for hidden_field in form.hidden_fields %}

    {{ hidden_field }}

  {% endfor %}


  {% if form.non_field_errors %}

    <div class="alert alert-danger" role="alert">

      {% for error in form.non_field_errors %}

        {{ error }}

      {% endfor %}

    </div>

  {% endif %}


  {% for field in form.visible_fields %}

    <div class="form-group">

      {{ field.label_tag }}


      {% if form.is_bound %}

        {% if field.errors %}

          {% render_field field class="form-control is-invalid" %}

          {% for error in field.errors %}

            <div class="invalid-feedback">

              {{ error }}

            </div>

          {% endfor %}

        {% else %}

          {% render_field field class="form-control is-valid" %}

        {% endif %}

      {% else %}

        {% render_field field class="form-control" %}

      {% endif %}


      {% if field.help_text %}

        <small class="form-text text-muted">{{ field.help_text }}</small>

      {% endif %}

    </div>

  {% endfor %}


  <button type="submit" class="btn btn-primary">Submit</button>

</form>


결과는 다음과 같습니다.

Bootstrap 4 Contact Form

유효성 검사를 통과 한 필드가 초록색으로 표시되어 매우 시원합니다.

Bootstrap 4 Contact Form

무슨 일이 일어나고 있는지 자세히 살펴 보겠습니다. 코드 스니펫을 향상시킬 수 있지만 템플릿 렌더링 논리에 대해 더 잘 이해할 수 있도록 이 방법을 사용하는 것이 좋습니다.


먼저 form.is_bound 메서드를 호출합니다. 양식에 데이터가 있는지 여부를 알려줍니다. form = ContactForm() 양식을 처음 초기화할 때 form.is_bound() 메서드는 False를 반환합니다. 제출 후 form.is_bound()는 True를 리턴합니다. 따라서 검증 과정이 이미 진행되었는지 여부를 확인하기 위해 함께 작업 할 수 있습니다.


그런 다음 유효성 검사가 이미 수행된 경우 사례에 따라 CSS 클래스 .is-invalid 및 .is-valid로 필드를 표시하기만 하면 됩니다. 양식 구성 요소를 빨간색 또는 녹색으로 그릴 책임이 있습니다.


양식 컴포넌트 재사용하기

지금 할 수 있는 한 가지 방법은 기존 코드를 외부 파일에 복사하고 코드 스니펫을 다른 형식으로 재사용하는 것입니다.


includes/bs4_form.html


{% load widget_tweaks %}


{% for hidden_field in form.hidden_fields %}

  {{ hidden_field }}

{% endfor %}


{% if form.non_field_errors %}

  <div class="alert alert-danger" role="alert">

    {% for error in form.non_field_errors %}

      {{ error }}

    {% endfor %}

  </div>

{% endif %}


{% for field in form.visible_fields %}

  <div class="form-group">

    {{ field.label_tag }}


    {% if form.is_bound %}

      {% if field.errors %}

        {% render_field field class="form-control is-invalid" %}

        {% for error in field.errors %}

          <div class="invalid-feedback">

            {{ error }}

          </div>

        {% endfor %}

      {% else %}

        {% render_field field class="form-control is-valid" %}

      {% endif %}

    {% else %}

      {% render_field field class="form-control" %}

    {% endif %}


    {% if field.help_text %}

      <small class="form-text text-muted">{{ field.help_text }}</small>

    {% endif %}

  </div>

{% endfor %}


이제 폼 정의는 다음과 같이 간단해질 수 있습니다.


<form method="post" novalidate>

  {% csrf_token %}

  {% include 'includes/bs4_form.html' with form=form %}

  <button type="submit" class="btn btn-primary">Submit</button>

</form>


예를 들어 위 코드 스니펫을 사용하여 django.contrib.auth 모듈 안에 있는 내장 양식인 UserCreationForm을 처리합니다. 아래의 결과 :


Bootstrap 4 Contact Form

결론

이 기사는 내가 예상했던 것보다 커졌습니다. 먼저 양식 렌더링에 대한 간단한 자습서를 작성해 보았습니다. 그런 다음 장고 - 위젯 조정 방법을 설명하는 데 필요한 시점별 자습서가 이미 있음을 기억했습니다. 그래서, 대신에 세부 사항을 자세히 들여다보고 양식 API의 메커니즘을 탐구하기로 결정했습니다.


복잡한 양식에 초점을 맞춘 후속 기사를 작성하고, 모두 함께 체크 상자를 선택하고, 필드를 선택하고, 날짜 선택기를 만들고, 사용자 정의 위젯을 개발하는 방법에 대해 알아볼 것입니다.


새로운 것을 배웠거나 이 기사를 읽으면서 즐거웠기를 바랍니다. 질문이 있거나 주제에 대해 더 상의하고 싶다면 아래에 의견을 남겨주세요!


평소처럼 GitHub에서 소스 코드와 모든 예제를 찾을 수 있습니다.











'Sundry > Python' 카테고리의 다른 글

json encode decode 예제  (0) 2018.12.14
django-widget-tweaks  (0) 2018.12.03
월 - 월 계산하기  (0) 2018.11.12
bdist_wheel error  (0) 2018.11.12
Django에서 WhiteNoise 사용하기  (0) 2018.11.09