본문 바로가기
django

2020.09.23_django_좋아요 기능 구현

by 해맑은 코린이 2020. 9. 24.

2020.09.24_django_좋아요 기능 구현_정리노트

 

 

 

 

헣헣.. 며칠만의 포스팅인가..쥬륵 요즘 점점 하루에 하나 올릴만한 내 능력딸림...흑흑 오늘은 프로젝트 중에 좋아요 기능 구현!

 

ㅠㅠ 드디어 원투원필드랑 매니투매니 필드......썼는데 혼돈 그자체...였음 

 

일단 내가 중간중간 하면서 오류 잡은 것부터 포스팅

 

 

 

 

프로젝트를 깃클론해서 받아온건데, 이러한 오류가 생겼다. 보통 테이블을 찾을 수 없다는 메세지는 마이그레이션 오류인데,

 

 

 

 

마이그레이션, 마이그레이트를 실행해봐도, 바꿀 것이 없다고 나온다. 또 __init.py__를 제외한 다른 마이그레이션 파일을 삭제하고, 마이그레이션을 초기화 시킨 후 해도 변하는 것이 없다면,

 

 

 

 

 

python manage.py migrate --run-syncdb 이라는 명령어를 실행해주면, 오류 해결 ! 앞으로 잘 써먹기 위해서 메모메모..

 

 

 

 

다음으로는 저번 포스팅 에서 __str__ (self) 가 문자열을 리턴해줘서 이름을 지어주는 느낌이라고 했었는데, 사실 무슨 기능을 하는지 정확히 몰랐던 나는 여기서 알 수 있었음.

 

 

 

 

내가 오늘 쓸 모델인 Post 에서 title을 넘겨주게 되면, 

 

 

 

 

 

오 어드민 상에서 Post 모델의 제목으로 이렇게 담기게 된다. 

 

 

비교를 하자면,

 

 

 

 

 

self 를 안썼을 경우에는 그냥 오브젝트로 담기게 된다. 오.. 이렇게 써주는 거였음 짝짝 

 

정리는 이까지..ㅎㅁㅎ... 오류랑 self 도 메모해놨으니 앞으로는 잘 쓸 수 있기를..


 

이제 기능으로 진짜 ㄱㄱㄱㄱㄱ

 

 

 

 

오늘 쓸 모델은 크게 2가지. 내가 쓸 유저 모델에서 One to One 관계로 확장을 시켜주고, 게시물에서도 여러 유저의 좋아요를 받을 수 있으면서, 유저 또한 여러 게시물에 좋아요를 할 수 있기 때문에 Many To Many 로 관계를 지어준 프로필 모델 ( 좋아요를 하나도 안할 수 있으니까 blank=True 속성을 추가해줌. ) 과,

 

기존 Post 모델에 좋아요 수를 받는 like_count 필드를 추가해준, 포스트 모델을 사용해볼 것이다.

여기서 PositiveIntergerField 는 int 즉, 정수형 필드다. IntegerField 라는 정수필드도 있는데,

다른 점은 PositiveIntergerField 는 0과 양수만을 가진다. 우리가 좋아요를 취소했을때 -1 이 뜨면 안되니까, IntegerField 대신 써준 것임. 

그리고 디폴트 값을 0으로 설정해주었다

 

또한 매니투매니를 사용할 때는 위의 모델에서 아래의 모델을 지정해 줄 때는 "Post" 라고 문자열로 표시해야 한다고 저번 포스팅에서 역시 설명했음 !-!

 

프로필 모델은 유저와 Post 와의 관계 설정을 해주고, Post 에서는 매니투매니로 관계시켜준 것에서 필드를 추가했다고 정리할 수 있을 것 같음...! 

 

또한 프로젝트를 하면서 나는 오늘 기존 장고에서 만들어둔, User 모델이 아닌, 다른 분이 작업해서 커스텀해놓은 MyUser 모델을 확장시킬 것이라, 나는 One to One 에서 MyUser를 썼지만, 

 

자 이제 오늘은 좋아요 기능에만 초점을 둘 것이기 때문에, Create를 따로 코드에서 실행 시키지 않고, 바로 어드민 상에서 게시물을 하나 만들어주려고 한다.

 

 

아 그리고 본격적으로 설명하기 전에 나는 이 기능하면서 역대급으로 오류를 많이 띄웠는데, 이해도 못하고 무작정 구글링으로 하려니까 진짜 멘탈이 탈탈 털려서 이제와서..하는 db 구조 파악하기...

 

그림판의 한계.. 내 언젠가 윈도우에도 일러를 설치하던가 아이패드를 살테다 ㅂㄷㅂㄷ..

 

 

 

