- 사용자가 입력한 데이터가 우리가 원하는 데이터 형식이 맞는지에 대한 유효성 검증이 필요하다.
- Django Form은 과정에서 과중한 작업과 반복 코드를 줄여줌으로써 훨씬 수비게 유효성 검증을 진행할 수 있도록 만들어 준다.
- Django는 Form과 관련한 유효성 검사를 단순화하고 자동화 할 수 있는 기능을 제공하여 , 개발자가 직접 작성하는 코드보다 더 안전하고 빠르게 수행하는 코드를 작성 할 수 있다.
- forms.py 생성후 ArticleForm class선언
from django import forms
class ArticleForm(forms.Form):
title = forms.CharField(max_length=30)
content = forms.CharField()
- view 업데이트
from django.shortcuts import render, redirect
from .models import Article
from .forms import ArticleForm
# Create your views here.
def index(request):
articles = Article.objects.all()
context = {'articles': articles}
return render(request, 'articles/index.html', context)
def detail(request, pk):
article = Article.objects.get(pk=pk)
context = {'article': article}
return render(request, 'articles/detail.html', context)
def create(request):
if request.method == 'POST':
title = request.POST.get('title')
content = request.POST.get('content')
article = Article(title=title, content=content)
article.save()
return redirect('articles:detail', pk=article.pk)
else:
form = ArticleForm()
context = {'form' : form}
return render(request, 'articles/create.html', context)
def delete(request, pk):
article = Article.objects.get(pk=pk)
article.delete()
return redirect('articles:index')
def update(request, pk):
article = Article.objects.get(pk=pk)
if request.method == 'POST':
article.title = request.POST.get('title')
article.content = request.POST.get('content')
article.save()
return redirect('articles:detail', pk=article.pk)
else:
context = {'article': article}
return render(request, 'articles/update.html', context)
- create.html 변경
{% extends 'base.html' %}
{% block content %}
<h1>글작성</h1>
<hr>
<form action="{% url 'articles:create' %}" method="POST">
{% csrf_token %}
{{form.as_p}}
<input type="submit">
</form>
{% endblock content %}
-
From rendering option
- label & input 쌍에 대한 3가지 출력 옵션
- as_p()
- p태그로 감싸져서 렌더링
- as_ul()
- li 태그로 감싸져서 렌더링
- ul 태그는 직접 작성해야한다.
- as_table()
- tr 태그로 감싸져서 렌더링
-
HTML input 요소
- Form fields
- 입력에 대한 유효성 검사 로직을 처리한다.
- 템플릿에서 직접 사용된다.
- Widgets
- 웹 페이지의 HTML input 요소 렌더링을 담당
- input 보여지는 부분을 변경한다.
- Widgets은 form fields에 할당된다.
- 웹 페이지의 HTML input 요소 렌더링을 담당
- Form fields
-
웹 페이지의 HTML input element 렌더링을 담당
- 유효성 검증과는 관계 X
- input 보여지는 부분을 변경한다.
from django import forms class ArticleForm(forms.Form): title = forms.CharField(max_length=30) content = forms.CharField(widget=forms.Textarea)
- Model을 통해 Form Class를 만들 수 있는 helper class
- ModelForm은 Form과 똑같은 방식으로 View 함수에서 사용
- ModelForm 선언
- forms 라이브러리에서 파생된 ModelForm 클래스를 상속받음
- 클래스 안에 Meta 클래스 선언
- exclude 속성을 사용하여 모델에서 포함하지 않을 필드를 지정할 있다.
from django import forms
from .models import Article
# class ArticleForm(forms.Form):
# title = forms.CharField(max_length=30)
# content = forms.CharField(widget=forms.Textarea)
class ArticleForm(forms.ModelForm):
class Meta:
model = Article
fields = '__all__'
# exclude = ('title',)
# fields랑 같이 써도 되지만 주로 따로 사용한다.
-
is_valid() 유효성 검사
- views
def create(request): if request.method == 'POST': form = ArticleForm(request.POST) if form.is_valid(): article = form.save() return redirect('articles:detail', article.pk) # title = request.POST.get('title') # content = request.POST.get('content') # article = Article(title=title, content=content) # article.save() return redirect('articles:create', pk=article.pk) else: form = ArticleForm() context = {'form' : form} return render(request, 'articles/create.html', context)
-
save() method
- form 인스턴스 바인딩 된 데이터를 통해 데이터베이스 객체를 만들고 저장
- ModelForm의 하위 클래스는 키워드 인자 instance 여부를 통해 생성할지 수정할 지를 정한다.
- 정리해보면
-
create 수정하기
def create(request):
if request.method == 'POST':
form = ArticleForm(request.POST)
if form.is_valid():
article = form.save()
return redirect('articles:detail', article.pk)
else:
form = ArticleForm()
context = {'form' : form}
return render(request, 'articles/create.html', context)
- update 수정하기
def update(request, pk):
article = Article.objects.get(pk=pk)
if request.method == 'POST':
form = ArticleForm(request.POST, instance=article)
if form.is_valid():
form.save()
return redirect('articles:detail', article.pk)
else:
form = ArticleForm(instance=article)
context = {'form': form, 'article': article}
return render(request, 'articles/update.html', context)
{% extends 'base.html' %}
{% block content %}
<h1>UPDATE</h1>
<hr>
<form action="{% url 'articles:update' article.pk %}" method="POST">
{% csrf_token %}
{{ form.as_p }}
<input type="submit">
</form>
<hr>
<a href="{% url 'articles:detail' article.pk %}">[BACK]</a>
{% endblock content %}
- 위젯을 작성하는 2가지 방법
class ArticleForm(form.ModelForm):
class Meta:
model = Article
fields = '__all__'
widgets = {
'title': forms.TextInput(attrs={
'class':'title',
'placeholder':'Enter the title',
'maxlength':10,
}
)
}
class ArticleForm(form.ModelForm):
title = forms.CharField(
label='제목',
widget=forms.TextInput(
attrs={
'class': 'my-title',
'placeholder':'Enter the title',
}
),
)
class Meta:
model = Article
fields = '__all__'
-
파일 자체가 고정되어 있고, 서비스 중에도 추가되거나 변경되지 않고 고정되어 있는 상황
-
Media File
- 미디어 파일
- 사용자가 웹에서 업로드하는 정적 파일
client → http request → server
client ← http response ← server
-
base.html
{% load static %}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha1/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-GLhlTQ8iRABdZLl6O3oVMWSktQOp6b7In1Zl3/Jr59b6EGGoI1aFkw7cmDA6j6gD" crossorigin="anonymous">
<link rel="stylesheet" href=" {% static 'base.css' %} ">
<title>CRUD PJT</title>
</head>
<body>
{% block content %}
{% endblock content %}
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha1/dist/js/bootstrap.bundle.min.js" integrity="sha384-w76AqPfDkMBDXo30jS1Sgez6pr3x5MlQ1ZAGC+nuZB+EYdgRZgiwxhTBTkF7CXvN" crossorigin="anonymous"></script>
</body>
</html>
- settings
STATIC_URL = '/static/'
STATICFILES_DIRS=[
BASE_DIR / 'static',
]