338 lines
15 KiB
Python
338 lines
15 KiB
Python
from django import forms
|
|
from django.contrib.auth import get_user_model
|
|
from B_main.models import Person, WithdrawalRequest # 또는 Person 모델이 정의된 경로로 import
|
|
import random
|
|
import re
|
|
|
|
User = get_user_model()
|
|
|
|
def format_phone_number(phone):
|
|
"""전화번호에서 대시 제거"""
|
|
return re.sub(r'[^0-9]', '', phone)
|
|
|
|
class CustomFileInput(forms.FileInput):
|
|
def get_context(self, name, value, attrs):
|
|
context = super().get_context(name, value, attrs)
|
|
# "Currently:" 텍스트 제거
|
|
if 'help_text' in context:
|
|
context['help_text'] = ''
|
|
return context
|
|
|
|
class ProfileFullEditForm(forms.ModelForm):
|
|
# 읽기 전용 필드들
|
|
full_name = forms.CharField(
|
|
label="이름",
|
|
required=False,
|
|
widget=forms.TextInput(attrs={
|
|
'class': 'w-full px-4 py-3 rounded-xl bg-gray-100 dark:bg-gray-600 text-gray-700 dark:text-gray-300 border border-gray-300 dark:border-gray-600 focus:outline-none transition-colors duration-300',
|
|
'readonly': 'readonly',
|
|
'placeholder': '이름'
|
|
})
|
|
)
|
|
|
|
phone_display = forms.CharField(
|
|
label="전화번호",
|
|
required=False,
|
|
widget=forms.TextInput(attrs={
|
|
'class': 'w-full px-4 py-3 rounded-xl bg-gray-100 dark:bg-gray-600 text-gray-700 dark:text-gray-300 border border-gray-300 dark:border-gray-600 focus:outline-none transition-colors duration-300',
|
|
'readonly': 'readonly',
|
|
'placeholder': '전화번호'
|
|
})
|
|
)
|
|
|
|
birth_date_display = forms.CharField(
|
|
label="생년월일",
|
|
required=False,
|
|
widget=forms.TextInput(attrs={
|
|
'class': 'w-full px-4 py-3 rounded-xl bg-gray-100 dark:bg-gray-600 text-gray-700 dark:text-gray-300 border border-gray-300 dark:border-gray-600 focus:outline-none transition-colors duration-300',
|
|
'readonly': 'readonly',
|
|
'placeholder': '생년월일'
|
|
})
|
|
)
|
|
|
|
amp_title_display = forms.CharField(
|
|
label="AMP내직책",
|
|
required=False,
|
|
widget=forms.TextInput(attrs={
|
|
'class': 'w-full px-4 py-3 rounded-xl bg-gray-100 dark:bg-gray-600 text-gray-700 dark:text-gray-300 border border-gray-300 dark:border-gray-600 focus:outline-none transition-colors duration-300',
|
|
'readonly': 'readonly',
|
|
'placeholder': 'AMP내직책'
|
|
})
|
|
)
|
|
|
|
class Meta:
|
|
model = Person
|
|
fields = [
|
|
'소속', '직책', '주소', 'keyword1', '소개글'
|
|
]
|
|
widgets = {
|
|
'소속': forms.TextInput(attrs={
|
|
'class': 'w-full px-4 py-3 rounded-xl bg-white dark:bg-gray-700 text-gray-900 dark:text-white border border-gray-300 dark:border-gray-600 focus:outline-none focus:ring-2 focus:ring-blue-500 dark:focus:ring-blue-400 transition-colors duration-300',
|
|
'placeholder': '소속 (예: 신라대학교 회계학과)'
|
|
}),
|
|
'직책': forms.TextInput(attrs={
|
|
'class': 'w-full px-4 py-3 rounded-xl bg-white dark:bg-gray-700 text-gray-900 dark:text-white border border-gray-300 dark:border-gray-600 focus:outline-none focus:ring-2 focus:ring-blue-500 dark:focus:ring-blue-400 transition-colors duration-300',
|
|
'placeholder': '직책 (예: 교수, 학생, 직원)'
|
|
}),
|
|
'주소': forms.TextInput(attrs={
|
|
'class': 'w-full px-4 py-3 rounded-xl bg-white dark:bg-gray-700 text-gray-900 dark:text-white border border-gray-300 dark:border-gray-600 focus:outline-none focus:ring-2 focus:ring-blue-500 dark:focus:ring-blue-400 transition-colors duration-300',
|
|
'placeholder': '주소'
|
|
}),
|
|
'keyword1': forms.TextInput(attrs={
|
|
'class': 'w-full px-4 py-3 rounded-xl bg-white dark:bg-gray-700 text-gray-900 dark:text-white border border-gray-300 dark:border-gray-600 focus:outline-none focus:ring-2 focus:ring-blue-500 dark:focus:ring-blue-400 transition-colors duration-300',
|
|
'placeholder': '검색 키워드 (예: 회계감사)'
|
|
}),
|
|
'소개글': forms.Textarea(attrs={
|
|
'class': 'w-full px-4 py-3 rounded-xl bg-white dark:bg-gray-700 text-gray-900 dark:text-white border border-gray-300 dark:border-gray-600 focus:outline-none focus:ring-2 focus:ring-blue-500 dark:focus:ring-blue-400 transition-colors duration-300',
|
|
'placeholder': '자신을 소개하는 간단한 글을 작성하세요 (최대 200자)',
|
|
'rows': 4,
|
|
'maxlength': 200
|
|
}),
|
|
}
|
|
|
|
def __init__(self, *args, **kwargs):
|
|
self.user = kwargs.pop('user')
|
|
super().__init__(*args, **kwargs)
|
|
|
|
# 읽기 전용 필드들 초기값 설정
|
|
if self.instance and self.instance.pk:
|
|
# 이름 설정 (Person 모델의 이름 필드 사용)
|
|
self.fields['full_name'].initial = self.instance.이름
|
|
|
|
# 전화번호 설정 (Person 모델의 연락처 필드 사용)
|
|
self.fields['phone_display'].initial = self.instance.연락처
|
|
|
|
# 생년월일 설정
|
|
if self.instance.생년월일:
|
|
self.fields['birth_date_display'].initial = self.instance.생년월일.strftime('%Y-%m-%d')
|
|
else:
|
|
self.fields['birth_date_display'].initial = '설정되지 않음'
|
|
|
|
# AMP내직책 설정 (TITLE 필드)
|
|
self.fields['amp_title_display'].initial = self.instance.TITLE or '설정되지 않음'
|
|
|
|
def save(self, commit=True):
|
|
# Person 모델 저장 (User 모델은 수정하지 않음)
|
|
if commit:
|
|
instance = super().save(commit=False)
|
|
instance.user = self.user
|
|
instance.save()
|
|
|
|
return self.user
|
|
|
|
# 모드1: 비밀번호 찾기 폼
|
|
class PasswordResetStep1Form(forms.Form):
|
|
"""비밀번호 찾기 1단계: 전화번호 인증"""
|
|
phone = forms.CharField(
|
|
max_length=11,
|
|
label='전화번호',
|
|
widget=forms.TextInput(attrs={
|
|
'class': 'w-full px-4 py-3 rounded-xl bg-gray-700 bg-opacity-80 text-white placeholder-gray-400 border border-gray-600 focus:outline-none focus:ring-2 focus:ring-blue-500 transition',
|
|
'placeholder': '01012345678'
|
|
})
|
|
)
|
|
verification_code = forms.CharField(
|
|
max_length=6,
|
|
label='인증번호',
|
|
required=False,
|
|
widget=forms.TextInput(attrs={
|
|
'class': 'w-full px-4 py-3 rounded-xl bg-gray-700 bg-opacity-80 text-white placeholder-gray-400 border border-gray-600 focus:outline-none focus:ring-2 focus:ring-blue-500 transition',
|
|
'placeholder': '6자리 인증번호'
|
|
})
|
|
)
|
|
|
|
def clean_phone(self):
|
|
phone = self.cleaned_data.get('phone')
|
|
if phone:
|
|
# 전화번호 포맷팅 적용 (대시 제거)
|
|
formatted_phone = format_phone_number(phone)
|
|
|
|
# 해당 전화번호로 가입된 사용자가 있는지 확인
|
|
try:
|
|
user = User.objects.get(username=formatted_phone)
|
|
return formatted_phone
|
|
except User.DoesNotExist:
|
|
raise forms.ValidationError('등록되지 않은 전화번호입니다.')
|
|
return phone
|
|
|
|
# 모드2: 로그인 상태 비밀번호 변경 폼
|
|
class PasswordChangeLoggedInForm(forms.Form):
|
|
"""로그인 상태에서 비밀번호 변경"""
|
|
current_password = forms.CharField(
|
|
label='현재 비밀번호',
|
|
widget=forms.PasswordInput(attrs={
|
|
'class': 'w-full px-4 py-3 rounded-xl bg-gray-700 bg-opacity-80 text-white placeholder-gray-400 border border-gray-600 focus:outline-none focus:ring-2 focus:ring-blue-500 transition',
|
|
'placeholder': '현재 비밀번호'
|
|
})
|
|
)
|
|
new_password1 = forms.CharField(
|
|
label='새 비밀번호',
|
|
widget=forms.PasswordInput(attrs={
|
|
'class': 'w-full px-4 py-3 rounded-xl bg-gray-700 bg-opacity-80 text-white placeholder-gray-400 border border-gray-600 focus:outline-none focus:ring-2 focus:ring-blue-500 transition',
|
|
'placeholder': '새 비밀번호'
|
|
})
|
|
)
|
|
new_password2 = forms.CharField(
|
|
label='새 비밀번호 확인',
|
|
widget=forms.PasswordInput(attrs={
|
|
'class': 'w-full px-4 py-3 rounded-xl bg-gray-700 bg-opacity-80 text-white placeholder-gray-400 border border-gray-600 focus:outline-none focus:ring-2 focus:ring-blue-500 transition',
|
|
'placeholder': '새 비밀번호 확인'
|
|
})
|
|
)
|
|
|
|
def __init__(self, *args, **kwargs):
|
|
self.user = kwargs.pop('user', None)
|
|
super().__init__(*args, **kwargs)
|
|
|
|
def clean_current_password(self):
|
|
current_password = self.cleaned_data.get('current_password')
|
|
if self.user and not self.user.check_password(current_password):
|
|
raise forms.ValidationError('현재 비밀번호가 올바르지 않습니다.')
|
|
return current_password
|
|
|
|
def clean(self):
|
|
cleaned_data = super().clean()
|
|
password1 = cleaned_data.get('new_password1')
|
|
password2 = cleaned_data.get('new_password2')
|
|
|
|
if password1 and password2 and password1 != password2:
|
|
raise forms.ValidationError('새 비밀번호가 일치하지 않습니다.')
|
|
|
|
if password1 and len(password1) < 8:
|
|
raise forms.ValidationError('비밀번호는 최소 8자 이상이어야 합니다.')
|
|
|
|
return cleaned_data
|
|
|
|
# 모드3: 강제 비밀번호 설정 폼
|
|
class ForcePasswordSetForm(forms.Form):
|
|
"""강제 비밀번호 설정"""
|
|
new_password1 = forms.CharField(
|
|
label='새 비밀번호',
|
|
widget=forms.PasswordInput(attrs={
|
|
'class': 'w-full px-4 py-3 rounded-xl bg-gray-700 bg-opacity-80 text-white placeholder-gray-400 border border-gray-600 focus:outline-none focus:ring-2 focus:ring-blue-500 transition',
|
|
'placeholder': '새 비밀번호'
|
|
})
|
|
)
|
|
new_password2 = forms.CharField(
|
|
label='새 비밀번호 확인',
|
|
widget=forms.PasswordInput(attrs={
|
|
'class': 'w-full px-4 py-3 rounded-xl bg-gray-700 bg-opacity-80 text-white placeholder-gray-400 border border-gray-600 focus:outline-none focus:ring-2 focus:ring-blue-500 transition',
|
|
'placeholder': '새 비밀번호 확인'
|
|
})
|
|
)
|
|
|
|
def clean(self):
|
|
cleaned_data = super().clean()
|
|
password1 = cleaned_data.get('new_password1')
|
|
password2 = cleaned_data.get('new_password2')
|
|
|
|
if password1 and password2 and password1 != password2:
|
|
raise forms.ValidationError('비밀번호가 일치하지 않습니다.')
|
|
|
|
if password1 and len(password1) < 8:
|
|
raise forms.ValidationError('비밀번호는 최소 8자 이상이어야 합니다.')
|
|
|
|
return cleaned_data
|
|
|
|
# 기존 폼들 (유지)
|
|
class PasswordChangeStep1Form(forms.Form):
|
|
"""비밀번호 변경 1단계: 전화번호 인증"""
|
|
phone = forms.CharField(
|
|
max_length=11,
|
|
label='전화번호',
|
|
widget=forms.TextInput(attrs={
|
|
'class': 'w-full px-4 py-3 rounded-xl bg-gray-700 bg-opacity-80 text-white placeholder-gray-400 border border-gray-600 focus:outline-none focus:ring-2 focus:ring-blue-500 transition',
|
|
'placeholder': '01012345678'
|
|
})
|
|
)
|
|
verification_code = forms.CharField(
|
|
max_length=6,
|
|
label='인증번호',
|
|
required=False,
|
|
widget=forms.TextInput(attrs={
|
|
'class': 'w-full px-4 py-3 rounded-xl bg-gray-700 bg-opacity-80 text-white placeholder-gray-400 border border-gray-600 focus:outline-none focus:ring-2 focus:ring-blue-500 transition',
|
|
'placeholder': '6자리 인증번호'
|
|
})
|
|
)
|
|
|
|
def clean(self):
|
|
cleaned_data = super().clean()
|
|
phone = cleaned_data.get('phone')
|
|
|
|
if phone:
|
|
# 전화번호 포맷팅 적용 (대시 제거)
|
|
formatted_phone = format_phone_number(phone)
|
|
cleaned_data['phone'] = formatted_phone
|
|
|
|
# 현재 로그인한 사용자의 전화번호와 일치하는지 확인
|
|
if not self.user or self.user.username != formatted_phone:
|
|
raise forms.ValidationError('등록된 전화번호와 일치하지 않습니다.')
|
|
|
|
return cleaned_data
|
|
|
|
class PasswordChangeStep2Form(forms.Form):
|
|
"""비밀번호 변경 2단계: 새 비밀번호 입력"""
|
|
new_password1 = forms.CharField(
|
|
label='새 비밀번호',
|
|
widget=forms.PasswordInput(attrs={
|
|
'class': 'w-full px-4 py-3 rounded-xl bg-gray-700 bg-opacity-80 text-white placeholder-gray-400 border border-gray-600 focus:outline-none focus:ring-2 focus:ring-blue-500 transition',
|
|
'placeholder': '새 비밀번호'
|
|
})
|
|
)
|
|
new_password2 = forms.CharField(
|
|
label='새 비밀번호 확인',
|
|
widget=forms.PasswordInput(attrs={
|
|
'class': 'w-full px-4 py-3 rounded-xl bg-gray-700 bg-opacity-80 text-white placeholder-gray-400 border border-gray-600 focus:outline-none focus:ring-2 focus:ring-blue-500 transition',
|
|
'placeholder': '새 비밀번호 확인'
|
|
})
|
|
)
|
|
|
|
def clean(self):
|
|
cleaned_data = super().clean()
|
|
password1 = cleaned_data.get('new_password1')
|
|
password2 = cleaned_data.get('new_password2')
|
|
|
|
if password1 and password2 and password1 != password2:
|
|
raise forms.ValidationError('비밀번호가 일치하지 않습니다.')
|
|
|
|
if password1 and len(password1) < 8:
|
|
raise forms.ValidationError('비밀번호는 최소 8자 이상이어야 합니다.')
|
|
|
|
return cleaned_data
|
|
|
|
class WithdrawalRequestForm(forms.ModelForm):
|
|
"""회원탈퇴 요청 폼"""
|
|
|
|
confirm_withdrawal = forms.BooleanField(
|
|
required=True,
|
|
label='위 주의사항을 모두 확인했으며, 회원탈퇴를 요청합니다',
|
|
widget=forms.CheckboxInput(attrs={
|
|
'class': 'w-4 h-4 text-red-600 bg-gray-700 border-gray-600 rounded focus:ring-red-500 focus:ring-2'
|
|
}),
|
|
error_messages={
|
|
'required': '탈퇴 확인을 체크해주세요'
|
|
}
|
|
)
|
|
|
|
class Meta:
|
|
model = WithdrawalRequest
|
|
fields = []
|
|
|
|
def __init__(self, *args, **kwargs):
|
|
self.user = kwargs.pop('user', None)
|
|
super().__init__(*args, **kwargs)
|
|
|
|
def save(self, commit=True):
|
|
withdrawal_request = super().save(commit=False)
|
|
|
|
if self.user:
|
|
withdrawal_request.user = self.user
|
|
try:
|
|
withdrawal_request.person = Person.objects.get(user=self.user)
|
|
except Person.DoesNotExist:
|
|
raise forms.ValidationError('사용자의 Person 정보를 찾을 수 없습니다.')
|
|
|
|
if commit:
|
|
withdrawal_request.save()
|
|
|
|
return withdrawal_request |