🤍 전 강의 25% 할인 중 🤍

2024년 상반기를 돌아보고 하반기에도 함께 성장해요!
인프런이 준비한 25% 할인 받으러 가기 >>

  • 카테고리

    질문 & 답변
  • 세부 분야

    풀스택

  • 해결 여부

    해결됨

LoginView와 SignupForm의 흐름 차이가 이게 맞을까요?

22.07.11 13:08 작성 조회수 116

0

안녕하세요. LoginView를 구현하다가 model-form과의 차이점이 제가 이해한 부분이 맞나해서 글 남겼습니다.

 

1)

accounts의 urls.py에서 login/, singup/ 으로 접근하면 각각 views의 login(인스턴스 함수?)와 signup(함수)를 보여주도록 안내한다.

2)

signup은 User모델을 Meta적으로 따르고 email, first_name, last_name을 커스텀한 SignupForm에 의해 form 인스턴스를 생성한다.(form = SignupForm())

3)

이 form은 'form'이라는 이름으로 accounts/signup_form.html에 전달돼서 {{ bootstrap_form form}} 부분으로 나타난다.

4)

LoginView로 생성된 인스턴스 함수(이렇게 부르는 게 맞는지 모르겠습니다.) login은 accounts/login_form.html으로 '자체적으로 생성된' 'form'을 넘겨준다. 이 역시 {{ bootstrap_form form }}에 적용되겠지만, 이는 signup에서와는 다른 form이다.

5)

(signup에서와 달리) forms.py에 해당 부분을 정의하지 않아도 되는 까닭은 LoginView-> FormView -> FormMixin의 함수 get_form_class와 get_form 부분이 AuthenticationForm을 참조하기 때문이다. 이때 (제가 생각하기에) 가장 큰 차이점은 forms.py 파일에서 Model을 Meta적으로 참조하는 부분이 없다는 것이다.

 

여기까지가 제가 이해한 부분인데 오류가 있다면 지적 부탁드리겠습니다. 그리고 아래는 궁금한 부분인데 완전한 해부가 안되고 직관적으로 받아들인 부분도 있어서 감안해주시면 감사하겠습니다 :)

 

6)

강사님께서 model-form이 강력한 무기라고 하셨는데 이건 뭔가 model에 따라 유연하게 form을 '만들어 주는' 자동화 무기같은 반면, LoginView가 제공하는 form은 forms.py를 거치지 않아서 더 빠르지만, AuthenticationForm등으로 이미 built-in 되어있기 때문에 유연성은 떨어지는 무기로 이해하면 될까요?

7)

그런데 이때

class AuthenticationForm(forms.Form):

를 봤을 때 우리가 보는 forms.py와만 관련이 없을 뿐이지, 장고 내부적인 메커니즘의 fomrs.py는 참조하게 되어있다. (더 들어가면 class Form(BaseForm... 이런 식인 것 같은데 심연 속으로 빠질까봐 여기까지만 확인해봤습니다.)

답변 2

·

답변을 작성해보세요.

1

옙. 화이팅입니다. :-)

<클래스 기반 뷰>에서의 form 처리에 대해서는 찾으신 대로, 아래 코드를 참고해보시면 됩니다.

https://github.com/django/django/blob/4.0.6/django/views/generic/edit.py

위 코드에 2~3개 정도의 포인트가 있어요. 차근차근 확인해보세요.

화이팅입니다. :-)

1

1. login 뷰는 LoginView.as_view(...) 를 통해 생성된 함수입니다. as_view는 class method로서 호출 시에 새로운 함수를 생성하여 반환합니다.

https://github.com/django/django/blob/main/django/views/generic/base.py#L80

/accounts/login/ 요청에 대한 처리는 login 뷰에서 처리를 하며,
/accounts/signup/ 요청에 대한 처리는 signup 뷰에서 처리를 하도록 URL Patterns를 정의하였습니다.

2. signup 뷰는 User 모델 인스턴스를 생성하는 데에 그 목적이 있습니다. 그러니 User 모델에 대한 ModelForm인 SignupForm을 통해 처리를 해볼 수 있는 거죠.

3. 뷰에서 생성한 Form 인스턴스는 대개 "form" 이름으로 템플릿 엔진에 전달됩니다. 그러니 form 이름으로 다양한 방법으로 form 인스턴스를 HTML로 표현하실 수 있습니다. {{ form }}과 같이 쓰시면 {{ form.as_table }}과 동일한 처리가 되구요. 이외에도 {{ form.as_p }}, {{ form.as_ul }} 등이 있습니다. 하지만 bootstrap 스타일로 폼을 보여주기 위해서는 django bootstrap 라이브러리를 활용하면 {% bootstrap_form form %} 을 통해 bootstrap 스타일로 HTML으로 폼 내용을 표현할 수 있습니다.

4. 위 3) 에서도 언급드린 것처럼 장고 기본의 CBV (클래스 기반 뷰) 에서는 "form" 이름으로 템플릿 엔진에 form 인스턴스가 전달됩니다. 그러니 LoginView에서도 마찬가지로 템플릿 엔진에서는 form 이름으로 form 인스턴스에 접근하실 수 있습니다.

5. LoginView 구현을 보시면 AuthenticationForm이 디폴트 form class로서 지정되어있습니다. AuthenticationForm을 그대로 쓰실려면 form class 지정을 하지 않으셔도 되고, 다른 폼 클래스로 변경하실려면 form class를 지정하셔야 겠죠.

---

6. ModelForm은 Model 기반에서 사용자로부터 입력폼을 노출하고, 입력값에 대한 유효성 검증을 하고, 유효성 검증을 거친 값에 대한 저장까지, 최소한의 코드로 중복코드를 최소화하여 구현할 수 있는 좋은 기술입니다.

Model 기반에서 폼을 구성할 때에는 forms.ModelForm을 쓰시면 좋고,
Model 기반이 아닐 데 폼을 구성하셔야 할 경우에는 forms.Form을 쓰시면 됩니다.

forms.Form을 쓴다고 해서 유연성이 떨어지는 것이 아니라, 그 목적이 다를 뿐입니다.

forms.ModelForm의 저력은 forms.Form에서 나옵니다.

좋은 질문 감사드립니다.
다양하게 고민하시고 살펴보시면서 질문도 많이 주세요.

화이팅입니다. :-)

뤀쪼님의 프로필

뤀쪼

질문자

2022.07.11

Model에 기반을 둘 것이냐가 관건이로군요. 그리고 "장고 기본의 CBV (클래스 기반 뷰) 에서는 "form" 이름으로 템플릿 엔진에 form 인스턴스가 전달됩니다."라고 말씀하신 부분에서, 해당 부분이 진행되려면 미리 1) "form이라는 이름의 객체를 생성하겠다." 2) "템플릿 엔진에 이 form 인스턴스를 넘기겠다." 라는 코딩이 미리 정의돼있어야 할 것 같은데 

class ProcessFormView(View):
"""Render a form on GET and processes it on POST."""
def get(self, request, *args, **kwargs):
"""Handle GET requests: instantiate a blank version of the form."""
return self.render_to_response(self.get_context_data())
def post(self, request, *args, **kwargs):
"""
Handle POST requests: instantiate a form instance with the passed
POST variables and then check if it's valid.
"""
form = self.get_form()

이 부분을 타고가서 추적?해보겠습니다.

 

감사합니다.

채널톡 아이콘