본문 바로가기

TIl

Form

Django Form

HTML Form

지금까지 사용자로부터 데이터를 받기위해 활용한 방법

But 비정상적 혹은 악의적인 요청을 필터링 할 수 없음

⇒ 유효한 데이터인지에 대한 확인이 필요

유효성 검사 :

  • 수집한 데이터가 정확하고 유효한지 확인하는 과정
  • 구현하기엔 많은 것을 고려해야 됨
  • ⇒ Django가 제공하는 Form을 쓰겠다.

Django Form

사용자 입력 데이터를 수집하고, 처리 및 유효성 검사를 수행하기 위한 도구

⇒ 유효성 검사를 단순화하고 자동화 할 수 있는 기능을 제공

# apps_name/forms.py
from Django import forms

class ArticleForm(forms,Form):
	title = forms.CharField(max_length=10)
	content = forms.CharField()

form 태그에서는 TextField가 없음

⇒ 그래서 CharField에서 씀

⇒ max_length를 필수가 아님 == model과의 차이점

  <form action="{% url "articles:create" %}" method="POST">
    {% csrf_token %}
    <div>
      <label for="title">Title: </label>
      <input type="text" name="title" id="title">
    </div>
    <div>
      <label for="content">Content: </label>
      <textarea name="content" id="content"></textarea>
    </div>
    <input type="submit">
  </form>
<!-- 바꾸기 -->
  <form action="{% url "articles:create" %}" method="POST">
    {% csrf_token %}
    {{form}}
    <input type="submit">
  </form>

Form rendering options

HTML 태그로 label, input 쌍을 감싸는 옵션

form.as_div , as_table ,as_p ,as_ul

Widgets

HTML ‘input’ element의 표현을 담당

Widget은 단순히 input 요소의 속성 및 출력되는 부분을 변경하는 것

[forms.py](<http://forms.py>) 에서 설정 하는 것

# froms.py
content = forms.CharField(widget=forms.Textarea)

Django ModelForm

-Form : 사용자 입력 데이터를 DB에 저장하지 않을 때 ex) 로그인

-ModelForm : 저장해야 할 때 ex) 회원가입, 게시글 작성

ModelForm

Model과 연결된 Form을 자동으로 생성해주는 기능을 제공

Form + Model

# articles/forms.py
from django import forms
from .models import Articles

class ArticleForm(forms.ModelForm):
    class Meta:
        model = Article
        fields = '__all__'

필수요소 2개

  1. model : 어떤 모델과 연동할거냐
  2. fields : 그 모델에서 어떤 필드를 쓸것이냐

Meta Class

ModelForm의 정보를 작성하는 곳

fields 및 exclude 속성

field를 사용해서 모델에서 그것만 포함시키거나 OR exclude 속성을 사용하여 포함하지 않거나

ModelForm을 적용한 create 로직

# articles/view.py
# 기존, 유효성 검사가 안이루어짐
def create(request):
    title = request.POST.get('title')
    content = request.POST.get('content')
    article = Article(title=title, content=content)
    article.save()
    return redirect('articles:detail', article.pk)  
    
# 변경
def create(request):
    form = ArticleForm(request.POST)
    if form.is_valid():
        article = form.save()
        return redirect('articles:detail', article.pk)
    # 유효성 검사를 통과 못했던 폼을 그대로 다시 보여줌 + 에러 메세지
    context = {
        'form' : form,
    }
    return render(request, 'articles/new.html', context)

공백 데이터가 유효하지 않은 이유와 에러메시지가 출력되는 과정

  • 별도로 명시하지 않았지만 모델 필드에는 기본적으로 빈 값은 허용하지 않는 제약조건이 설정되어있음
  • 빈 값은 is_valid()에 의해 False로 평가되고 form 객체에는 그에 맞는 에러 메시지가 포함되어 다음 코드로 진행됨

update

# articles/views.py
def update(request, pk):
    article = Article.objects.get(pk=pk)
    form = ArticleForm(request.POST, instance=article) # instance로 생성과 업데이트 구분
    if form.is_valid():
        form.save()
        return redirect('articles:detail', article.pk)
    context = {
        'form': form,
        'article':article # 이거 누락하기 쉬움, 누락하면 유효성검사 실패 시 에러페이지로 감
    }
    return render(request, 'articles/edit.html', context)

Handling HTTP requests

view 함수 구조 변화

new & create view 함수간 공통점과 차이점

공통점 : 데이터 생성을 구현하기 위함

차이점 : new는 GET method 요청만을, create는 POST method 요청만을 처리

def new(request):
    form = ArticleForm()
    context = {
        'form': form
    }
    return render(request, 'articles/new.html', context)

def create(request):
    form = ArticleForm(request.POST)
    if form.is_valid():
        article = form.save()
        return redirect('articles:detail', article.pk)    
    # 유효성 검사를 통과 못했던 폼을 그대로 다시 보여줌 + 에러메세지
    context = {
        'form' : form,
    }
    return render(request, 'articles/new.html', context)

method 차이만 구분해서 합친 것

def create(request):
    form = ArticleForm(request.POST)
    if request.method == 'POST': # POST로 받았네
        if form.is_valid():
            article = form.save()
            return redirect('articles:detail', article.pk)
    else: # GET을 받았네
        form = ArticleForm()
    # context 가 이구조로 있어야 유효성 검사 실패했을 때 에러메시지가 저장됨
    context = {
        'form': form
    }
    return render(request, 'articles/new.html', context)

Edit 과 Update

def edit(request, pk):
    article = Article.objects.get(pk=pk)
    form = ArticleForm(instance=article)
    context = {
        'article': article,
        'form' : form,
    }
    return render(request, 'articles/edit.html', context)

def update(request, pk):
    article = Article.objects.get(pk=pk)
    form = ArticleForm(request.POST, instance=article)
    if form.is_valid():
        form.save()
        return redirect('articles:detail', article.pk)
    context = {
        'form': form,
        'article':article # 이거 누락하기 쉬움
    }
    return render(request, 'articles/edit.html', context)

작성 순서

else 부터 채워야지 데이터 흐름을 이해했다고 볼 수 있다.

def create(request):
    if request.method == 'POST':
        pass
    else:
        pass

Widget 응용

# articles/formcs.py

class ArticleForm(forms.ModelForm):
    title = forms.CharField(
        lable='제목',
        widget=forms.TextInput(
            attrs={
                'class': 'my-title'
                'placeholder': 'Enter the title',
                'maxlength':10,
            }
        ),
    )
    content = forms.CharField(
        label='내용',
        widget=forms.Textarea(
            attrs={
                'class':'my-content',
                'placeholder':'Enter the content',
                'rows':5,
                'cols':50,
            }
        ),
        error_messages={'required':'내용을 입력해주세요.'}
    )
    class Meta:
        model = Article
        fields = '__all__'

응용 2번째

class TodoForm(forms.ModelForm):
    # is_completed = forms.BooleanField(
    #     widget=forms.HiddenInput(),
    #     required=False
    # )
    class Meta:
        model = Todo
        fields = '__all__'
        widgets = {'is_completed':forms.HiddenInput()}

'TIl' 카테고리의 다른 글

Authentication  (0) 2024.04.16
Statics  (1) 2024.04.16
ORM with View  (0) 2024.04.01
ORM  (0) 2024.04.01
MST, Dijkstra  (0) 2024.04.01