이렇게 그림으로 정리.. 이렇게 하면 우리가 뷰에서 왜 get_object_or_404 를 쓰는지도 알게 되고, attribute 는 속성이라 여기서 오류가 났구나라고 알고... 디버깅할 때 이해하면서 해서 좀 더.. 구글링도 잘 할 수 있지 않을까 하고...ㅎㅁㅎ... 아직까지 이런것도 잘몰랐음 흑흑 일단 다음에 또 보기 위해서 정리정리

 

 

 

 

진짜 찐으로 기능 설명 ㄱㄱ

 

 

 

 

먼저 admin.py 로 가서

 

 

 

 

글을 적기 위해 필요한 유저, 유저프로필, 포스트 모델을 등록해주었음.

 

 

 

 

 

그러면 어드민 페이지에서 내가 등록해준 모델들이 뜰 것이고, 여기서 나는 User를 생성해주었다.

 

그러면 이 유저에 대한 프로필을 하나 생성해주어야겠다!

 

 

 

 

 

이렇게 내가 만들어준 계정을 선택하고, 코린 계정에 대한 프로필을 하나 생성해주었음. 밑의 필드에서는,

내가 좋아한 글을 정해줄 수 있는데, 내가 매니투매니로 정해줬기 때문에, 여기서도 게시물 여러개를 선택할 수 있게 + 가 뜬다.

 

 

이렇게 생성해주니까,

 

 

 

흐어 왜 문자열로 리턴이 안되는거지, 

 

 

 

또 찾아보니까 이 타입이 문자열로 반환을 잘 하지 못하는 거.. 그래서 이렇게 str() 로 감싸줘서 리턴하면

 

 

 

 

잘 User 계정에서 생성해주었던, 이름으로 프로필이 생성되었다.

 

자 이제 이 프로필을 가진 유저가 게시물을 작성해줘 보겠음!

 

 

짝짝 잘 작성이 된다. 지금은 내가 좋아요 기능을 중심으로 Post 모델을 작성했기 때문에, 그냥 title 하나만 해주었는데, 쨋든 우리가  필요할 것은 프로필을 FK 로 참조하는 user 필드와 이 게시물에 대한 좋아요 수를 세는 필드인 like_count만 지금 필수적으로 필요함 ㅇㅇ 쨋든 이렇게 포스팅을 적어주자. 

 

 

그래서 나는 오늘은 create 기능 없이 어드민에서 등록해줬고, 

 

우리가 해줘야할 일은 detail 페이지로 들어가서 좋아요 기능 띄우는거만 하면 된다!!!!!

 

 

간단하게 모델폼 띄워주고,

 

 

 

 

 

 

뷰에서 고냥 간단하게 글 하나만 생성해줘가지구 메인페이지에 이렇게 띄워주었음. 이러면 내가 작성한 글 오브젝트들을 전부 들고옴. 보통 게시물은 여러개니까 objects 로 들고온거여씀.

 

 

 

 

그래서 오브젝트들을 그냥 들고오니까( {{post_form}} ) 쿼리셋으로 뜨더라.. 이제 또 하나씩 왜 이렇게 썼는지 이제야 이해한다.. 그래서 for 문으로 우리가 가져온 오브젝트들을 필드하나하나 분리해주고, title만 써줬으니까 우리도 title만 써주자.

 

 

 

쨋든 url 연결 다해주고 detail도 연결 시켜주고 투닥투닥

 

메인html에 연결연결

 

 

pk 값으로 특정 글 detail 페이지 띄워주기

 

 

이거는..항상 했던 거라서 더이상 설명은 안하게쑴.

 

 

쨋든 이렇게 해주고 본격적으로 이 detail 페이지에 좋아요를 실행시키자 

후.. 함수부터 ㄱㄱ..

 

 

나는..다 이해한게 맞겠지.....ㅎ허헣허허..... 자 하나하나 일단 설명...주석...달아보았음..

 

먼저 우리가 좋아요를 아무나 누르게 하면 안되니까 장고에서 미리 제공하는 decorator 기능 중에 login_required 가 있다. 이렇게 임포트해서 @와 같이 써주면 해당 기능이 실행된다. 또,

 

 

url 상에서도 id 값과 같이 써주면 됨! 하나의 함수라고 생각하면 될 것 같다. 그러니 물론 import 도 해주자.

 

 

자 이렇게 이 데코레이터 기능을 써주고, 

해당 아이디 값 포스트, 유청된 유저, 요청된 유저의 프로필을 가져와주고

 

