본문 바로가기
django

2021.01.22 django User Custom ModelForm

by 해맑은 코린이 2021. 1. 22.

2021.01.22_ django  User Custom ModelForm_정리노트

 

오늘은 그 때 model custom 한거랑 연결 되는 모델폼을 같이 커스텀 해보자!!!!

 

 

불러올 기능들은 이렇게, forms 에서 불러올 것들은 밑줄 친 것만!! 나머지는 다음에 비밀번호 관련 내용이니 지금 당장은 필요 없는 폼들이다. 

 

forms.py

 

 

 

우리가 일반 모델폼을 작성할 때와 같이, 모델을 우리가 커스텀했던 모델로 불러와주고, 

우리가 입력받을 필드들을 적어준다. 대신에 models.ModelForm 을 상속 받지 않고, 장고에서 기본적으로 제공하는 유저를 생성할 때 쓰는 UserCreationForm 을 상속받아줬다.

 

근데 우리가 비밀번호, 비밀번호 확인과 같은 필드들은 설정을 안해줬잖??

 

출처 - 장고 공식 문서

 

 

그 이유는 이미, 장고에서 기본적인 필드를 제공해 놓았기 때문에 우리는 여기서 제공된 password1, password2 필드를 쓸 수 있기 때문이다.  

 

여기서 하나하나 살펴보면, 먼저 주석으로 주어진 사용자의 이름과 비밀번호에서 권한 없이 사용자를 생성하는 양식이라고 적혀있다.

그래서 각각 두 비밀번호가 다르면 , 두 비밀번호가 일치하지 않는다는 에러메세지를 띄워주고, password2 필드에는 확인을 위해 위와 동일한 비밀번호를 입력해라는 help_text 가 영어로 적혀있다. 이 부분은 폼의 위젯 양식으로 적혀있는 기본적인 에러 메세지로, 밑의 함수에서 이 메세지를 띄우는 것이다. 이와 함께 필드 위젯으로 비밀번호 확인 필드를 돕는 메세지가 적힌 것들이다!!

 

우리가 더 자세히 봐야할 부분은, 밑의 함수 부분! 클래스 안에서 구현된 함수는 파이썬에서 메소드라고 부른다. 

우리는 이 메소드 부분들을 커스텀 해 줄 것이다.

 

 

길어질 것 같으니 하나하나 끊어서 보겠음. 

 

forms.py

 

 먼저 clean이라는 메소드를 적어주고, 파이썬에서 클래스 메소드를 작성할 때에는 , 첫번째 매개변수를 관례적으로 self라고 적어준다. 물론 self 라고 안적어도 작동은 되겠지만, 나는 관례를 따라야지..ㅎ.ㅎ

또한 self 는 호출한 객체 자기 자신을 들고오기 때문에 아마 self라는 이름이 붙지 않았나 싶다 ㅎㅁㅎ

 

쨋든 self를 들고 왔는데, 우리가 nickname이라는 것을 뒤에 cleaned_data 라는 것으로 가지고 왔다. 

 

여기서  cleaned_data가 뭘까.

 

 cleaned_data

말그대로 깨끗한 데이터를 만드는 기능. 

장고에서 Form 인스턴스는 is_valid 함수를 가지고 있다. 이 경우는 우리가 뷰에서 봤듯이 유효성 검사를 실시해주는 함수이다. 그래서 유효성 검사를 시행 후, 참인 값들만 이 cleaned_data 에 의해 딕셔너리 형태로 오브젝트에 담기게 된다. 또한 장고에서는 유효성 검사 뿐만 아니라 데이터를 정리하여 일관된 형식으로 정규화를 하기 때문에 특정 필드에 대한 데이터를 다양한 방식으로 입력할 수 있다. 

CharField 또는 EmailField와 같은 텍스트 기반 필드는 항상 문자열로 입력을 정리하고, 인코딩을 따로 해주어야 한다.

 

또 만약 유효하지 않은 값들이 들어오면, 딕셔너리 형태로 출력을 한다고 했으니, 키값은 담기게 되고, 벨류값은 빈 값이 리턴된다. 

 

