User Authentication Custom
회원가입 UserCreationForm 커스텀
- case 1) 기존 username/password만 입력. email 추가 입력받기
1 | # accounts/forms.py |
accounts.views.signup 뷰 Form Class를 SignupForm으로 변경
(그냥 class Meta로 할경우 기존 Meta정보를 다 삭제후 적는것이므로 model도 지정안되있음)
(따라서 class Meta(UserCreationForm.Meta)로 상속받은후 오버라이딩 필요)
이미 user 데이터베이스에는 기본으로 email 필드가있으므로 가능
case 2) phone_number 추가 입력받기
ModelForm은 하나의 모델만 지원합니다. 따라서 Profile 모델 정의하고, User 모델 인스턴스 생성 시 에 Profile 모델 인스턴스도 같이 생성해줍시다.!!
1 | # accounts/models.py |
로그인 AuthenticationForm 커스텀
- username/password 와 더불어, 숫자 퀴즈를 맞혀야 로그인
1 | # accounts/forms.py |
form.is_valid() 작업시 모든 필드가 유효성검사 통과 해야하므로 모든 필드명 true해야함, 폼클래스에 clean_필드명 함수를 해놔야함, 이미 AuthenticationForm을 상속받았기때문에 다른 로그인관련된인자는 이미 유효성검사할수있음. 내가 추가해준 필드만 검사로직 추가해주면됨
select_related와 prefetch_related
웹서비스, 각 요청 반응속도에서의 병목 (django debugtool쪽에 설명참조)
데이터베이스 : 아주 중요 , DB로 전달/실행되는 SQL갯수를 줄이고
- 절대적인 SQL갯수를 줄이고(조회 SQL의 경우 “JOIN”을 통해 쿼리갯수를 줄일 수 있음)
- 각 SQL의 성능/처리속도 최적화가 필요
로직의 복잡도 : 중요
프로그래밍 언어의 종류 : 대개는 미미
# 현재장고는 Model이 SQL구문을 생성해주고 이 SQL이 DB가 처리함.그리고 SQL로 돌려줌
DB단/파이썬단 조인을 통한 조회쿼리 성능 향상
HOW ?
ForeignKey 혹은 OneToOneField 관계
QuerySet.select_related()
(ForeignKey예시: class Comment안에 post = ForeignKey(Post)같이 외래키가 Post이므로 Comment에서 Post를 찾아들어갈때를 .select_related() )
ManyToManyField 혹은 ForeignKey의 reverse relation
QuerySet.prefetch_related()
( ForeignKey의 reverse relation 예시: Post측에는 외래키정해져있지않은데 외래키를 찾아들어가는것이므로 Post에서 Comment찾아들어감 .prefetch_related() )
사용이유는 106SQL 쿼리인게 위에 두개 사용하면 6SQL에 시간은 5배줄어든다
QuerySet.select_related()
(ForeignKey 혹은 OneToOneField관계시 사용)
1 | from blog.models import Comment #Post와 1:N의 관계 |
1 | tip: DB에 대량생산후 저장 |
QuerySet.select_related() 적용
- ForeignKey/OneToOneField 관계에서 Lazy하게 쿼리하지 않고, INNER JOIN 으로 쿼리할 수 있습니다.
1 | from blog.models import Comment |
QuerySet.prefetch_related()
(ManyToManyField 혹은 ForeignKey의 reverse relation)
#Post:Comment=1:N관계에서 comment쪽에서는 comment.post하면 접근가능하지만
post쪽에서는 인자가 없으므로 post.comment_set이렇게 하면 접근가능하다.
(Comment.objects.filter(post=post)와 완전히 같다)
1 | from blog.models import Post |
1 | # 클래스 기반 뷰에서는 (queryset=Post.objects.all().prefetch_related())를 따로 지정하므로써 디폴트값에서 바꿀수있다. |
django admin에 적용
select_related
방법1) ModelAdmin.list_select_related 옵션 적용(장고가자동으로)
1 | class CommentAdmin(admin.ModelAdmin): |
방법2) ModelAdmin.get_queryset 멤버함수 재정의를 통해 적용
1 | class CommentAdmin(admin.ModelAdmin): |
prefetch_related
ModelAdmin.get_queryset 멤버함수 재정의를 통해 적용
1 | class PostAdmin(admin.ModelAdmin): |
1 | #admin.py |
Error Logging
로그
특정 형식으로 현 상황을 기록하는 문자열 기록
디버그 로그 : 디버깅을 목적으로 자세하게 로깅
웹서버 ACCESS LOG / ERROR LOG
[09/Feb/2017 07:04:26] “GET /blog/1/ HTTP/1.1” 200 18314 #(시간, 방식, url, http버전 응답상태 응답사이즈)
[09/Feb/2017 07:04:33] “GET /blog/6/ HTTP/1.1” 200 12314
오류 로그 : 오류에 대한 자세한 정보를 로깅 (절대 상상하지 마세요.)
그 외 다양한 상황을 기록
logging
파이썬 빌트인 logging #ref 모듈을 통해 지원 장고 로깅 설정은 logging.config.dictConfig #ref 포맷을 사용
- Loggers
- Handlers
- Filters
- Formatters: LogRecord 속성 지원
logger
named bucket을 지정하여, 현 모듈에서 쓸 logger 획득 지원
Level(경고메세지 레벨지정) : debug, info, warning, error, critical
1 | # myapp/views.py |
named bucket
마침표로 parent/child 계층 구분
ex) django.security.csrf 로그: django.security(자식)와 django(부모)에 전파, 정보둘다가짐
부모 namespace로의 전파를 막을려면, 해당 handlers에 propagate=False 설정
django에서 사용중인 named bucket
• django • django.contrib.gis • django.db.backends • django.db.backends.schema • django.request • django.security.csrf • django.server • django.template • etc
sentry(오류로깅 처리해줌)
- Error 로깅은 Sentry 를 이용하시면 편리
- 지원 언어/플랫폼 : Python, JavaScript, PHP, Ruby, Java, Cocoa, C#, Go, Elixir
- 실 서버 배포했을 때, 오류현황을 모아서 볼 수 있고, 이메일 알림도 지원
- 서비스 버전 pricing 및 설치 버전
sentry 서비스, 장고설정
설정방법
쉘> pip install raven
1 | https://sentry.io/organizations/spicyhoro/issues/1362602338/?project=1838267&query=is%3Aunresolved# |
- 연동테스트
참고) logging.config.dictConfig 포맷
example : #1, #2
version: dictConfig 포맷 버전. 1로 지정
root : 최 상위 핸들러 정의
loggers : named bucket 별 수행할 “log 핸들러” 지정
handlers : 핸들러 별 수행할 Handler 클래스 지정
formatters : 로그 문자열 포맷 정의
filters : 핸들러가 호출될 조건 정의
OAuth 회원가입과 동시에 로그인
OAuth
- OpenID 로 개발된 표준 인증 방식
- 각 서비스 별로 제 각각인 인증방식을 표준화한 인증방식
- 인증을 공유하는 애플리케이션끼리는 별도의 인증이 필요없음.
- 하지만 회사별로 OAuth Provider에 따라 조금씩 다름
다양한 장고 OAuth 라이브러리
- django-allauth
- django-oauth-toolkit
- python-social-auth #ref
django-allauth
- 라이브러리 설치: 라이브러리 설치 : pip3 install “django-allauth==0.31.0”
다양한 로그인 방법 (Provider) 지원
- daum, kakao, naver, facebook, google, linkedin 등
적용할 Provider를 settings/INSTALLED_APPS 에 추가하고, admin 페이지를 통해 SocialApplication 등록 (client key/secret)(이것이 SocialApplication에 등록되어있다
설정법
1 | # 프로젝트/settings.py |
1 | # 프로젝트/urls.py |
1 | # accounts/views.py |
1 | {% extends "accounts/layout.html" %} |
프로필 이미지 노출
1 | # first.get_avatar_url라는함수를 통해 프로필 사진도가져옴 |
플랫폼별 로그인
페이스북 로그인, 적용순서
facebook for developers 에서 “새 앱” 등록
새로이 생성된 앱의 app_id, app_secret 키를 복사
“Facebook 로그인” 설정에서 “유효한 OAuth 리다이렉션 URI” 세팅
로그인을 수행할 사이트의 호스트명을 다수 입력
장고 admin 페이지에서 Facebook Provider에 대해,
새로운 SOCIAL ACCOUNTS에 Social applications에 등록
등록시 더 폼을 이용해 받을수있으므로 나중에 해보기(allauth)
유효한 OAuth 리디렉션 URI:
https://호스트명/accounts/facebook/login/callback/
네이버 로그인, 적용순서(오래되서 바뀐듯)
- “로그인 오픈 API” 활성화 • 이용목적 : “로그인 오픈 API (네이버 아이디로 로그인)” 체크
- 로그인 오픈 API 서비스 환경 : “웹” 체크
- PC 웹
- 서비스 URL : http://localhost:8000
- 네이버 아이디로 로그인 Callback URL : http://localhost:8000/accounts/naver/login/ callback/
- PC 웹
- 애플리케이션 개발 상태 : 릴리즈 시에 “서비스 적용” 체크
- “개발 중” 상태일 경우, 로그인 가능한 아이디 제한 (최대 20개)
카카오 로그인, 적용순서
Kakao Developers / 내 애플리케이션에서 앱 등록
특이사항 : 카카오 oauth 설정에서는 시크릿키는 없습니다.
사이트 도메인에 다음 추가
플렛폼추가
그리고, 실제 서비스 주소
rest API키를 client id로 등록하고 secret키는 따로 제공안함
Redirect URI: http://localhost:8000/accounts/kakao/login/callback/