if 문을 쓰는 게 속도 차원에서 좋다고 하는데... 오류가 많이 떠서 try except 를 써주었다.  이 문은 먼저 try 에 실행할 코드를 써주고, 예외처리를 할 코드들은 except 에 써준다. 

 

그래서 우리가 매니투매니로 들고와줄 수 있게 설정했기 때문애 like_post 는 Post 에서 여러 개의 글을 들고 올 수 있는 내가 좋아요한 글 목록이 될 테고, 그 글 목록 중에서 우리가 특정 아이디 값을 가져와서 이 글 목록에 이 아이디를 가진 게시물이 있니? 라고 check 해주고 예외라면 밑에를 실행 시키는 것!

 

 

정리하자면 이 기능은 좋아요가 있는지 체크를 먼저 해주고 좋아요가 되어 있으면, 해당 좋아요 된 포스트를 좋아요한 목록에서 지워주고 , 좋아요 수를 -1 을 한 채로 세이브. 반대로 좋아요를 하지 않았으면, 좋아요 한 목록에 해당 포스트를 등록해주고 좋아요 수를 +1 해준 뒤 저장!

 

 

여기서 보는 내가 저번에 카테고리 때 썼던, filter와 get 의 차이 정리정리

장고에서 쿼리셋을 사용할 때 filter 와 get을 써서 조건에 부합하는 것들을 불러와줄 때 사용.  

 

get

get 은 쿼리셋이 아닌 모델의 오브젝트를 반환. 만약 조건에 해당하는 결과가 없으면, MultipleObjects 혹은 DoesNotExist exception 오류를 발생시킴.

그리고 get 을 쓸 때는 try, except 구문으로 예외처리 해주는게 좋다고 하네여.. 휴 다행

 

get 사옹시 에러

 

filter

새로운 쿼리셋을 생성 후 필터 조건에 부합하는 오브젝트들을 반환.

조건에 부합하는 오브젝트가 없다면, 에러메세지를 띄우지 않고, 빈 쿼리셋을 리턴.

 

filter 를 적어준 구문이 아닌, 빈 쿼리셋을 리턴해 그 밑 구분에서 에러가 난 것을 볼 수 있음.

 

 

후 이제 기능을 우리가 템플릿에 띄워주면 된다. detail.html 로 ㄱㄱ 

 

 

자 이것도 이렇게 띄워주었다. 특정 값을 가진 my_post 에서 PositiveIntegerField를 가져와주고,

 

마찬가지로 데코레이터와 id 값을 연결 시켜주고,

프로필 모델에 있는 like_post 필드를 모두 가져와서 글 목록에 my_post 가 있다면, 취소를 띄워주고 

아니면 좋아요를 띄워줘라 라고 if문으로 적어주었다...! 

 

ㅠㅠㅠㅠㅠㅠㅠ어우 어려워 .. ( 내 기준 )  여기서도 id 값이나 필드를 적어주는 것도 정말 오류가 많이 났다.. 모델 필드와 detail 뷰에서 적어준 my_post 값과 그 밑 데코레이터 함수에서 나온 함수의 post 등등..흑흑 html 에서는 하나밖에 인식을 못하는 정적인 페이지라서 아이디를 하나만 인식한닥오..하더라..뭐 쨋든 이렇게 적어주구 실행 ㄱㄱ

 

 

 

 

 

갹갹 좋아요를 누르면 어케 될까나

 

 

 

 

 

짝짝 된다!!!!!!!!!!!! 좋아요 수 올라가고 취소가 뜨게 된다..짝짝 ㅠㅠㅠㅠㅠ휴ㅠㅠㅠ

( 참고로 어드민 계정을 로그인하고 다른 계정으로 로그인해서 오류가 뜬다면, 어드민 계정 로그아웃 하고 다시 다른 계정으로 로그인을 하고, 그 로그인 된 유저의 프로필이 있는지 확인! 어드민으로 한번 들어가서 로그인 하게 되면, 관리자 계정으로 계속 유저가 남기 때문. )

 

 

 

 

 

 


 

 

후... 힘들군 드디어 포스팅 완료,,,, 사실 아직 완벽히 100프로 이해한지는 모르겠지만,, 멘탈 터진거는 어느정도 회복된 듯 허허 오늘은 이만 말도 끝끝 포스팅 끝!

'django' 카테고리의 다른 글

2020.10.05_django paging  (0) 2020.10.05
2020.09.27_django_댓글 수정,삭제, 대댓글  (0) 2020.09.28
2020.09.19_django_class CRUD  (0) 2020.09.19
2020.09.17_django_댓글 구현  (0) 2020.09.17
2020.09.15_django_관계 표현 modelfield  (0) 2020.09.16

댓글