diff --git a/codes/__init__.py b/codes/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/codes/admin.py b/codes/admin.py new file mode 100644 index 0000000..8c38f3f --- /dev/null +++ b/codes/admin.py @@ -0,0 +1,3 @@ +from django.contrib import admin + +# Register your models here. diff --git a/codes/apps.py b/codes/apps.py new file mode 100644 index 0000000..5238a21 --- /dev/null +++ b/codes/apps.py @@ -0,0 +1,6 @@ +from django.apps import AppConfig + + +class CodesConfig(AppConfig): + default_auto_field = 'django.db.models.BigAutoField' + name = 'codes' diff --git a/codes/models.py b/codes/models.py new file mode 100644 index 0000000..b95593f --- /dev/null +++ b/codes/models.py @@ -0,0 +1,19 @@ +from django.db import models + +from common.models.baseModels import BaseModel +from common.models.choiceModels import CertificateCodeUseType, InviteCodeUseType +from common.utils.codeManger import set_expire + + +class CertificationCode(BaseModel): + use_type = models.CharField(choices=CertificateCodeUseType.choices, max_length=5) + code = models.CharField(max_length=6) + expire_at = models.DateTimeField(default=set_expire(minutes=5)) + is_used = models.BooleanField(default=False) + identifier = models.CharField(max_length=40) + +class InviteCode(BaseModel): + use_type = models.CharField(choices=InviteCodeUseType.choices, max_length=5) + code = models.CharField(max_length=10) + expire_at = models.DateTimeField(default=set_expire(minutes=10080)) # 일주일은 10080분 + identifier = models.CharField(max_length=40) diff --git a/codes/tests.py b/codes/tests.py new file mode 100644 index 0000000..7ce503c --- /dev/null +++ b/codes/tests.py @@ -0,0 +1,3 @@ +from django.test import TestCase + +# Create your tests here. diff --git a/codes/views.py b/codes/views.py new file mode 100644 index 0000000..91ea44a --- /dev/null +++ b/codes/views.py @@ -0,0 +1,3 @@ +from django.shortcuts import render + +# Create your views here. diff --git a/common/models/baseModels.py b/common/models/baseModels.py new file mode 100644 index 0000000..e89718e --- /dev/null +++ b/common/models/baseModels.py @@ -0,0 +1,17 @@ +from django.db import models + +from common.utils.codeManger import generate_ulid + + +class BaseModel(models.Model): + id = models.CharField( + max_length=26, + primary_key=True, + default=generate_ulid, + editable=False + ) + created_at = models.DateTimeField(auto_now_add=True) + updated_at = models.DateTimeField(auto_now=True) + + class Meta: + abstract = True \ No newline at end of file diff --git a/common/models/choiceModels.py b/common/models/choiceModels.py new file mode 100644 index 0000000..f2ea76e --- /dev/null +++ b/common/models/choiceModels.py @@ -0,0 +1,13 @@ +from django.db import models + +class GenderChoices(models.TextChoices): + MAN = '남', '남성' + WOMAN = '여', '여성' + +class CertificateCodeUseType(models.TextChoices): + EMAIL = '이메일', '이메일' + PHONE = '휴대폰', '휴대폰' + +class InviteCodeUseType(models.TextChoices): + PROJECT = '프로젝트', '프로젝트' + HACKATHON = '해커톤', '해커톤' diff --git a/common/utils/codeManger.py b/common/utils/codeManger.py new file mode 100644 index 0000000..8b1398f --- /dev/null +++ b/common/utils/codeManger.py @@ -0,0 +1,20 @@ +from random import randint, choices +from django.utils.timezone import now +from datetime import timedelta + +import ulid, uuid + +def generate_ulid(): + return str(ulid.ULID()) + +def generate_uuid(): + return str(uuid.uuid4()) + +allowed_char = ''.join(chr(i) for i in range(33, 127) if chr(i).isalnum()) + +def generate_code(code_len): # 코드 생성 + code = ''.join(choices(allowed_char, k=code_len)) + return code + +def set_expire(minutes): # 유효기간 설정 + return now() + timedelta(minutes=minutes) \ No newline at end of file diff --git a/config/settings.py b/config/settings.py index d2ae3d5..bdd23db 100644 --- a/config/settings.py +++ b/config/settings.py @@ -44,7 +44,9 @@ INSTALLED_APPS = [ 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.staticfiles', + 'django.contrib.postgres', 'django_apscheduler', + 'django_extensions', 'rest_framework', 'rest_framework_simplejwt', 'rest_framework_simplejwt.token_blacklist', @@ -52,6 +54,7 @@ INSTALLED_APPS = [ 'users', 'portfolios', 'projects', + 'codes', ] MIDDLEWARE = [ diff --git a/portfolios/models.py b/portfolios/models.py index 71a8362..6a68602 100644 --- a/portfolios/models.py +++ b/portfolios/models.py @@ -1,3 +1,20 @@ from django.db import models -# Create your models here. +from common.models.baseModels import BaseModel + +from django.contrib.postgres.fields import ArrayField +from django.conf import settings + +from users.models import User + + +class Portfolio(BaseModel): + name = models.CharField(max_length=20) + category = ArrayField(models.CharField(max_length=20), default=list) + is_published = models.BooleanField(default=False) + view_count = models.IntegerField(default=0) + like_count = models.IntegerField(default=0) + scrab_count = models.IntegerField(default=0) + is_represent = models.BooleanField(default=False) + code_id = models.CharField(max_length=26, blank=True) + user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE, related_name='portfolios', to_field="id") \ No newline at end of file diff --git a/projects/models.py b/projects/models.py index 71a8362..bcd3b10 100644 --- a/projects/models.py +++ b/projects/models.py @@ -1,3 +1,23 @@ from django.db import models -# Create your models here. +from common.models.baseModels import BaseModel + +from django.contrib.postgres.fields import ArrayField +from django.conf import settings + +from users.models import User + +class Project(BaseModel): + name = models.CharField(max_length=20) + is_team = models.BooleanField(default=False) + category = ArrayField(models.CharField(max_length=20), default=list) + is_published = models.BooleanField(default=False) + view_count = models.IntegerField(default=0) + like_count = models.IntegerField(default=0) + scrab_count = models.IntegerField(default=0) + is_represent = models.BooleanField(default=False) + code_id = models.CharField(max_length=26, blank=True) + +class ProjectTeamList(BaseModel): + project = models.ForeignKey(Project, on_delete=models.CASCADE, related_name='project_team_list', to_field='id') + user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE, related_name='project_team_list',to_field='id') diff --git a/requirements.txt b/requirements.txt index a4c944c..513391e 100644 Binary files a/requirements.txt and b/requirements.txt differ diff --git a/users/models.py b/users/models.py index 79eba13..4ac7949 100644 --- a/users/models.py +++ b/users/models.py @@ -1,6 +1,59 @@ from django.db import models +from common.models.baseModels import BaseModel +from common.models.choiceModels import GenderChoices, CertificateCodeUseType +from common.utils.codeManger import set_expire -from django.contrib.auth.models import AbstractBaseUser, BaseUserManager, PermissionsMixin, AbstractUser +from django.contrib.postgres.fields import ArrayField +from django.contrib.auth.models import AbstractBaseUser, BaseUserManager, PermissionsMixin -class User(AbstractUser): - pass \ No newline at end of file +class UserManager(BaseUserManager): + def create_user(self, email, password, **kwargs): + user = self.model(email = email, **kwargs) + user.set_password(password) + user.save(using=self._db) + return user + + def create_superuser(self, email=None, password=None, **extra_fields): + superuser = self.create_user( + email = email, + password = password, + ) + + superuser.is_staff = True + superuser.is_superuser = True + superuser.is_active = True + + superuser.save(using=self._db) + return superuser + +class User(BaseModel, AbstractBaseUser, PermissionsMixin): + email = models.EmailField(unique=True) + is_email_verified = models.BooleanField(default=False) + is_plers_terms_of_service = models.BooleanField(default=False) + is_terms_of_service_colio = models.BooleanField(default=False) + is_consent_personal_info = models.BooleanField(default=False) + is_consent_third_party_sharing = models.BooleanField(default=False) + is_consent_marketing = models.BooleanField(default=False) + phone = models.CharField(max_length=11) + is_phone_verified = models.BooleanField(default=False) + nickname = models.CharField(default=False) + gender = models.CharField(choices=GenderChoices.choices, max_length=1) + birth_date = models.CharField(max_length=10) + custom_url = models.CharField(max_length=20) + job_and_interests = ArrayField(models.CharField(max_length=20), default=list) + skills = ArrayField(models.CharField(max_length=20), default=list, blank=True) + external_links = ArrayField(models.TextField(), default=list, blank=True) + short_bio = models.CharField(max_length=100, blank=True) + profile_image = models.ImageField(upload_to='', blank=True) + + is_staff = models.BooleanField(default=False) + is_active = models.BooleanField(default=True) + + objects = UserManager() + + USERNAME_FIELD = 'email' + REQUIRED_FIELDS = [] + + def __str__(self): + return self.nickname + \ No newline at end of file