음.. 사실 나도 그냥 무작정 형식대로 따라하다 포스팅 하려고 공식문서와 구글링을 해서 찾아봤는데, 생각보다 심오한 뜻..이었군

 

 

그래도 차근차근 살펴보면,

 

cleaned_data 는 폼 유효성을 시행한 후에 참인 데이터 값들을 정리해주는 역할을 하는데, 만약 여기서 nickname이라는 객체가 유효하지 않은 값이 들어오게 되면, {'nickname' : ''} 이런식으로 빈 값을 출력해주고, 만약 다른 필드들은 유효한 값들이 들어오면, { 'email' : 벨류값 } 이런 식으로 정리해서 들고 와준다는 뜻임.

 

쨋든, 폼에서 이렇게 유효성 검사를 해주었으니, 뷰에서 원래 우리가 해줬던 것처럼 is_valid() 함수를 써줄 필요가 없겠지??

 

그러니 뷰에서는 따로 유효성 검사에 대한 로직을 작성하지 않아도 된다.

 

 

만약 또 뷰에서 딕셔너리 값으로 들고와서 유효성 처리를 해주고 싶다면..! 그것은 또 다음 포스팅에서 해볼 것이다. 오늘은 폼 유효성 검사에 대해서만 다루겠음 !

 

 

 

쨋든 우리가 원하는 필드의 데이터를 유효성 검사를 통해 들고는 왔는데, 우리가 오버라이딩 해줘야 할 것은 많이 남았즤... 우리가 원하는 조건들에 맞춰서 데이터들을 들고 와야 하지 않겠는가..! 그래서 우리는 원하는 조건을 if 와 try를 사용해서 적어줄 것이다. 

 

if 가 구문이라 블럭단위인 try 와는 속도면에서 차이가 나서 if 를 보통 많이 쓴다고 예ㅔㅔ전 포스팅에서 잠시 언급했던 것 같은데, 

 

여기서 except 에 에러를 띄워버리면, try에서 통과가 되어도 except 에서 에러를 발생시키기 때문에, 조심해서 써야 한다. 그러니 되도록 if문으로 간결하게.. 작성해보자

 

 

이번 프로젝트 같은 경우는 뒤에 완성에 초점을 두어서 막 베낀..결과 ㅠㅠ 결국 Js 에 대한 지식도 부족해서 하나때문에 완성도 못했다.. 물론 Js 가 아닐지도 모르겠지만.. 넘어야할 산이 많균.. 쨋든 이제라도 다시 블로그 포스팅 하면서 하나하나 배워야겠다.

 

 

 

뭐가 되게 많은데, 기본적으로 위에 비밀번호 관련은 내가 포스팅하면서 에러를 띄워보았을 때, 기본적으로 장고에서 제공하는 규악으로 인해 이미 text를 띄워주더라..헣헣 마찬가지로 비밀번호가 같은지 확인은 위의 공식문서에 보면 에러 메세지로 이미 처리하는 것을 볼 수가 있다.

 

 

 

나도 원래 비밀번호를 8자 이상 적어달라는 규악을 걸었기 때문에, 다른 것 또한 미리 장고에서 완벽히 준비를..^^ 그래서 나는 css 상에서 help텍스트를 지우지 않고 그대로 남겨 두었다. 이것은 그대로 사용하고, 

나머지 필드에 대한 조건을 걸어주었다. 

 

차례대로 위에서 cleaned_data의 방법으로 불러온 객체들을 담아서 주석으로 쓰여진 설명처럼 에러를 띄워주었다. 

조건을 걸고, 모델의 객체에서 각 인스턴스들을 가져와서 

( 위에서 내가 cleaned_data 를 쓴 객체들 -- 여기서는 모델 객체와의 관계에서 인스턴스라는 말을 썼음. 객체라는 것과 관계 지어줄 때에는 인스턴스라는 말을 쓴다. ) 

 

