1)

Form 요청은 크게 method와 요청이 들어갈 주소인 action으로 이루어져 있다.

Form 요청에서 GET 요청은 http protocol을 보낼 때 보통 url의 ?(query) 뒤에 인자를 실어 보낸다. 이를 "querystring 형식의 encoding을 한다."라고 표현한다.

header 영역은 key: value의 형식의 header가 여러 줄 있고 body 영역은 POST 요청에만 있다고 한다. POST 요청에서 파일을 업로드 할 수 있는 이유도 여기에 있다. 그러므로 html GET 요청에서 input type에 text가 아닌 file을 설정해줘도 실효성은 없다.

enctype이 강제되는 GET 요청과 달리 POST 요청에서 파일을 업로드할 때는 enctype을 "multipart/form-data"로 명시해준다.

2)

httprequest는 응답 header, 빈 줄, 응답 body영역을 포함하는 요청 패킷을 parsing한 정보를 담고 있다.

request.FILES가 갖는 MultiValueDict 타입은 QueryDict 타입과 다르게 key 중복을 허용한다. http 요청이 하나의 key에 대해 중복 value를 전달하기 때문에 django 역시 이를 처리할 수 있어야하는 맥락에서 지원한다. 그렇지 않다면 "?name=Tom&name=Steve&name=Tomi" 같은 querystring은 overwrite 될 것이다.

3)

MultiValueDict를 상속한 QueryDict의 value는 기본적으로 mutable=False이기 때문에 수정 불가능(immutable)하다.

qd = QueryDict('name=Ardian&name=Simon&position=Developer', encoding='utf8')
+
qd['name'] = 'changed'

이를 시도할 시 AttributeError가 발생한다.

4)

앞에 정의한 MiddleWare의 기능 덕분에 View에서는 HttpRequest가 들어올 시 HttpResponse 응답을 기대 받는다.

settings.py의 MiddleWare의 리스트 내부는 순차적으로 호출되며 View 함수 호출에 까지 이르는데, View 함수가 응답을 하면 HttpResponse를 전달하기 까지 역순으로 처리된다.

5)

form과 user의 관계는 model과 db의 관계와 흡사하다. 각자 서비스의 앞/뒤를 맡고 있는 것이다. form 처리 과정은 크게
1) url로 View를 타고 들어왔을 때 빈 폼을 보여주는 것(GET)
2) 폼을 통해 입력된 값의 유효성 검증을 수행하고 저장하는 것(POST)
두 가지가 있다.

그러므로 하나의 함수 form(혹은 클래스 form)은 GET 요청 때 한 번, POST 요청 때 한 번, 총 두 번 호출될 가능성이 크다.

6)

form을 생성할 때 직접 validators를 넣어줄 수도 있고 model에 설정한 validators를 ModelForm을 통해 받을 수도 있다. 해당 유효성 검사 기능은 model에는 영향을 미치진 않는다.

그런데 admin단은 내부적으로 ModelForm을 만들어 사용하므로 validator가 작동했다. 이것이 싫다면 admin.py에 직접 작성한 form을 등록할 수도 있다.

"대부분의 로직은 Model에 구현하고 ModelForm에서는 Meta 클래스로 본뜨기 작업만 하자."라는 의도로 이해하고 넘어가자.

ModelForm에서 fields를 추출하는 작업은 django/forms/models.py의 fields_for_model 함수가 주축으로 보인다.

7)

class ItemForm(forms.ModelForm):
    class Meta:
        model = Item
        fields = '__all__'
+
from django.core.validators import MinLengthValidator
...
class Item(models.Model):
...
    description = models.TextField(
        validators==[MinLengthValidator(25)]
    )

django.core.validators에서 기본 validator를 가져오고 Item 모델 클래스를 본 뜬 간단한 ModelForm을 작성해보았다.

validators 적용 후 강사님은 makemigrations-migrate를 진행하지 않으셨지만, 나는 버전이 달라서 그런지 에러가 발생했다.

8)

urlpatterns=[
...
    path('new/', views.item_new, name='item_new'),
]

new/라는 주소로 접근하면 post_new 함수로 연결되도록 지정해주었다. 해당 함수는 form과 GET, POST 요청으로 엮일 것이다.

9)

<a herf="{% url gallery:item_new" class="btn btn-primary btn-block mt-3 mb-3"> 포스팅 작성 </a>
+
def item_new(request):
    form = ItemForm()
    return render(request, 'gallery/item_form.html', {
        'form': form
    })
+
<form action="" method="POST" enctype="multipart/form-data">
    {% csrf_token%}
    <table>
        {{ form }}
    </table>
    <input type="submit" value="저장" />
</form>

url_reverse 기능으로 item_new에 작성된 form을 불러 올 것이다.

item_new 함수가 form을 넘기는 item_form.html의 기본 사항도 작성해주도록 한다. ^table^ 태그가 없으면 가독성이 매우 떨어지니 주의하자.

"저장"을 클릭해서 request.POST와 request.FILES 요청을 보내더라도 아직 받아줄 수 있는 기능이 없으므로 작성하도록 한다.

10)

def item_new(request):
    if request.method == "POST":
        form = ItemForm(request.POST, request.FILES)
        if form.is_valid():
            item = form.save()
            return redirect(item)
    else:
        form = ItemForm()

    return render(request, 'gallery/item_form.html', {
        'form': form,
    })

item_new 함수는 첫 번째 인자로 데이터를 넘기고 두 번째 인자로 파일을 넘긴다. 이것이 유효성 검사를 통과하면 ModelForm이기 때문에 save() 명령어로 저장 가능하다. 일반 Form은 이를 지원하지 않는다. 그리고 Model에서 get_absolute_url() 구현된 점을 이용해서 redirect로 item_detail로 보낼 것이다.

주목할 점은 바로 저장하지 않고 request가 입력된 ModelForm의 instance를 만들고, 이 instance를 item란 이름으로 저장하는 두 단계를 거친다는 점이다.

11)

유저가 view를 통해서 GET 요청을 보내면 빈 폼과 함께 CSRF token을 전달 받고 이를 POST 요청과 함께 서버에 전달하면

<form action="" method="POST" enctype="multipart/form-data">

에 의해서 POST 요청에 한해 CSRFViewMiddleWare의 검사가 이뤄진다.

view에 @csrf_exmept를 씌워준다면 끌 수는 있다.

이는 유저 인증 token과 Json web token과는 다른 개념인데 SPA, Android/iOS 등에서는 사용하지 않는다.

0개의 댓글