해피 코딩!

Django form 정리 본문

Django

Django form 정리

지속가능한 성장을 2021. 1. 14. 13:27

Django form에 대하여 작성 단계에 있는 블로그 글 입니다. 지속적으로 글이 변경되는 점 양해 부탁드립니다.

외부의 요청을 Django serverview를 통해 실행하여 응답합니다.

이 때 ViewCBV 또는 FBV로 구현을 할 수 있습니다.

Form 의 구성

forms.Form

forms.ModelForm

Form 을 HTML을 통해 표현하는 방법

반복문을 활용한 방법

context를 통해 form 을 html에 보낸 후 작성자는 반복문을 통해 form을 표현할 시 이런 방법을 사용합니다.

<form>
{% csrf_token %}
{% for filed in form %}
    <p>{{ field.label }}</p>
      {{ field }}
{% endfor %}
<button type="submit" class="btn btn-primary btn-box">btn</button>
</form>

load bootstrap3

html에서 부트스트랩을 로드하여 한 줄로 form의 필드들을 표현 합니다.

<form>
{% csrf_token %}
    {% bootstrap_form form %}
<button type="submit" class="btn btn-primary btn-box">btn</button>
</form>

각 필드 명 별로 호출

작성자는 보다 상세한 html을 작성할 때 사용하였습니다.

<form>
{% csrf_token %}
<table class="table">
    <tr>
          <th>접수 번호</th>
          <td>{{ form.id }}</td>
          <th></th>
        <td></td>
      </tr>
    <tr>
        <th><span>*</span> 업 체</th>
        <td>{{ form.company }}</td>
        <th>프로젝트명</th>
        <td>{{ form.name }}</td>
    </tr>
</form>

form clean_fieldname()을 활용한 에러 표현

Django 내부의 form.is_valid()가 호출이 될 때의 순서는

  1. 폼이 데이터를 받으면 form.is_valid()form.full_clean()를 호출합니다.
  2. form.full_clean()은 폼 필드들과 각각의 필드 유효성을 하나하나 검사합니다.
  3. 필드에 들어온 데이터에 대해 to_python() 이용하여 문제가 있을 시 validationError 에러를 일으킨다.
  4. 폼에 clean_<field_name>() 메서드가 있을 시 해당 메서드를 실해앟ㄴ다.

각 Form Class는 필드를 가지고 있으며 이는
clean(), clean_filename()함수를 사용할 수 있게 합니다.
이 때 각 필드별로 clean 메서드가 동작한 후, 전체 form에 대한 유효성이 통과하면서 form의 유효성 검사는 마무리가 됩니다.

clean_field에 추가적으로 유효성을 검사하고 싶은 경우가 있을 것 입니다.
본인은 해당 두 가지 방법을 통해 에러를 반환하였습니다.

Two Scoops of Django 서적에서는

self.add_error('field_name', msg)

를 추천합니다.

개인적으로 추천하는 방법은 B 방법입니다. 출처가 정확히 기억나지 않으나 raise를 활용하는 것은 좋은 수단이라 기억하기 때문이며 추후, 출처에 대한 내용을 추가하도록 하겠습니다.

def clean_file(self):
    if <추가할 유효성>:
        # A. self.add_error('file', '데이터 분석에 필요한 필드가 없습니다.')
        # return 

        # B. raise forms.ValidationError("데이터 분석에 필요한 필드가 없습니다.")

    return self.cleaned_data['file']

이후 View 코드에서 유효성이 통과가 된다면 HTML 코드를 통해 에러를 표현하면 됩니다.

작성자는 이러한 방법으로 에러를 웹 페이지에 표현하였습니다.

<form method="post" enctype="multipart/form-data">
{% csrf_token %}
<div class="form-group">
    {% for field in form %}
        <p>{{ field.label }}</p>
        {% if field.errors %}
            <span style="color: red">{{ field.errors }}</span>
        {% endif %}
        {{ field }}
    {% endfor %}
</div>
<button class="btn btn-primary">btn</button>
</form>

CBV(Class Base View)

  • CBV 링크 → CBV을 사용하는 이유로는 표준이기 때문이며
  • 이에 대한 단점으로는 추상화가 심하여 커스텀이 어렵다는 것이고
  • 장점으로는 높은 생산성을 보장한다는 것이다.
  • urls에서 호출 시 view.as_view()를 작성해야 한다.
  • CBV는 상속이 가능하다는 장점으로 많이 사용된다.
  • HTTP Method에 따라 처리가 가능하다.

FBV(Fucntional Base view)

  • 쉬운 기능 생산이 가능하다.
  • 가독성이 좋다.

form의 구조

  • widgets을 통해서 폼의 형식과 class명이 포함 된 attribute를 추가한다.
  • label을 통해서 각 폼 필드의 label을 지정할 수 있다.
  • __init__메소드를 통해서 부모모델 User의 기본 설정을 (maxlength 등) 변경할 수 있다.
from django import forms
from django.contrib.auth import get_user_model

User = get_user_model()

class UserForm(forms.ModelForm):
    class Meta:
        model = User
        fields = ['username', 'email', 'password']
        widgets = {
            'username': forms.TextInput(attrs={'class': 'form-control', 'placeholder':'15자 이내로 입력 가능합니다.'}),
            'email': forms.EmailInput(attrs={'class': 'form-control'}),
            'password' : forms.PasswordInput(attrs={'class': 'form-control'}),
        }
        labels = {
            'username': '닉네임',
            'email': '이메일',
            'password': '패스워드'
        }
    # 글자수 제한
    def __init__(self, *args, **kwargs):
        super(UserForm, self).__init__( *args, **kwargs)
        self.fields['username'].widget.attrs['maxlength'] = 15

form 호출

# urls의 app_name은 view name의 중복을 피할 수 있다.
def user_create(request):
    if request.method == 'POST':
        form = UserForm(request.POST)
        if form.is_valid():
            form.save()
            return redirect('user-list')
    form = UserForm
    context = {
        'form': form
    }
    return render(request, 'system/user/add_account.html', context=context)

참고 자료

'Django' 카테고리의 다른 글

Django 유틸리티  (0) 2021.03.11
Django의 쿼리와 데이터베이스 레이어  (4) 2020.12.18
Django를 사용하게 된 이유  (0) 2020.12.15
pytest를 사용하는 이유  (0) 2020.11.23
Django 구성에 대한 이해  (0) 2020.11.23
Comments