해당 사항이 False 이면 에러를 띄워줄건데, 여기서 폼에서는 에러를 띄울 때는 장고에서 ValidationError 를 통해 띄워준다. forms.ValidationError 형식을 통해 return 하지 않고 단순히 raise 를 통해 띄워주면 된다.

 

 

len 은 파이썬의 길이를 세는 기능, split은 괄호 안에 있는 값을 기준으로 문자열을 나누는 기능이다.

 

 

우리는 try except 를 쓸 때에는 except 구문에서는 error를 작성하지 않아야 한다는 것을 명심합시다!!

 

 

 

사실 또 찾아보다보니... 폼에 에러를 띄워주는 것 보단, 모델폼을 상속 받을 때는 모델에서 직접 필드를 정의 할 때, 

 

def length_error(value):

    if len(value) < 8: raise forms.ValidationError('3글자 이상 입력해주세요')

 

class CommunityUser

nickname = forms.CharField(validators=[length_error])

 

 

 

이렇게 적어주는 것이 어드민 페이지에서도 에러를 띄워줄 수 있고, 모델폼으로 그대로 반영할 수 있어서 좋다고 한다. 

 

하지만 우리는 오늘 장고에 있는 UserCreationForm 을 상속 받아 왔기 때문에 폼에서 직접 에러를 띄워주었다. 

만약 모델폼을 사용할 때에는 모델에서 띄워주자.

 

 

 

마지막으로 cleande_data를 리턴해주면 끝!

 

 

 

이렇게 하면, 또 html 상에서 메세지를 짠하고 브라우저에 보여줘야 한다. 템플릿으로 직접 수동으로 띄워주자!

 

출처 - 장고 공식문서

 

signup_html

 

 

복잡해보이지만, 우리는

 

{% if field.errors %}

이 필드에 에러가 있으면, 에러들을 for문으로 돌려서 해당 에러 한개를 띄워주고,

 

{% if signup_form.non_field_errors %}

signup_form 에 non_field_error 가 있으면 역시 해당 에러들을 for문으로 돌려서 해당 에러 하나를 띄우는 것이다. 

 

<div class="form-group{% if field.errors %}-error{% endif %}">

이 부분은 그냥, div 태그 이름을 자바스크립트처럼 에러가 있으면 에러에 대한 이름을 붙여서 클래스 이름을 바꾸는 태그이다.

 


 

블로그 포스팅을 하면서 다시 코드를 보며 중복 코드, 필요 없는 부분을 정리했지만, 사실 구글링을 통해 여러 기초적인 부분들을 보면서 이 코드가 좋은 코드라고는 생각되지 않았다.

 

 

일단 조건들을 한꺼번에 clean 이라는 메소드에 넣었고, 기능별로 메소드를 정리해서 return self.cleaned_data 해주는게 훨씬 직관적이고 일일이 주석을 달지 않아도 알 수 있는 방법이라고 생각한다.

 

 

출처 - 장고 공식 문서

 

또한 수동으로 템플릿 태그를 사용하지 않고, input value 값으로 해당 nickname, email 등의 객체를 넘겨주면, 수동으로 띄워줄 필요 없이 메세지들만 for문으로 돌려서 하나씩 띄워줄 수 있다.

 

 

 

 

 

역시 포스팅은 좋은 것.. 많은 점들을 배우고 정리할 수 있고 무엇보다 내가 내 블로그글을 필요할 때 마다 제일 자주 보는거 같다 ㅎㅁㅎ 지금은 또 다 아는거 같지만.. 나도 똑같이 또 다른 프로젝트에서 커스텀하라고 하면 내 블로그글 보면서 할 것 같기 때문...ㅎ 

 

쨋든 오늘의 포스팅도 여기서 끝끝!

 

 

 

'django' 카테고리의 다른 글

2021.12.17 Django Country field  (0) 2021.12.17
2021.11.11 Django Multi Image  (6) 2021.11.11
2021.01.18 django User Custom Model  (1) 2021.01.18
2021.01.15_django hitcount 조회수  (0) 2021.01.15
2020.11.08_django_category 자동 넘겨주기  (0) 2020.11.09

댓글