From 072817d469e7da3942d9ea1cc4f04022919d821e Mon Sep 17 00:00:00 2001
From: YoungKwangJoo <164307740+youngkwangjoo@users.noreply.github.com>
Date: Sat, 3 Aug 2024 01:55:14 +0900
Subject: [PATCH 01/25] =?UTF-8?q?READ=20ME=20=EC=97=85=EB=8D=B0=EC=9D=B4?=
=?UTF-8?q?=ED=8A=B8?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
사진까지 교체
---
readme.md | 193 +++++++++++++++++++++++++++++++++++++++++++++++++++++-
1 file changed, 192 insertions(+), 1 deletion(-)
diff --git a/readme.md b/readme.md
index 3e03eb5..6bca9a4 100644
--- a/readme.md
+++ b/readme.md
@@ -1 +1,192 @@
-우린 감자쓰~~~~!!!!
\ No newline at end of file
+
+
GitPotato
+

+
이 프로젝트는 사용자의 GitHub 및 Baekjoon 활동을 기반으로 감자 캐릭터를 성장시키는 게임형 웹 애플리케이션입니다.
사용자는 자신의 활동을 통해 감자 캐릭터를 키우고, 게임의 재미를 통해 동기 부여를 받으며 일상적인 업무와 목표를 관리할 수 있습니다.
+
+
+
+## 프로젝트 개요
+- 프로젝트 이름: GitPotato
+- 프로젝트 기간: 2024년 7월 10일~2024년 8월 4일
+- 배포URL: https://www.gitpotatoes.com/
+
+
+### 팀원 구성
+| **김다연** | **주영광** | **노성우** |
+|:-------------------------------:|:-----------------------------:|:-----------------------------:|
+|
|
|
|
+| [dayeonkimm](https://github.com/dayeonkimm) | [youngkwangjoo](https://github.com/youngkwangjoo) | [NohSungwoo](https://github.com/NohSungwoo) |
+
+
+
+***
+
+## 1. 개발 환경
+### 개발언어
+
+

+
+
+### 라이브러리
+
+

+

+
+
+### 상태관리
+
+

+
+
+### 버전관리
+
+

+
+
+### 배포
+
+

+

+
+
+### 협업툴
+
+
+
+## 2. 채택한 개발기술과 브랜치 전략
+### 기술
+- React의 컴포넌트 기반 구조와 JavaScript의 최신 기능을 활용하여 애플리케이션의 모듈화와 재사용성을 높였습니다
+- Tailwind CSS의 유틸리티 클래스들을 사용하여 빠르고 일관된 스타일링을 구현했습니다
+- Zustand를 활용하여 웹어플리케이션의 상태를 간단하고 직관적으로 관리했습니다, 또한 불필요한 리렌더링을 방지하고 성능을 최적화했습니다
+- ESLint와 Prettier를 사용하여 코드 스타일을 자동으로 정리하고 일관성을 유지했습니다
+
+### 브랜치 전략
+- Main 프로젝트를 Fork하여 각자의 레포지토리에서 개발을 진행합니다.
+- 개발을 진행할 때에는 개발 유형에 맞게 개발유형/개발구역이름 형식으로 브랜치를 생성하여 작업합니다. 예를 들어, 새로운 기능을 추가할 때는 feat/login, 버그를 수정할 때는 fix/bug123과 같은 형식을 사용합니다.
+- 현재 작업하고 있는 부분의 기능 구현이 완료되면 팀원들에게 코드 리뷰를 요청합니다. Pull Request를 생성하여 코드 검토를 진행하며, 리뷰어의 피드백을 반영하여 코드를 개선합니다.
+- 코드 리뷰가 완료되고 승인이 나면, Pull Request를 통해 dev 브랜치로 변경 사항을 병합합니다. 병합 후에는 dev 브랜치에서 전체적인 기능 테스트를 진행합니다. dev 브랜치의 안정성이 확보되면 main 브랜치로 병합하여 배포를 준비합니다.
+- 이 전략을 통해 각 개발자는 독립적으로 작업하면서도 팀과의 협업을 원활하게 진행할 수 있습니다. 코드의 품질을 유지하고 버그를 최소화할 수 있도록 지속적으로 코드 리뷰와 테스트를 강화합니다.
+
+
+## 3. Commit Convention
+| 커밋 유형 | 의미 | 깃모지 |
+|--------------|------------------------------------------|-----------------|
+| **Feat** | 새로운 기능 추가 | :sparkles: |
+| **Fix** | 버그를 고친 경우 | :bug: |
+| **Docs** | 문서 수정 | :memo: |
+| **Refactor** | 코드 리팩토링 | :recycle: |
+| **Chore** | 패키지 매니저 수정, 그 외 기타 수정 | :package: |
+| **Design** | CSS 등 사용자 UI 디자인 변경 | :art: |
+| **Change** | 파일명 변경, 파일 삭제 등 기타 | :wrench: |
+| **Test** | 테스트 코드, 리팩토링 테스트 코드 추가 | :clown_face: |
+
+
+
+## 4. 프로젝트 구조
+```
+.
+├── README.md
+├── package-lock.json
+├── package.json
+├── src
+│ ├── App.jsx
+│ ├── apis
+│ │ ├── api
+│ │ │ ├── attendance.js
+│ │ │ ├── auth.js
+│ │ │ ├── baekjoon.js
+│ │ │ ├── github.js
+│ │ │ ├── potato.js
+│ │ │ ├── stack.js
+│ │ │ └── todo.js
+│ │ ├── services
+│ │ │ ├── authService.js
+│ │ │ ├── calendarService.js
+│ │ │ ├── levelService.js
+│ │ │ ├── settingPageService.js
+│ │ │ ├── stackService.js
+│ │ │ ├── todoService.js
+│ │ │ └── userUpdateService.js
+│ │ └── utils
+│ │ └── instance.js
+│ ├── assets
+│ │ ├── description.json
+│ │ └── images
+│ ├── components
+│ │ ├── common
+│ │ │ ├── alert
+│ │ │ ├── input
+│ │ │ └── loading
+│ │ ├── layout
+│ │ │ ├── footer
+│ │ │ └── header
+│ │ ├── modal
+│ │ │ ├── BaekjoonConnectModal.jsx
+│ │ │ ├── ChangePotatoModal.jsx
+│ │ │ ├── PotatoInfoModal.jsx
+│ │ │ ├── UserUpdateModal.jsx
+│ │ │ └── index.js
+│ │ └── shared
+│ │ ├── calendar
+│ │ ├── collection
+│ │ ├── info
+│ │ ├── level
+│ │ ├── potato
+│ │ ├── stack
+│ │ └── todo
+│ ├── hooks
+│ │ └── useCalendar
+│ ├── lib
+│ ├── main.jsx
+│ ├── pages
+│ │ ├── home
+│ │ ├── landing
+│ │ ├── oauthCallback
+│ │ ├── setting
+│ │ └── signin
+│ ├── store
+│ │ ├── dateStore.js
+│ │ ├── todosCompleteStore.js
+│ │ └── userStore.js
+│ ├── styles
+│ │ └── global.css
+│ └── utils
+│ └── storage.js
+├── tailwind.config.js
+└── vite.config.js
+```
+
+## 5. 프로젝트
+
+
+
Main Page
+

+
+
+
+
Login Page
+

+
+
+
+
Home Page
+

+
+
+
+
Update Modal
+

+
+
+
+
+
+## 6. Architecture 및 ERD
+### Architecture
+
+
+
From 8be7a24641f4a0d34e96bacb40e7694fa7f70047 Mon Sep 17 00:00:00 2001
From: YoungKwangJoo <164307740+youngkwangjoo@users.noreply.github.com>
Date: Sat, 3 Aug 2024 02:14:25 +0900
Subject: [PATCH 02/25] =?UTF-8?q?READ=20ME=20=EC=97=85=EB=8D=B0=EC=9D=B4?=
=?UTF-8?q?=ED=8A=B8?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
기술스택 변경 중..
---
readme.md | 26 +++++---------------------
1 file changed, 5 insertions(+), 21 deletions(-)
diff --git a/readme.md b/readme.md
index 6bca9a4..d66e6fd 100644
--- a/readme.md
+++ b/readme.md
@@ -21,32 +21,16 @@
***
-## 1. 개발 환경
-### 개발언어
+## 1. 기술 스택
-
-### 라이브러리
-
-

-

-
-
-### 상태관리
-
-

-
-
-### 버전관리

-
-
-### 배포
-

-
### 협업툴
From e20069195dae42a6a9478b4c747b42209225cd97 Mon Sep 17 00:00:00 2001
From: dayeonkimm
Date: Sun, 4 Aug 2024 22:09:16 +0900
Subject: [PATCH 03/25] docker-compose.yml
---
docker-compose.yml | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/docker-compose.yml b/docker-compose.yml
index 372dcda..0b3e88d 100644
--- a/docker-compose.yml
+++ b/docker-compose.yml
@@ -21,7 +21,8 @@ services:
- DB_USER=${RDS_USERNAME}
- DB_PASSWORD=${RDS_PASSWORD}
env_file:
- - .env
+ - .env
+
# 개발용
@@ -53,7 +54,7 @@ services:
# - .env
# depends_on:
# - db
-
+
# db: # PostgreSQL Database
# image: postgres:16-alpine
@@ -66,4 +67,5 @@ services:
# env_file:
# - .env
+
From 95db2c6762edfe0841119ae675041b00583372a9 Mon Sep 17 00:00:00 2001
From: dayeonkimm
Date: Sun, 4 Aug 2024 22:11:07 +0900
Subject: [PATCH 04/25] Dockerfile
---
Dockerfile | 42 ++++++++++++++++++++----------------------
1 file changed, 20 insertions(+), 22 deletions(-)
diff --git a/Dockerfile b/Dockerfile
index 8fb6ca7..7a14c02 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -19,29 +19,26 @@ EXPOSE 8000
# ARG DEV=false
-RUN python -m venv /py && \
- /py/bin/pip install --upgrade pip && \
- /py/bin/pip install -r /tmp/requirements.txt && \
- apk add --update --no-cache jpeg-dev && \
- apk add --update --no-cache --virtual .tmp-build-deps \
- build-base musl-dev zlib zlib-dev linux-headers && \
- # if [ $DEV = "true" ]; \
- # then /py/bin/pip install -r /tmp/requirements.dev.txt ; \
- # fi && \
- rm -rf /tmp && \
- apk del .tmp-build-deps && \
- adduser \
- --disabled-password \
- --no-create-home \
- django-user
-
-ENV PATH="/py/bin:$PATH"
-
+# 가상 환경 설정 및 패키지 설치
+RUN python -m venv /py
+RUN /py/bin/pip install --upgrade pip
+RUN /py/bin/pip install --no-cache-dir -r /tmp/requirements.txt
+
+# 시스템 패키지 설치
+RUN apk add --update --no-cache jpeg-dev
+RUN apk add --update --no-cache --virtual .tmp-build-deps \
+ build-base musl-dev zlib zlib-dev linux-headers \
+ && apk del .tmp-build-deps
+
+# django-user 생성 및 권한 설정
+RUN if ! getent passwd django-user; then adduser -D django-user; fi
+USER root
+RUN chown -R django-user:django-user /py/lib/python3.11/site-packages
USER django-user
-# 이 명령어를 추가하여 pytest를 설치합니다.
-RUN /py/bin/pip install pytest pytest-django
-
+# 추가 패키지 설치
+ENV PATH="/py/bin:$PATH"
+RUN /py/bin/pip install --no-cache-dir pytest pytest-django django-cors-headers
# 개발용
@@ -87,4 +84,5 @@ RUN /py/bin/pip install pytest pytest-django
# USER django-user
# # 이 명령어를 추가하여 pytest를 설치합니다.
-# RUN /py/bin/pip install pytest pytest-django
\ No newline at end of file
+# RUN /py/bin/pip install pytest pytest-django
+
From d207fdbcd95bbdb3a90ec11e0e45e32e1e62b212 Mon Sep 17 00:00:00 2001
From: dayeonkimm
Date: Sun, 4 Aug 2024 22:12:52 +0900
Subject: [PATCH 05/25] cors setting
---
potato_project/app/settings.py | 61 ++++++++++++++++++++++++++++++++--
1 file changed, 58 insertions(+), 3 deletions(-)
diff --git a/potato_project/app/settings.py b/potato_project/app/settings.py
index f0f2833..7eaac4d 100644
--- a/potato_project/app/settings.py
+++ b/potato_project/app/settings.py
@@ -53,8 +53,10 @@
"allauth.account",
"allauth.socialaccount",
"allauth.socialaccount.providers.github",
+ "corsheaders",
]
+
INSTALLED_APPS = DJANGO_SYSTEM_APPS + CUSTOM_USER_APPS
# Custom user model
@@ -71,6 +73,7 @@
# 미들웨어 설정
MIDDLEWARE = [
+ "corsheaders.middleware.CorsMiddleware",
"django.middleware.security.SecurityMiddleware",
"django.contrib.sessions.middleware.SessionMiddleware",
"django.middleware.common.CommonMiddleware",
@@ -115,6 +118,9 @@
"USER": os.environ.get("RDS_USERNAME"),
"PASSWORD": os.environ.get("RDS_PASSWORD"),
"PORT": os.environ.get("RDS_PORT", 5432),
+ "OPTIONS": {
+ "client_encoding": "UTF8", # UTF-8 문자셋 설정
+ },
}
}
@@ -205,6 +211,55 @@
}
}
-SOCIALACCOUNT_LOGIN_ON_GET = True
-LOGIN_REDIRECT_URL = "/oauth-callback/"
-ACCOUNT_LOGOUT_REDIRECT_URL = "/landing/"
+SOCIALACCOUNT_LOGIN_ON_GET = False
+# LOGIN_REDIRECT_URL = "/oauth-callback/"
+# ACCOUNT_LOGOUT_REDIRECT_URL = "/landing/"
+
+DEFAULT_CHARSET = "utf-8"
+
+DEFAULT_CHARSET = "utf-8"
+
+LOGGING = {
+ "version": 1,
+ "disable_existing_loggers": False,
+ "handlers": {
+ "console": {
+ "class": "logging.StreamHandler",
+ },
+ },
+ "root": {
+ "handlers": ["console"],
+ "level": "DEBUG",
+ },
+}
+
+# CORS_ORIGIN_WHITELIST = ['http://localhost:5173', 'http://127.0.0.1:5173', 'https://www.gitpotatoes.com',] # 특정 Origin만 허용
+CORS_ALLOWED_ORIGINS = [
+ "https://www.gitpotatoes.com", # 실제 배포 프론트엔드 URL
+ "http://localhost:5173", # 프론트엔드 로컬 서버 URL
+ "http://127.0.0.1:5173", # 프론트엔드 로컬 서버 URL
+]
+CORS_ALLOW_CREDENTIALS = True # 쿠키 등 credential 정보 허용
+CORS_ALLOW_METHODS = [
+ "DELETE",
+ "GET",
+ "OPTIONS",
+ "PATCH",
+ "POST",
+ "PUT",
+]
+CORS_ALLOW_HEADERS = [
+ "accept",
+ "accept-encoding",
+ "authorization",
+ "content-type",
+ "dnt",
+ "origin",
+ "user-agent",
+ "x-csrftoken",
+ "x-requested-with",
+]
+SECURE_PROXY_SSL_HEADER = ("HTTP_X_FORWARDED_PROTO", "https")
+
+CSRF_COOKIE_SECURE = True
+SESSION_COOKIE_SECURE = True
From 605a1e1666246bbfe081016f51c9adc42d9cabfd Mon Sep 17 00:00:00 2001
From: dayeonkimm
Date: Sun, 4 Aug 2024 22:13:59 +0900
Subject: [PATCH 06/25] isort, black
---
potato_project/attendances/views.py | 8 ++++++--
1 file changed, 6 insertions(+), 2 deletions(-)
diff --git a/potato_project/attendances/views.py b/potato_project/attendances/views.py
index 3014709..a85f113 100644
--- a/potato_project/attendances/views.py
+++ b/potato_project/attendances/views.py
@@ -40,7 +40,9 @@ def increment(self, request):
# 출석날짜가 오늘이면 이미 출석함을 반환
attendance = self.get_user_attendance(user)
if attendance and attendance.date == today:
- return Response({"오늘은 출석을 이미 하셨어요!"}, status=status.HTTP_400_BAD_REQUEST)
+ return Response(
+ {"오늘은 출석을 이미 하셨어요!"}, status=status.HTTP_400_BAD_REQUEST
+ )
# 새로운 출석 기록 생성
new_attendance = Attendance.objects.create(
@@ -71,4 +73,6 @@ def decrement(self, request):
user.save()
# 성공 응답 반환
- return Response({"message": "물건을 구매했습니다.", "total_coins": user.total_coins})
+ return Response(
+ {"message": "물건을 구매했습니다.", "total_coins": user.total_coins}
+ )
From 6776c32db50023274039e5ec62fb35cd4e61bcaf Mon Sep 17 00:00:00 2001
From: dayeonkimm
Date: Sun, 4 Aug 2024 22:15:50 +0900
Subject: [PATCH 07/25] =?UTF-8?q?=20=EA=B9=83=ED=97=88=EB=B8=8C=20?=
=?UTF-8?q?=EC=BB=A4=EB=B0=8B=EC=97=90=20=EB=94=B0=EB=A5=B8=20=EA=B0=90?=
=?UTF-8?q?=EC=9E=90=20=ED=9A=8D=EB=93=9D?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
potato_project/githubs/signals.py | 122 ++++++++++++++++++++++++++++++
1 file changed, 122 insertions(+)
create mode 100644 potato_project/githubs/signals.py
diff --git a/potato_project/githubs/signals.py b/potato_project/githubs/signals.py
new file mode 100644
index 0000000..78467e8
--- /dev/null
+++ b/potato_project/githubs/signals.py
@@ -0,0 +1,122 @@
+from datetime import date, timedelta
+
+from django.db.models.signals import post_save
+from django.dispatch import receiver
+from githubs.models import Github
+from potatoes.models import Potato
+
+
+@receiver(post_save, sender=Github)
+def get_winter_potato(sender, instance, created, **kwargs):
+ # 새 Github 데이터가 생성 or 업데이트, 날짜가 크리스마스이며, commit_num이 1 이상인 경우에만 실행
+ if (
+ created
+ and instance.commit_num >= 1
+ and instance.date.month == 12
+ and instance.date.day == 25
+ ): # 월과 일만 비교
+ try:
+ # potato_type_id=6인 감자 조회
+ potato = Potato.objects.get(user=instance.user, potato_type_id=6)
+ if not potato.is_acquired: # 이미 획득한 경우에는 변경하지 않음
+ potato.is_acquired = True
+ potato.save()
+ except Potato.DoesNotExist:
+ # 해당 감자가 없는 경우 에러 처리 (필요에 따라 추가)
+ pass
+
+
+@receiver(post_save, sender=Github)
+def get_ghost_potato(sender, instance, created, **kwargs):
+ if (
+ created
+ and instance.commit_num >= 1
+ and instance.date.month == 10
+ and instance.date.day == 31
+ ):
+ try:
+ potato = Potato.objects.get(user=instance.user, potato_type_id=7)
+ if not potato.is_acquired:
+ potato.is_acquired = True
+ potato.save()
+ except Potato.DoesNotExist:
+ pass
+
+
+@receiver(post_save, sender=Github)
+def get_crystal_potato(sender, instance, created, **kwargs):
+ if created and instance.commit_num >= 1:
+ # 30일 전 날짜 계산
+ thirty_days_ago = instance.date.date() - timedelta(days=30)
+
+ # 30일 연속 커밋 여부 확인
+ commits_in_30_days = (
+ Github.objects.filter(
+ user=instance.user,
+ date__gte=thirty_days_ago,
+ date__lte=instance.date.date(),
+ commit_num__gte=1,
+ )
+ .values("date")
+ .distinct()
+ .count()
+ )
+
+ if commits_in_30_days == 30:
+ try:
+ potato = Potato.objects.get(user=instance.user, potato_type_id=8)
+ if not potato.is_acquired:
+ potato.is_acquired = True
+ potato.save()
+ except Potato.DoesNotExist:
+ pass
+
+
+@receiver(post_save, sender=Github)
+def get_dirty_potato(sender, instance, created, **kwargs):
+ if created:
+ # 30일 전 날짜 계산
+ thirty_days_ago = instance.date.date() - timedelta(days=30)
+
+ # 30일 동안 커밋이 있었는지 확인
+ any_commits_in_30_days = Github.objects.filter(
+ user=instance.user,
+ date__gte=thirty_days_ago,
+ date__lte=instance.date.date(),
+ commit_num__gte=1,
+ ).exists()
+
+ if not any_commits_in_30_days:
+ # 30일 연속 커밋이 없는 경우 감자 아이디 9 획득 로직 실행
+ try:
+ potato = Potato.objects.get(user=instance.user, potato_type_id=9)
+ if not potato.is_acquired:
+ potato.is_acquired = True
+ potato.save()
+ except Potato.DoesNotExist:
+ pass # 필요에 따라 에러 처리 추가
+
+
+@receiver(post_save, sender=Github)
+def get_green_potato(sender, instance, created, **kwargs):
+ if created:
+ # 90일 전 날짜 계산
+ ninety_days_ago = instance.date.date() - timedelta(days=90)
+
+ # 90일 동안 커밋이 있었는지 확인
+ any_commits_in_90_days = Github.objects.filter(
+ user=instance.user,
+ date__gte=ninety_days_ago,
+ date__lte=instance.date.date(),
+ commit_num__gte=1,
+ ).exists()
+
+ if not any_commits_in_90_days:
+ # 90일 연속 커밋이 없는 경우 감자 아이디 10 획득 로직 실행
+ try:
+ potato = Potato.objects.get(user=instance.user, potato_type_id=10)
+ if not potato.is_acquired:
+ potato.is_acquired = True
+ potato.save()
+ except Potato.DoesNotExist:
+ pass # 필요에 따라 에러 처리 추가
From b571aac7673d87bc0f92856de0bfc450320b200a Mon Sep 17 00:00:00 2001
From: dayeonkimm
Date: Sun, 4 Aug 2024 22:16:08 +0900
Subject: [PATCH 08/25] =?UTF-8?q?=20=EB=A0=88=EB=B2=A8=EC=97=85?=
=?UTF-8?q?=EC=97=90=20=EB=94=B0=EB=A5=B8=20=EA=B0=90=EC=9E=90=20=ED=9A=8D?=
=?UTF-8?q?=EB=93=9D?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
potato_project/users/signals.py | 71 +++++++++++++++++++++++++++++++++
1 file changed, 71 insertions(+)
create mode 100644 potato_project/users/signals.py
diff --git a/potato_project/users/signals.py b/potato_project/users/signals.py
new file mode 100644
index 0000000..3fc6bb5
--- /dev/null
+++ b/potato_project/users/signals.py
@@ -0,0 +1,71 @@
+from django.db.models.signals import post_save
+from django.dispatch import receiver
+from potatoes.models import Potato
+from users.models import User
+
+
+@receiver(post_save, sender=User)
+def get_level_two_potato(sender, instance, **kwargs):
+ # 레벨이 2로 변경되었고, 이전 레벨이 2가 아닐 때만 실행
+ if (
+ instance.potato_level == 2
+ and instance.tracker.previous("potato_level") != 2
+ and not kwargs.get("created", False)
+ ):
+ try:
+ # potato_type_id=2인 감자 조회
+ potato = Potato.objects.get(user=instance.user, potato_type_id=2)
+ if not potato.is_acquired:
+ potato.is_acquired = True
+ potato.save()
+ except Potato.DoesNotExist:
+ # 해당 감자가 없는 경우 에러 처리 (필요에 따라 추가)
+ pass
+
+
+@receiver(post_save, sender=User)
+def get_level_three_potato(sender, instance, **kwargs):
+ if (
+ instance.potato_level == 3
+ and instance.tracker.previous("potato_level") != 3
+ and not kwargs.get("created", False)
+ ):
+ try:
+ potato = Potato.objects.get(user=instance.user, potato_type_id=3)
+ if not potato.is_acquired:
+ potato.is_acquired = True
+ potato.save()
+ except Potato.DoesNotExist:
+ pass
+
+
+@receiver(post_save, sender=User)
+def get_level_four_potato(sender, instance, **kwargs):
+ if (
+ instance.potato_level == 4
+ and instance.tracker.previous("potato_level") != 4
+ and not kwargs.get("created", False)
+ ):
+ try:
+ potato = Potato.objects.get(user=instance.user, potato_type_id=4)
+ if not potato.is_acquired:
+ potato.is_acquired = True
+ potato.save()
+ except Potato.DoesNotExist:
+ pass
+
+
+@receiver(post_save, sender=User)
+def get_level_five_potato(sender, instance, **kwargs):
+ if (
+ instance.potato_level == 5
+ and instance.tracker.previous("potato_level") != 5
+ and not kwargs.get("created", False)
+ ):
+ try:
+ potato = Potato.objects.get(user=instance.user, potato_type_id=5)
+ if not potato.is_acquired:
+ potato.is_acquired = True
+ potato.save()
+ except Potato.DoesNotExist:
+ pass
From a704b244cd395d67311d089e69c454e524aee305 Mon Sep 17 00:00:00 2001
From: dayeonkimm
Date: Sun, 4 Aug 2024 22:17:16 +0900
Subject: [PATCH 09/25] =?UTF-8?q?=20=EA=B9=83=ED=97=88=EB=B8=8C?=
=?UTF-8?q?=20api=20=EC=88=98=EC=A0=95?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
- 반환값 개수 매칭 에러 수정
- 필터에 author 추가해서 사용자가 커밋한 내용만 필터
---
potato_project/githubs/views.py | 97 ++++++++++++++++-----------------
1 file changed, 47 insertions(+), 50 deletions(-)
diff --git a/potato_project/githubs/views.py b/potato_project/githubs/views.py
index 60c6c4d..53a6589 100644
--- a/potato_project/githubs/views.py
+++ b/potato_project/githubs/views.py
@@ -1,11 +1,10 @@
from datetime import datetime, timedelta
-# githubs api를 불러오는 함수
-# 깃허브 API 호출 서비스
import requests
from django.db.models import Avg, Sum
from django.http import JsonResponse
from django.utils import timezone
+from rest_framework import status
from rest_framework.permissions import IsAuthenticated
from rest_framework.response import Response
from rest_framework.views import APIView
@@ -13,22 +12,25 @@
from .models import Github as GithubModel
-# 깃허브 API 호출 서비스
class GitHubAPIService:
def __init__(self, access_token):
self.access_token = access_token
- def get_commits(self, repo):
+ def get_commits(self, repo, author):
github_api_url = f"https://api.github.com/repos/{repo}/commits"
+ params = {
+ "author": author, # author 파라미터 설정
+ "per_page": 100,
+ }
headers = {
"Authorization": f"token {self.access_token}",
"Accept": "application/vnd.github.v3+json",
}
- response = requests.get(github_api_url, headers=headers)
+ response = requests.get(github_api_url, headers=headers, params=params)
if response.status_code == 200:
- return response.json()
+ return response.json(), 200
else:
return None, response.status_code
@@ -42,22 +44,7 @@ def get_repos(self, username):
response = requests.get(github_api_url, headers=headers)
if response.status_code == 200:
- return response.json()
- else:
- return None, response.status_code
-
- def get_total_commits(self, username):
- github_api_url = f"https://api.github.com/search/commits?q=author:{username}"
- headers = {
- "Authorization": f"token {self.access_token}",
- "Accept": "application/vnd.github.v3+json",
- }
-
- response = requests.get(github_api_url, headers=headers)
-
- if response.status_code == 200:
- data = response.json()
- return data["total_count"]
+ return response.json(), 200
else:
return None, response.status_code
@@ -83,9 +70,12 @@ def get(self, request):
return Response({"error": "깃허브 액세스 토큰이 없습니다."}, status=401)
github_service = GitHubAPIService(user.github_access_token)
+ db_service = GitHubDatabaseService()
# 오늘 날짜
- today = timezone.now().date()
+ today = timezone.localtime(timezone.now()).date()
+
+ print("today: ", today)
# 7일 전 날짜
week_ago = today - timedelta(days=7)
@@ -94,57 +84,64 @@ def get(self, request):
if repos is not None:
# 오늘, 7일간 커밋 수 계산
- today_commit_count = 0
- week_commit_count = 0
+ today_commits = 0
for repo in repos:
- commits, _ = github_service.get_commits(repo["full_name"])
+ commits, _ = github_service.get_commits(
+ repo["full_name"], user.username
+ )
if commits is not None:
for commit in commits:
commit_date = datetime.strptime(
commit["commit"]["author"]["date"], "%Y-%m-%dT%H:%M:%SZ"
).date()
if commit_date == today:
- today_commit_count += 1
- if commit_date >= week_ago:
- week_commit_count += 1
-
- # 7일 평균 커밋 수 계산
- week_average_commit_count = round(week_commit_count / 7, 2)
-
- # 총 커밋 수 가져오기 (get_total_commits 사용)
- total_commit_count = github_service.get_total_commits(user.username)
+ today_commits += 1
# 오늘 커밋 수 데이터베이스에 저장
db_service = GitHubDatabaseService()
- db_service.update_or_create_commit_record(user, today_commit_count, today)
+ db_service.update_or_create_commit_record(user, today_commits, today)
- # 경험치 및 레벨 업데이트
- user.exp = (
+ # 최근 7일간 커밋 수 및 전체 커밋 수 계산
+ week_commits = (
+ GithubModel.objects.filter(user=user, date__gte=week_ago).aggregate(
+ Sum("commit_num")
+ )["commit_num__sum"]
+ or 0
+ )
+ total_commits = (
GithubModel.objects.filter(user=user).aggregate(Sum("commit_num"))[
"commit_num__sum"
]
or 0
)
- level_up_threshold = 50 * 1.5**user.level
- while user.exp >= level_up_threshold:
- user.level += 1
- user.exp -= level_up_threshold
- level_up_threshold = 50 * 1.5**user.level
+
+ # 7일 평균 커밋 수 계산
+ week_average_commit_count = round(week_commits / 7, 2)
+
+ # 경험치 및 레벨 업데이트
+ user.potato_exp = total_commits
+ level_up_threshold = int(50 * 1.5 ** (user.potato_level - 1))
+ while user.potato_exp >= level_up_threshold:
+ user.potato_level += 1
+ user.potato_exp -= level_up_threshold
+ level_up_threshold = int(50 * 1.5 ** (user.potato_level - 1))
user.save()
# 다음 레벨까지 필요한 경험치 계산
- next_level_exp = 50 * 1.5**user.level - user.exp
+ next_level_exp = int(50 * 1.5 ** (user.potato_level - 1)) - user.potato_exp
# 응답 데이터 생성
commit_statistics = {
- "today_commit_count": today_commit_count,
- "week_commit_count": week_commit_count,
- "total_commit_count": total_commit_count,
+ "today_commit_count": today_commits,
+ "week_commit_count": week_commits,
+ "total_commit_count": total_commits,
"week_average_commit_count": week_average_commit_count,
- "level": user.level,
- "exp": user.exp,
- "next_level_exp": next_level_exp, # 다음 레벨까지 필요한 경험치 추가
+ "level": user.potato_level,
+ "exp": user.potato_exp,
+ "next_level_exp": int(
+ next_level_exp
+ ), # 다음 레벨까지 필요한 경험치 추가
}
return JsonResponse(commit_statistics, safe=False)
From 25c8f4949bd1ef4b45a1845baeb2380c07f67406 Mon Sep 17 00:00:00 2001
From: dayeonkimm
Date: Sun, 4 Aug 2024 22:18:20 +0900
Subject: [PATCH 10/25] =?UTF-8?q?=20permission=5Fclasses=20=3D?=
=?UTF-8?q?=20[AllowAny]=20=EC=B6=94=EA=B0=80?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
potato_project/potato_types/views.py | 3 +++
potato_project/stacks/views.py | 3 +++
2 files changed, 6 insertions(+)
diff --git a/potato_project/potato_types/views.py b/potato_project/potato_types/views.py
index 7836229..0cb5a08 100644
--- a/potato_project/potato_types/views.py
+++ b/potato_project/potato_types/views.py
@@ -2,6 +2,7 @@
from django.db import DatabaseError
from rest_framework import status
from rest_framework.exceptions import ValidationError
+from rest_framework.permissions import AllowAny
from rest_framework.response import Response
from rest_framework.views import APIView
@@ -11,6 +12,8 @@
# 전체 감자 목록 조회
class PotatoesList(APIView):
+ permission_classes = [AllowAny]
+
def get(self, request):
try:
potatoes = PotatoType.objects.all()
diff --git a/potato_project/stacks/views.py b/potato_project/stacks/views.py
index 2295b5b..0f8d617 100644
--- a/potato_project/stacks/views.py
+++ b/potato_project/stacks/views.py
@@ -2,6 +2,7 @@
from django.db import DatabaseError
from rest_framework import status
from rest_framework.exceptions import ValidationError
+from rest_framework.permissions import AllowAny
from rest_framework.response import Response
from rest_framework.views import APIView
@@ -11,6 +12,8 @@
# 전체 스택 조회
class StackList(APIView):
+ permission_classes = [AllowAny]
+
def get(self, request):
try:
stacks = Stack.objects.all()
From 7ff0a43fe0815fa5536d84627d939a6de2a1d559 Mon Sep 17 00:00:00 2001
From: dayeonkimm
Date: Sun, 4 Aug 2024 22:19:08 +0900
Subject: [PATCH 11/25] potato_id -> potato_type_id
---
potato_project/potatoes/views.py | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/potato_project/potatoes/views.py b/potato_project/potatoes/views.py
index 1c13239..4d33f58 100644
--- a/potato_project/potatoes/views.py
+++ b/potato_project/potatoes/views.py
@@ -57,8 +57,8 @@ class PotatoSelectPatch(APIView):
def patch(self, request):
try:
- potato_id = request.data.get("id")
- potato = Potato.objects.get(id=potato_id, user=request.user)
+ potato_type_id = request.data.get("id")
+ potato = Potato.objects.get(potato_type=potato_type_id, user=request.user)
if not potato:
return Response(
From 21b5058fb7718aae449a3e6ffa62df6551c83afd Mon Sep 17 00:00:00 2001
From: dayeonkimm
Date: Sun, 4 Aug 2024 22:20:38 +0900
Subject: [PATCH 12/25] =?UTF-8?q?=20=EC=A3=BC=EC=84=9D=20?=
=?UTF-8?q?=EC=82=AD=EC=A0=9C?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
potato_project/todos/models.py | 1 -
1 file changed, 1 deletion(-)
diff --git a/potato_project/todos/models.py b/potato_project/todos/models.py
index d2d4326..e4ba831 100644
--- a/potato_project/todos/models.py
+++ b/potato_project/todos/models.py
@@ -4,7 +4,6 @@
class Todo(TimeStampedModel):
- # field이름은 _id를 붙이지 않는게 좋다고하네?
user = models.ForeignKey(User, on_delete=models.CASCADE)
task = models.CharField(max_length=50)
is_done = models.BooleanField(default=False)
From 71ec3644c1aa1a942d7665bd0c8f268c8edf84dd Mon Sep 17 00:00:00 2001
From: dayeonkimm
Date: Sun, 4 Aug 2024 22:20:59 +0900
Subject: [PATCH 13/25] =?UTF-8?q?=20=EB=B3=80=EC=88=98=EC=9D=B4?=
=?UTF-8?q?=EB=A6=84=20=EC=88=98=EC=A0=95?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
potato_project/todos/views.py | 9 +++++----
1 file changed, 5 insertions(+), 4 deletions(-)
diff --git a/potato_project/todos/views.py b/potato_project/todos/views.py
index 1048ae8..a6a3598 100644
--- a/potato_project/todos/views.py
+++ b/potato_project/todos/views.py
@@ -20,14 +20,14 @@ def perform_create(self, serializer):
date_str = self.request.data.get("date") # 프론트엔드에서 전달된 날짜 문자열
try:
# datetime 객체 생성
- date_obj = datetime.strptime(date_str, "%Y-%m-%d").date()
+ date = datetime.strptime(date_str, "%Y-%m-%d").date()
except (ValueError, TypeError):
return Response(
{"error": "Invalid date format or missing date."},
status=status.HTTP_400_BAD_REQUEST,
)
- serializer.save(user=self.request.user, date=date_obj)
+ serializer.save(user=self.request.user, date=date)
# 2. 투두리스트 항목 수정 (UI에서 입력 받은 데이터 + 선택된 날짜로 수정)
@@ -46,14 +46,14 @@ def perform_update(self, serializer):
date_str = self.request.data.get("date")
try:
# datetime 객체 생성
- date_obj = datetime.strptime(date_str, "%Y-%m-%d").date()
+ date = datetime.strptime(date_str, "%Y-%m-%d").date()
except (ValueError, TypeError):
return Response(
{"error": "Invalid date format or missing date."},
status=status.HTTP_400_BAD_REQUEST,
)
- serializer.save(date=date_obj)
+ serializer.save(date=date)
# 3. 투두리스트 항목 삭제
@@ -93,6 +93,7 @@ class TodoMarkUndoneView(generics.UpdateAPIView):
def get_object(self):
todo_id = self.kwargs.get("id")
+
return get_object_or_404(Todo, id=todo_id, user=self.request.user)
def get_queryset(self):
From 796d1aa247e5c3d9fafaa435bdc5d0fe8ebd8fe7 Mon Sep 17 00:00:00 2001
From: dayeonkimm
Date: Sun, 4 Aug 2024 22:21:25 +0900
Subject: [PATCH 14/25] =?UTF-8?q?=20=EA=B0=90=EC=9E=90=EB=A0=88?=
=?UTF-8?q?=EB=B2=A8=20=EB=94=94=ED=8F=B4=ED=8A=B8=200=20->=201?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
potato_project/users/models.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/potato_project/users/models.py b/potato_project/users/models.py
index bb7bccb..50e773f 100644
--- a/potato_project/users/models.py
+++ b/potato_project/users/models.py
@@ -59,7 +59,7 @@ class User(AbstractBaseUser, PermissionsMixin, TimeStampedModel):
nickname = models.CharField(max_length=255, null=False)
# 감자 관련 필드
- potato_level = models.PositiveIntegerField(null=False, default=0)
+ potato_level = models.PositiveIntegerField(null=False, default=1)
potato_exp = models.PositiveIntegerField(null=False, default=0)
total_coins = models.PositiveIntegerField(default=0)
From 652b837453c0bbe3674453671759c5e3a923c8b5 Mon Sep 17 00:00:00 2001
From: dayeonkimm
Date: Sun, 4 Aug 2024 22:21:49 +0900
Subject: [PATCH 15/25] =?UTF-8?q?=20api=20=EC=88=98=EC=A0=95?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
potato_project/users/urls.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/potato_project/users/urls.py b/potato_project/users/urls.py
index eaea092..d4ce7d3 100644
--- a/potato_project/users/urls.py
+++ b/potato_project/users/urls.py
@@ -14,7 +14,7 @@
views.CustomTokenRefreshView.as_view(),
name="token_refresh",
),
- path("api/accounts/logout/", views.logout_view, name="logout"),
+ path("api/logout/", views.logout_view, name="logout"),
path("api/accounts/profile/", views.UserDetail.as_view(), name="user_detail"),
path(
"api/accounts/baekjoon_id/",
From 4b59ebc0d3a219f8f560ec46690923650b526d40 Mon Sep 17 00:00:00 2001
From: dayeonkimm
Date: Sun, 4 Aug 2024 22:22:53 +0900
Subject: [PATCH 16/25] =?UTF-8?q?=20=EB=A6=AC=EB=94=94=EB=A0=89?=
=?UTF-8?q?=EC=85=98=20url=20=EC=88=98=EC=A0=95?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
potato_project/users/views.py | 22 +++++++++++++++++-----
1 file changed, 17 insertions(+), 5 deletions(-)
diff --git a/potato_project/users/views.py b/potato_project/users/views.py
index 27785c6..4deb7f9 100644
--- a/potato_project/users/views.py
+++ b/potato_project/users/views.py
@@ -30,10 +30,9 @@
load_dotenv() # .env 파일 로드
-
state = os.environ.get("STATE")
-# BASE_URL = "http://43.201.150.178:8000/"
-BASE_URL = "http://localhost:8000/" # 프론트엔드 URL로 변경해야 함
+BASE_URL = "https://api.gitpotatoes.com/"
+# BASE_URL = "http://localhost:8000"
GITHUB_CALLBACK_URI = BASE_URL + "accounts/github/callback/"
@@ -98,6 +97,7 @@ def github_callback(request):
"https://api.github.com/user",
headers={"Authorization": f"Bearer {access_token}"},
)
+ user_response.encoding = "utf-8"
user_json = user_response.json()
# 에러 처리
@@ -181,7 +181,20 @@ def github_callback(request):
secure=True,
samesite="Lax",
)
- return response
+
+ jwt_access_token = login_data.get("access_token")
+ jwt_refresh_token = login_data.get("refresh_token")
+ user_data = (
+ {
+ "pk": user.pk,
+ "username": user.username,
+ "profile_url": user.profile_url,
+ "nickname": user.nickname,
+ },
+ )
+ redirect_url = f"https://www.gitpotatoes.com/oauth-callback?access_token={jwt_access_token}&refresh_token={jwt_refresh_token}&user={json.dumps(user_data)}"
+ return redirect(redirect_url)
+ # return response
class GithubLogin(SocialLoginView):
@@ -211,7 +224,6 @@ def get_response(self):
"nickname": user.nickname,
},
}
- # return redirect(settings.LOGIN_REDIRECT_URL)
return JsonResponse(response_data)
return response
From 24b6cd3cc0da8a249c78782e42450020b9cb7673 Mon Sep 17 00:00:00 2001
From: DAYEON
Date: Sun, 4 Aug 2024 22:27:20 +0900
Subject: [PATCH 17/25] Update docker-compose.yml
---
docker-compose.yml | 11 -----------
1 file changed, 11 deletions(-)
diff --git a/docker-compose.yml b/docker-compose.yml
index c3e41ee..207bb77 100644
--- a/docker-compose.yml
+++ b/docker-compose.yml
@@ -72,14 +72,3 @@ services:
-
- db: # PostgreSQL Database
- image: postgres:16-alpine
- volumes:
- - ./data/db:/var/lib/postgresql/data
- environment:
- - POSTGRES_DB=${POSTGRES_DB}
- - POSTGRES_USER=${POSTGRES_USER}
- - POSTGRES_PASSWORD=${POSTGRES_PASSWORD}
- env_file:
- - .env
\ No newline at end of file
From f01d0577935a143529836a7926ff830f46e2f64f Mon Sep 17 00:00:00 2001
From: DAYEON
Date: Sun, 4 Aug 2024 22:31:51 +0900
Subject: [PATCH 18/25] =?UTF-8?q?=20csrf=20=EC=84=A4=EC=A0=95=20?=
=?UTF-8?q?=EC=A0=9C=EA=B1=B0?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
potato_project/app/settings.py | 2 --
1 file changed, 2 deletions(-)
diff --git a/potato_project/app/settings.py b/potato_project/app/settings.py
index 7eaac4d..70035c6 100644
--- a/potato_project/app/settings.py
+++ b/potato_project/app/settings.py
@@ -261,5 +261,3 @@
]
SECURE_PROXY_SSL_HEADER = ("HTTP_X_FORWARDED_PROTO", "https")
-CSRF_COOKIE_SECURE = True
-SESSION_COOKIE_SECURE = True
From c42874b6b5abaec8550e2684735ea38e670ac32c Mon Sep 17 00:00:00 2001
From: YoungKwangJoo <164307740+youngkwangjoo@users.noreply.github.com>
Date: Mon, 5 Aug 2024 23:57:43 +0900
Subject: [PATCH 19/25] Update readme.md
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
tree 추가
---
readme.md | 245 ++++++++++++++++++++++++++++++++++++++----------------
1 file changed, 175 insertions(+), 70 deletions(-)
diff --git a/readme.md b/readme.md
index d66e6fd..d7a44a0 100644
--- a/readme.md
+++ b/readme.md
@@ -72,76 +72,181 @@
## 4. 프로젝트 구조
```
-.
-├── README.md
-├── package-lock.json
-├── package.json
-├── src
-│ ├── App.jsx
-│ ├── apis
-│ │ ├── api
-│ │ │ ├── attendance.js
-│ │ │ ├── auth.js
-│ │ │ ├── baekjoon.js
-│ │ │ ├── github.js
-│ │ │ ├── potato.js
-│ │ │ ├── stack.js
-│ │ │ └── todo.js
-│ │ ├── services
-│ │ │ ├── authService.js
-│ │ │ ├── calendarService.js
-│ │ │ ├── levelService.js
-│ │ │ ├── settingPageService.js
-│ │ │ ├── stackService.js
-│ │ │ ├── todoService.js
-│ │ │ └── userUpdateService.js
-│ │ └── utils
-│ │ └── instance.js
-│ ├── assets
-│ │ ├── description.json
-│ │ └── images
-│ ├── components
-│ │ ├── common
-│ │ │ ├── alert
-│ │ │ ├── input
-│ │ │ └── loading
-│ │ ├── layout
-│ │ │ ├── footer
-│ │ │ └── header
-│ │ ├── modal
-│ │ │ ├── BaekjoonConnectModal.jsx
-│ │ │ ├── ChangePotatoModal.jsx
-│ │ │ ├── PotatoInfoModal.jsx
-│ │ │ ├── UserUpdateModal.jsx
-│ │ │ └── index.js
-│ │ └── shared
-│ │ ├── calendar
-│ │ ├── collection
-│ │ ├── info
-│ │ ├── level
-│ │ ├── potato
-│ │ ├── stack
-│ │ └── todo
-│ ├── hooks
-│ │ └── useCalendar
-│ ├── lib
-│ ├── main.jsx
-│ ├── pages
-│ │ ├── home
-│ │ ├── landing
-│ │ ├── oauthCallback
-│ │ ├── setting
-│ │ └── signin
-│ ├── store
-│ │ ├── dateStore.js
-│ │ ├── todosCompleteStore.js
-│ │ └── userStore.js
-│ ├── styles
-│ │ └── global.css
-│ └── utils
-│ └── storage.js
-├── tailwind.config.js
-└── vite.config.js
+potato_project
+├── app
+│ ├── __init__.py
+│ ├── __pycache__
+│ ├── asgi.py
+│ ├── settings.py
+│ ├── urls.py
+│ └── wsgi.py
+├── attendances
+│ ├── __init__.py
+│ ├── __pycache__
+│ ├── admin.py
+│ ├── apps.py
+│ │ ├── 0001_initial.py
+│ │ ├── 0002_initial.py
+│ │ ├── __init__.py
+│ │ └── __pycache__
+│ ├── models.py
+│ ├── serializers.py
+│ ├── tests.py
+│ ├── urls.py
+│ └── views.py
+├── baekjoons
+│ ├── __init__.py
+│ ├── __pycache__
+│ ├── admin.py
+│ ├── apps.py
+│ │ ├── 0001_initial.py
+│ │ ├── 0002_initial.py
+│ │ ├── __init__.py
+│ │ └── __pycache__
+│ ├── models.py
+│ ├── tests.py
+│ ├── urls.py
+│ └── views.py
+├── common
+│ ├── __init__.py
+│ ├── __pycache__
+│ ├── admin.py
+│ ├── apps.py
+│ │ ├── __init__.py
+│ │ └── __pycache__
+│ ├── models.py
+│ ├── tests.py
+│ └── views.py
+├── core
+│ ├── __init__.py
+│ ├── __pycache__
+│ ├── admin.py
+│ ├── apps.py
+│ ├── management
+│ │ ├── __init__.py
+│ │ ├── __pycache__
+│ │ └── commands
+│ │ ├── __init__.py
+│ │ ├── __pycache__
+│ │ └── wait_for_db.py
+│ │ ├── __init__.py
+│ │ └── __pycache__
+│ ├── models.py
+│ ├── tests.py
+│ └── views.py
+├── githubs
+│ ├── __init__.py
+│ ├── __pycache__
+│ ├── admin.py
+│ ├── apps.py
+│ │ ├── 0001_initial.py
+│ │ ├── 0002_initial.py
+│ │ ├── 0003_alter_github_date.py
+│ │ ├── __init__.py
+│ │ └── __pycache__
+│ ├── models.py
+│ ├── signals.py
+│ ├── test
+│ │ ├── __init__.py
+│ │ └── tests.py
+│ ├── urls.py
+│ └── views.py
+├── manage.py
+├── potato_types
+│ ├── __init__.py
+│ ├── __pycache__
+│ ├── actions.py
+│ ├── admin.py
+│ ├── apps.py
+│ │ ├── 0001_initial.py
+│ │ ├── 0002_add_initial_data.py
+│ │ ├── 0003_alter_potatotype_options.py
+│ │ ├── 0003_remove_potatotype_potato_image.py
+│ │ ├── 0004_merge_20240730_0318.py
+│ │ ├── __init__.py
+│ │ └── __pycache__
+│ ├── models.py
+│ ├── serializers.py
+│ ├── tests.py
+│ ├── urls.py
+│ └── views.py
+├── potatoes
+│ ├── __init__.py
+│ ├── __pycache__
+│ ├── admin.py
+│ ├── apps.py
+│ │ ├── 0001_initial.py
+│ │ ├── 0002_initial.py
+│ │ ├── 0003_rename_potato_type_id_potato_potato_type.py
+│ │ ├── __init__.py
+│ │ └── __pycache__
+│ ├── models.py
+│ ├── serializers.py
+│ ├── tests.py
+│ ├── urls.py
+│ └── views.py
+├── stacks
+│ ├── __init__.py
+│ ├── __pycache__
+│ ├── admin.py
+│ ├── apps.py
+│ │ ├── 0001_initial.py
+│ │ ├── 0001_initial.py.save
+│ │ ├── 0002_add_initial_stacks.py
+│ │ ├── __init__.py
+│ │ └── __pycache__
+│ ├── models.py
+│ ├── serializers.py
+│ ├── tests.py
+│ ├── urls.py
+│ ├── views.py
+│ └── views.py.save
+├── todos
+│ ├── __init__.py
+│ ├── __pycache__
+│ ├── admin.py
+│ ├── apps.py
+│ │ ├── 0001_initial.py
+│ │ ├── 0002_initial.py
+│ │ ├── 0003_alter_todo_date.py
+│ │ ├── __init__.py
+│ │ └── __pycache__
+│ ├── models.py
+│ ├── serializers.py
+│ ├── tests.py
+│ ├── urls.py
+│ └── views.py
+├── user_stacks
+│ ├── __init__.py
+│ ├── __pycache__
+│ ├── admin.py
+│ ├── apps.py
+│ │ ├── 0001_initial.py
+│ │ ├── 0002_initial.py
+│ │ ├── __init__.py
+│ │ └── __pycache__
+│ ├── models.py
+│ ├── serializers.py
+│ ├── tests.py
+│ ├── urls.py
+│ └── views.py
+└── users
+ ├── __init__.py
+ ├── __pycache__
+ ├── admin.py
+ ├── apps.py
+ │ ├── 0001_initial.py
+ │ ├── 0002_alter_user_potato_level.py
+ │ ├── __init__.py
+ │ └── __pycache__
+ ├── models.py
+ ├── serializers.py
+ ├── signals.py
+ ├── tests.py
+ ├── urls.py
+ ├── views.py
+ ├── views.py.save
+ └── views.py.save.1
```
## 5. 프로젝트
From ae196e11c68e14a2feb7d56b91501b7c985277c1 Mon Sep 17 00:00:00 2001
From: dayeonkimm
Date: Tue, 13 Aug 2024 00:22:28 +0900
Subject: [PATCH 20/25] =?UTF-8?q?=20=EC=B5=9C=EC=A2=85=20main=20?=
=?UTF-8?q?=EC=88=98=EC=A0=95?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
potato_project/app/settings.py | 9 +-
potato_project/githubs/models.py | 2 +-
potato_project/githubs/signals.py | 170 +++++++++++++++++-------------
potato_project/githubs/views.py | 16 ++-
potato_project/potatoes/views.py | 1 -
potato_project/users/signals.py | 13 ++-
6 files changed, 125 insertions(+), 86 deletions(-)
diff --git a/potato_project/app/settings.py b/potato_project/app/settings.py
index 7eaac4d..579c0fc 100644
--- a/potato_project/app/settings.py
+++ b/potato_project/app/settings.py
@@ -217,8 +217,6 @@
DEFAULT_CHARSET = "utf-8"
-DEFAULT_CHARSET = "utf-8"
-
LOGGING = {
"version": 1,
"disable_existing_loggers": False,
@@ -236,8 +234,8 @@
# CORS_ORIGIN_WHITELIST = ['http://localhost:5173', 'http://127.0.0.1:5173', 'https://www.gitpotatoes.com',] # 특정 Origin만 허용
CORS_ALLOWED_ORIGINS = [
"https://www.gitpotatoes.com", # 실제 배포 프론트엔드 URL
- "http://localhost:5173", # 프론트엔드 로컬 서버 URL
- "http://127.0.0.1:5173", # 프론트엔드 로컬 서버 URL
+ # 'http://localhost:5173', # 프론트엔드 로컬 서버 URL
+ # 'http://127.0.0.1:5173', # 프론트엔드 로컬 서버 URL
]
CORS_ALLOW_CREDENTIALS = True # 쿠키 등 credential 정보 허용
CORS_ALLOW_METHODS = [
@@ -260,6 +258,3 @@
"x-requested-with",
]
SECURE_PROXY_SSL_HEADER = ("HTTP_X_FORWARDED_PROTO", "https")
-
-CSRF_COOKIE_SECURE = True
-SESSION_COOKIE_SECURE = True
diff --git a/potato_project/githubs/models.py b/potato_project/githubs/models.py
index ba83439..894e14e 100644
--- a/potato_project/githubs/models.py
+++ b/potato_project/githubs/models.py
@@ -8,7 +8,7 @@
class Github(TimeStampedModel):
user = models.ForeignKey(User, on_delete=models.CASCADE, verbose_name="User_id")
commit_num = models.BigIntegerField(verbose_name="Commit Number")
- date = models.DateField(default=timezone.now)
+ date = models.DateField()
def __str__(self):
return f"{self.date}-{self.commit_num}"
diff --git a/potato_project/githubs/signals.py b/potato_project/githubs/signals.py
index 78467e8..63c04a7 100644
--- a/potato_project/githubs/signals.py
+++ b/potato_project/githubs/signals.py
@@ -7,11 +7,10 @@
@receiver(post_save, sender=Github)
-def get_winter_potato(sender, instance, created, **kwargs):
- # 새 Github 데이터가 생성 or 업데이트, 날짜가 크리스마스이며, commit_num이 1 이상인 경우에만 실행
+def get_winter_potato(sender, instance, **kwargs):
+ # 새 Github 데이터가 생성 or 업데이트, 날짜가 크리스마스이며, commit_num이 >
if (
- created
- and instance.commit_num >= 1
+ instance.commit_num >= 1
and instance.date.month == 12
and instance.date.day == 25
): # 월과 일만 비교
@@ -27,10 +26,9 @@ def get_winter_potato(sender, instance, created, **kwargs):
@receiver(post_save, sender=Github)
-def get_ghost_potato(sender, instance, created, **kwargs):
+def get_ghost_potato(sender, instance, **kwargs):
if (
- created
- and instance.commit_num >= 1
+ instance.commit_num >= 1
and instance.date.month == 10
and instance.date.day == 31
):
@@ -44,79 +42,109 @@ def get_ghost_potato(sender, instance, created, **kwargs):
@receiver(post_save, sender=Github)
-def get_crystal_potato(sender, instance, created, **kwargs):
- if created and instance.commit_num >= 1:
+def get_crystal_potato(sender, instance, **kwargs):
+ if instance.commit_num >= 1:
# 30일 전 날짜 계산
- thirty_days_ago = instance.date.date() - timedelta(days=30)
+ thirty_days_ago = instance.date - timedelta(days=30)
- # 30일 연속 커밋 여부 확인
- commits_in_30_days = (
- Github.objects.filter(
- user=instance.user,
- date__gte=thirty_days_ago,
- date__lte=instance.date.date(),
- commit_num__gte=1,
- )
- .values("date")
- .distinct()
- .count()
+ # 30일치 데이터가 있는지 확인
+ oldest_record = (
+ Github.objects.filter(user=instance.user).order_by("date").first()
)
+ if oldest_record and (instance.date - oldest_record.date).days >= 30:
+ # 30일 연속 커밋 여부 확인
+ commits_in_30_days = (
+ Github.objects.filter(
+ user=instance.user,
+ date__gte=thirty_days_ago,
+ date__lte=instance.date,
+ commit_num__gte=1,
+ )
+ .values("date")
+ .distinct()
+ .count()
+ )
- if commits_in_30_days == 30:
- try:
- potato = Potato.objects.get(user=instance.user, potato_type_id=8)
- if not potato.is_acquired:
- potato.is_acquired = True
- potato.save()
- except Potato.DoesNotExist:
- pass
+ if commits_in_30_days == 30:
+ try:
+ potato = Potato.objects.get(user=instance.user, potato_type_id=8)
+ if not potato.is_acquired:
+ potato.is_acquired = True
+ potato.save()
+ except Potato.DoesNotExist:
+ pass
+ else:
+ # 30일치 데이터가 없는 경우 로그 남기기 또는 다른 처리
+ print(
+ f"Not enough data for user {instance.user.id}. Oldest record date: {oldest_record.date if oldest_record else 'No records'}"
+ )
@receiver(post_save, sender=Github)
-def get_dirty_potato(sender, instance, created, **kwargs):
- if created:
+def get_dirty_potato(sender, instance, **kwargs):
+ if instance.commit_num == 0:
# 30일 전 날짜 계산
- thirty_days_ago = instance.date.date() - timedelta(days=30)
-
- # 30일 동안 커밋이 있었는지 확인
- any_commits_in_30_days = Github.objects.filter(
- user=instance.user,
- date__gte=thirty_days_ago,
- date__lte=instance.date.date(),
- commit_num__gte=1,
- ).exists()
-
- if not any_commits_in_30_days:
- # 30일 연속 커밋이 없는 경우 감자 아이디 9 획득 로직 실행
- try:
- potato = Potato.objects.get(user=instance.user, potato_type_id=9)
- if not potato.is_acquired:
- potato.is_acquired = True
- potato.save()
- except Potato.DoesNotExist:
- pass # 필요에 따라 에러 처리 추가
+ thirty_days_ago = instance.date - timedelta(days=30)
+
+ # 30일치 데이터가 있는지 확인
+ oldest_record = (
+ Github.objects.filter(user=instance.user).order_by("date").first()
+ )
+ if oldest_record and (instance.date - oldest_record.date).days >= 30:
+ # 30일 동안 커밋이 있었는지 확인
+ any_commits_in_30_days = Github.objects.filter(
+ user=instance.user,
+ date__gte=thirty_days_ago,
+ date__lte=instance.date,
+ commit_num__gte=1,
+ ).exists()
+
+ if not any_commits_in_30_days:
+ # 30일 연속 커밋이 없는 경우 감자 아이디 9 획득 로직 실행
+ try:
+ potato = Potato.objects.get(user=instance.user, potato_type_id=9)
+ if not potato.is_acquired:
+ potato.is_acquired = True
+ potato.save()
+ except Potato.DoesNotExist:
+ pass # 필요에 따라 에러 처리 추가
+ else:
+ # 30일치 데이터가 없는 경우 로그 남기기 또는 다른 처리
+ print(
+ f"Not enough data for user {instance.user.id}. Oldest record date: {oldest_record.date if oldest_record else 'No records'}"
+ )
@receiver(post_save, sender=Github)
-def get_green_potato(sender, instance, created, **kwargs):
- if created:
+def get_green_potato(sender, instance, **kwargs):
+ if instance.commit_num == 0:
# 90일 전 날짜 계산
- ninety_days_ago = instance.date.date() - timedelta(days=90)
-
- # 90일 동안 커밋이 있었는지 확인
- any_commits_in_90_days = Github.objects.filter(
- user=instance.user,
- date__gte=ninety_days_ago,
- date__lte=instance.date.date(),
- commit_num__gte=1,
- ).exists()
-
- if not any_commits_in_90_days:
- # 90일 연속 커밋이 없는 경우 감자 아이디 10 획득 로직 실행
- try:
- potato = Potato.objects.get(user=instance.user, potato_type_id=10)
- if not potato.is_acquired:
- potato.is_acquired = True
- potato.save()
- except Potato.DoesNotExist:
- pass # 필요에 따라 에러 처리 추가
+ ninety_days_ago = instance.date - timedelta(days=90)
+
+ # 90일치 데이터가 있는지 확인
+ oldest_record = (
+ Github.objects.filter(user=instance.user).order_by("date").first()
+ )
+ if oldest_record and (instance.date - oldest_record.date).days >= 90:
+ # 90일 동안 커밋이 있었는지 확인
+ any_commits_in_90_days = Github.objects.filter(
+ user=instance.user,
+ date__gte=ninety_days_ago,
+ date__lte=instance.date,
+ commit_num__gte=1,
+ ).exists()
+
+ if not any_commits_in_90_days:
+ # 90일 연속 커밋이 없는 경우 감자 아이디 10 획득 로직 실행
+ try:
+ potato = Potato.objects.get(user=instance.user, potato_type_id=10)
+ if not potato.is_acquired:
+ potato.is_acquired = True
+ potato.save()
+ except Potato.DoesNotExist:
+ pass # 필요에 따라 에러 처리 추가
+ else:
+ # 90일치 데이터가 없는 경우 로그 남기기 또는 다른 처리
+ print(
+ f"Not enough data for user {instance.user.id}. Oldest record date: {oldest_record.date if oldest_record else 'No records'}"
+ )
diff --git a/potato_project/githubs/views.py b/potato_project/githubs/views.py
index 53a6589..71becdb 100644
--- a/potato_project/githubs/views.py
+++ b/potato_project/githubs/views.py
@@ -1,5 +1,6 @@
from datetime import datetime, timedelta
+import pytz
import requests
from django.db.models import Avg, Sum
from django.http import JsonResponse
@@ -92,9 +93,17 @@ def get(self, request):
)
if commits is not None:
for commit in commits:
- commit_date = datetime.strptime(
- commit["commit"]["author"]["date"], "%Y-%m-%dT%H:%M:%SZ"
- ).date()
+ commit_date = (
+ timezone.make_aware(
+ datetime.strptime(
+ commit["commit"]["author"]["date"],
+ "%Y-%m-%dT%H:%M:%SZ",
+ ),
+ timezone=pytz.UTC,
+ )
+ .astimezone(timezone.get_current_timezone())
+ .date()
+ )
if commit_date == today:
today_commits += 1
@@ -121,6 +130,7 @@ def get(self, request):
# 경험치 및 레벨 업데이트
user.potato_exp = total_commits
+ user.potato_level = 1
level_up_threshold = int(50 * 1.5 ** (user.potato_level - 1))
while user.potato_exp >= level_up_threshold:
user.potato_level += 1
diff --git a/potato_project/potatoes/views.py b/potato_project/potatoes/views.py
index 4d33f58..96d0078 100644
--- a/potato_project/potatoes/views.py
+++ b/potato_project/potatoes/views.py
@@ -10,7 +10,6 @@
from .serializers import PotatoSerializer
-# 유저의 포테이토가 다가지고있지, 획득을 못햇던 햇던, 유저가감자를 획득했는지, 대표이미지 설정했는지.
# 유저의 감자 조회
class MyPotatoDetail(APIView):
permission_classes = [IsAuthenticated]
diff --git a/potato_project/users/signals.py b/potato_project/users/signals.py
index 3fc6bb5..57f9f84 100644
--- a/potato_project/users/signals.py
+++ b/potato_project/users/signals.py
@@ -9,10 +9,11 @@ def get_level_two_potato(sender, instance, **kwargs):
# 레벨이 2로 변경되었고, 이전 레벨이 2가 아닐 때만 실행
if (
instance.potato_level == 2
+ and instance.tracker.has_changed('potato_level')
and instance.tracker.previous("potato_level") != 2
and not kwargs.get("created", False)
):
- try:
+ try:
# potato_type_id=2인 감자 조회
potato = Potato.objects.get(user=instance.user, potato_type_id=2)
if not potato.is_acquired:
@@ -23,10 +24,12 @@ def get_level_two_potato(sender, instance, **kwargs):
pass
+
@receiver(post_save, sender=User)
def get_level_three_potato(sender, instance, **kwargs):
if (
instance.potato_level == 3
+ and instance.tracker.has_changed('potato_level')
and instance.tracker.previous("potato_level") != 3
and not kwargs.get("created", False)
):
@@ -44,9 +47,10 @@ def get_level_four_potato(sender, instance, **kwargs):
if (
instance.potato_level == 4
and instance.tracker.previous("potato_level") != 4
+ and instance.tracker.has_changed('potato_level')
and not kwargs.get("created", False)
):
- try:
+ try:
potato = Potato.objects.get(user=instance.user, potato_type_id=4)
if not potato.is_acquired:
potato.is_acquired = True
@@ -55,17 +59,20 @@ def get_level_four_potato(sender, instance, **kwargs):
pass
+
@receiver(post_save, sender=User)
def get_level_five_potato(sender, instance, **kwargs):
if (
instance.potato_level == 5
+ and instance.tracker.has_changed('potato_level')
and instance.tracker.previous("potato_level") != 5
and not kwargs.get("created", False)
):
- try:
+ try:
potato = Potato.objects.get(user=instance.user, potato_type_id=5)
if not potato.is_acquired:
potato.is_acquired = True
potato.save()
except Potato.DoesNotExist:
pass
+
From 6faa74963e697d2fdd0df4abb26038c5a42cefcd Mon Sep 17 00:00:00 2001
From: DAYEON
Date: Tue, 13 Aug 2024 00:37:19 +0900
Subject: [PATCH 21/25] Update readme.md
---
readme.md | 7 +++----
1 file changed, 3 insertions(+), 4 deletions(-)
diff --git a/readme.md b/readme.md
index f6195ef..b33d976 100644
--- a/readme.md
+++ b/readme.md
@@ -245,9 +245,7 @@ potato_project
├── signals.py
├── tests.py
├── urls.py
- ├── views.py
- ├── views.py.save
- └── views.py.save.1
+ └── views.py
```
## 5. 프로젝트
@@ -295,8 +293,9 @@ GitHub와 백준 활동으로 성장하는 감자 캐릭터를 키우며 생산
- 사용자 스택 조회, 수정, 업데이트
- 캘린더 조회
- Todo 조회, 추가, 수정, 삭제
-- 회원가입$
+- 회원가입
- 소셜 로그인, 깃허브, 백준 연동
+- 로그아웃, 회원 탈퇴 (추가 예정)
- 테스트 코드 (추가 예정)
- 감자 코인 (추가 예정)
- 감자 상점 (추가 예정)
From 5bf4e77f0fe1cdce9d0f2f7e7962ada43b1073ac Mon Sep 17 00:00:00 2001
From: dayeonkimm
Date: Fri, 20 Sep 2024 11:26:21 +0900
Subject: [PATCH 22/25] =?UTF-8?q?=EC=8B=9C=EA=B7=B8=EB=84=90=20=EC=88=98?=
=?UTF-8?q?=EC=A0=95?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
potato_project/githubs/apps.py | 3 +++
potato_project/todos/views.py | 7 +++----
potato_project/users/apps.py | 3 +++
3 files changed, 9 insertions(+), 4 deletions(-)
diff --git a/potato_project/githubs/apps.py b/potato_project/githubs/apps.py
index b3180a3..8f32ed0 100644
--- a/potato_project/githubs/apps.py
+++ b/potato_project/githubs/apps.py
@@ -4,3 +4,6 @@
class GithubsConfig(AppConfig):
default_auto_field = "django.db.models.BigAutoField"
name = "githubs"
+
+ def ready(self):
+ import githubs.signals
diff --git a/potato_project/todos/views.py b/potato_project/todos/views.py
index 6a1b581..b614e8a 100644
--- a/potato_project/todos/views.py
+++ b/potato_project/todos/views.py
@@ -27,7 +27,7 @@ def perform_create(self, serializer):
status=status.HTTP_400_BAD_REQUEST,
)
- serializer.save(user=self.request.user, date=date_obj)
+ serializer.save(user=self.request.user, date=date)
# 2. 투두리스트 항목 수정 (UI에서 입력 받은 데이터 + 선택된 날짜로 수정)
@@ -50,10 +50,9 @@ def perform_update(self, serializer):
except (ValueError, TypeError):
return Response(
{"error": "Invalid date format or missing date."},
- status=status.HTTP_400_BAD_REQUEST,
- )
+ status=status.HTTP_400_BAD_REQUEST,)
- serializer.save(date=date_obj)
+ serializer.save(date=date)
# 3. 투두리스트 항목 삭제
diff --git a/potato_project/users/apps.py b/potato_project/users/apps.py
index 88f7b17..7e511c4 100644
--- a/potato_project/users/apps.py
+++ b/potato_project/users/apps.py
@@ -4,3 +4,6 @@
class UsersConfig(AppConfig):
default_auto_field = "django.db.models.BigAutoField"
name = "users"
+
+ def ready(self):
+ import users.signals
From f409e28d01a97f1731ff3718c87ffcac5175f353 Mon Sep 17 00:00:00 2001
From: dayeonkimm
Date: Fri, 20 Sep 2024 11:40:48 +0900
Subject: [PATCH 23/25] isort, black
---
potato_project/githubs/apps.py | 2 +-
potato_project/todos/views.py | 3 ++-
potato_project/users/apps.py | 2 +-
3 files changed, 4 insertions(+), 3 deletions(-)
diff --git a/potato_project/githubs/apps.py b/potato_project/githubs/apps.py
index 8f32ed0..e012887 100644
--- a/potato_project/githubs/apps.py
+++ b/potato_project/githubs/apps.py
@@ -4,6 +4,6 @@
class GithubsConfig(AppConfig):
default_auto_field = "django.db.models.BigAutoField"
name = "githubs"
-
+
def ready(self):
import githubs.signals
diff --git a/potato_project/todos/views.py b/potato_project/todos/views.py
index b614e8a..a6a3598 100644
--- a/potato_project/todos/views.py
+++ b/potato_project/todos/views.py
@@ -50,7 +50,8 @@ def perform_update(self, serializer):
except (ValueError, TypeError):
return Response(
{"error": "Invalid date format or missing date."},
- status=status.HTTP_400_BAD_REQUEST,)
+ status=status.HTTP_400_BAD_REQUEST,
+ )
serializer.save(date=date)
diff --git a/potato_project/users/apps.py b/potato_project/users/apps.py
index 7e511c4..4697735 100644
--- a/potato_project/users/apps.py
+++ b/potato_project/users/apps.py
@@ -4,6 +4,6 @@
class UsersConfig(AppConfig):
default_auto_field = "django.db.models.BigAutoField"
name = "users"
-
+
def ready(self):
import users.signals
From e6bc18971d74bc81b21f8c058d285274bba83d8f Mon Sep 17 00:00:00 2001
From: dayeonkimm
Date: Fri, 20 Sep 2024 11:58:37 +0900
Subject: [PATCH 24/25] =?UTF-8?q?=EC=98=A4=EB=A5=98=20=EC=88=98=EC=A0=95?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
potato_project/todos/views.py | 9 +++------
1 file changed, 3 insertions(+), 6 deletions(-)
diff --git a/potato_project/todos/views.py b/potato_project/todos/views.py
index a6a3598..ea0454d 100644
--- a/potato_project/todos/views.py
+++ b/potato_project/todos/views.py
@@ -4,6 +4,7 @@
from django.shortcuts import get_object_or_404
from django.utils import timezone
from rest_framework import generics, permissions, status
+from rest_framework.exceptions import ValidationError
from rest_framework.permissions import IsAuthenticated
from rest_framework.response import Response
@@ -47,13 +48,9 @@ def perform_update(self, serializer):
try:
# datetime 객체 생성
date = datetime.strptime(date_str, "%Y-%m-%d").date()
+ serializer.save(date=date) # serializer에 날짜 저장
except (ValueError, TypeError):
- return Response(
- {"error": "Invalid date format or missing date."},
- status=status.HTTP_400_BAD_REQUEST,
- )
-
- serializer.save(date=date)
+ raise ValidationError({"error": "Invalid date format or missing date."})
# 3. 투두리스트 항목 삭제
From 1576df972349736aa81abae2cbb067a43c9a9bf1 Mon Sep 17 00:00:00 2001
From: dayeonkimm
Date: Fri, 20 Sep 2024 18:03:42 +0900
Subject: [PATCH 25/25] =?UTF-8?q?=EC=98=A4=EB=A5=98=20=EC=88=98=EC=A0=95?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
docker-compose.yml | 13 ++----
potato_project/users/signals.py | 79 ++++++++++++++++++++-------------
requirements.txt | 2 +
3 files changed, 55 insertions(+), 39 deletions(-)
diff --git a/docker-compose.yml b/docker-compose.yml
index 207bb77..380cbf8 100644
--- a/docker-compose.yml
+++ b/docker-compose.yml
@@ -18,16 +18,14 @@ services:
python manage.py migrate &&
python manage.py runserver --noreload 0.0.0.0:8000"
environment:
- - DB_HOST=${DB_HOST}
- - DB_NAME=${DB_NAME}
- - DB_USER=${DB_USER}
- - DB_PASSWORD=${DB_PASSWORD}
+ - DB_HOST=${RDS_HOSTNAME}
+ - DB_NAME=${RDS_DB_NAME}
+ - DB_USER=${RDS_USERNAME}
+ - DB_PASSWORD=${RDS_PASSWORD}
- PYDEVD_DISABLE_FILE_VALIDATION=1
env_file:
- .env
-
-
# 개발용
# # version: "3.11"
@@ -69,6 +67,3 @@ services:
# - POSTGRES_PASSWORD=${POSTGRES_PASSWORD}
# env_file:
# - .env
-
-
-
diff --git a/potato_project/users/signals.py b/potato_project/users/signals.py
index 57f9f84..d4fc90c 100644
--- a/potato_project/users/signals.py
+++ b/potato_project/users/signals.py
@@ -5,17 +5,21 @@
@receiver(post_save, sender=User)
-def get_level_two_potato(sender, instance, **kwargs):
+def get_level_two_potato(sender, instance, created, **kwargs):
+ if created:
+ return
+
+ # 이전 인스턴스 재조회
+ previous_instance = User.objects.get(pk=instance.pk)
+
# 레벨이 2로 변경되었고, 이전 레벨이 2가 아닐 때만 실행
if (
- instance.potato_level == 2
- and instance.tracker.has_changed('potato_level')
- and instance.tracker.previous("potato_level") != 2
- and not kwargs.get("created", False)
+ previous_instance.potato_level != instance.potato_level
+ and instance.potato_level == 2
):
- try:
+ try:
# potato_type_id=2인 감자 조회
- potato = Potato.objects.get(user=instance.user, potato_type_id=2)
+ potato = Potato.objects.get(user=instance, potato_type_id=2)
if not potato.is_acquired:
potato.is_acquired = True
potato.save()
@@ -24,17 +28,22 @@ def get_level_two_potato(sender, instance, **kwargs):
pass
-
@receiver(post_save, sender=User)
-def get_level_three_potato(sender, instance, **kwargs):
+def get_level_three_potato(sender, instance, created, **kwargs):
+ if created:
+ return
+
+ # 이전 인스턴스 재조회
+ previous_instance = User.objects.get(pk=instance.pk)
+
+ # 레벨이 3로 변경되었고, 이전 레벨이 3가 아닐 때만 실행
if (
- instance.potato_level == 3
- and instance.tracker.has_changed('potato_level')
- and instance.tracker.previous("potato_level") != 3
- and not kwargs.get("created", False)
+ previous_instance.potato_level != instance.potato_level
+ and instance.potato_level == 3
):
try:
- potato = Potato.objects.get(user=instance.user, potato_type_id=3)
+ # potato_type_id=3인 감자 조회
+ potato = Potato.objects.get(user=instance, potato_type_id=3)
if not potato.is_acquired:
potato.is_acquired = True
potato.save()
@@ -43,15 +52,21 @@ def get_level_three_potato(sender, instance, **kwargs):
@receiver(post_save, sender=User)
-def get_level_four_potato(sender, instance, **kwargs):
+def get_level_four_potato(sender, instance, created, **kwargs):
+ if created:
+ return
+
+ # 이전 인스턴스 재조회
+ previous_instance = User.objects.get(pk=instance.pk)
+
+ # 레벨이 4로 변경되었고, 이전 레벨이 4가 아닐 때만 실행
if (
- instance.potato_level == 4
- and instance.tracker.previous("potato_level") != 4
- and instance.tracker.has_changed('potato_level')
- and not kwargs.get("created", False)
+ previous_instance.potato_level != instance.potato_level
+ and instance.potato_level == 4
):
- try:
- potato = Potato.objects.get(user=instance.user, potato_type_id=4)
+ try:
+ # potato_type_id=4인 감자 조회
+ potato = Potato.objects.get(user=instance, potato_type_id=4)
if not potato.is_acquired:
potato.is_acquired = True
potato.save()
@@ -59,20 +74,24 @@ def get_level_four_potato(sender, instance, **kwargs):
pass
-
@receiver(post_save, sender=User)
-def get_level_five_potato(sender, instance, **kwargs):
+def get_level_five_potato(sender, instance, created, **kwargs):
+ if created:
+ return
+
+ # 이전 인스턴스 재조회
+ previous_instance = User.objects.get(pk=instance.pk)
+
+ # 레벨이 5로 변경되었고, 이전 레벨이 5가 아닐 때만 실행
if (
- instance.potato_level == 5
- and instance.tracker.has_changed('potato_level')
- and instance.tracker.previous("potato_level") != 5
- and not kwargs.get("created", False)
+ previous_instance.potato_level != instance.potato_level
+ and instance.potato_level == 5
):
- try:
- potato = Potato.objects.get(user=instance.user, potato_type_id=5)
+ try:
+ # potato_type_id=5인 감자 조회
+ potato = Potato.objects.get(user=instance, potato_type_id=5)
if not potato.is_acquired:
potato.is_acquired = True
potato.save()
except Potato.DoesNotExist:
pass
-
diff --git a/requirements.txt b/requirements.txt
index 5dfcc9a..afeb782 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -18,3 +18,5 @@ pytest
pytest-django
PyGithub>=1.55
+pytz
+