회원관리 2-1. 커스텀유저(Profile 이용)

Pywiki
Sam (토론 | 기여)님의 2021년 11월 4일 (목) 14:55 판 (→‎view 추가)
둘러보기로 가기 검색하러 가기

1 개요

프로필은 또 다른 DB 요청이 있다는 점에서 불필요한 과정이 늘기도 하지만... SNS 계정을 한 프로필 내에서 관리하기 위해 사용해본다.

그리고, 일단 간단하다.

2 모델작성

기본적으로 프로필 모델을 작성하고 다음과 같이 1:1 연결을 하는 것이 일반적이다.

class Profile(models.Model):
    user = models.OneToOneField(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)

3 더 나아가기

일반적인 프로필 모델이라면 위 과정만으로도 구현이 끝난다.

다만, 이번엔 여러 계정을 하나의 프로필에 엮어줄 예정이라, AbstractBaseUser를 이용하여 다음과 같은 방식으로 짜주자. 다음 문서를 참고하자.

class User(AbstractBaseUser):
    identifier = models.CharField(max_length=20, unique=True)
    is_active = models.BooleanField(default=True)
    is_admin = models.BooleanField(default=False)
    profile = models.ForeignKey(Profile, on_delete=models.CASCADE, null=True, blank=True)  # 연결할 프로필모델. 아래에서 정의.
    # 프로필이 사라지면 사용자 모델도 한꺼번에 다 없어지게끔!
    objects = UserManager()  # 회원가입을 다룰 클래스를 지정한다.

    USERNAME_FIELD = 'identifier'   # 식별자로 사용할 필드.
    REQUIRED_FIELDS = []            # 회원가입 때 필수 입력필드.

    def __str__(self):
        return self.identifier

그리고 프로필 계정은 필요에 따라 다음과 같이 짠다. User에서 참고해야 하므로 User모델보다 위에 위치하게 해주자.

class Profile(models.Model):
    '''계정모델에서 연결하여 상위에 있는, 하위 SNS계정을 종합하는 프로필.'''
    # 유저정보 관련
    username = models.CharField(max_length=10)  # 실명을 기입하게끔 하자.
    nickname = models.CharField(max_length=10, unique=True, null=True, blank=False)  # 드러날 식별자. 변경 가능하지만, 유일하다.
    date_joined = models.DateTimeField(auto_now_add=True)
    last_login = models.DateTimeField(auto_now=True)
    email_active = models.BooleanField(default=False)  # 이메일 검증여부

이렇게 하면 user.profile.username 같은 방식으로 프로필 속성에 접근할 수 있다.

3.1 계정에서 프로필 생성

회원가입 후 프로필을 생성하여야 한다.

3.1.1 탬플릿 추가

base.html 등에 프로필이 없는 경우, 프로필을 생성하고 활동할 수 있게끔 코드를 넣는다.

{% if user.profile %}
{% else %}
<div class="alert alert-danger">
    <h1><strong>프로필을 등록해야 글을 쓸 수 있습니다.</strong></h1>
    <h2><a href="{% url 'account:create_profile' %}">프로필 생성</a></h2>
</div>
{% endif %}

3.1.2 url 추가

다음과 같이 url을 추가해준다.

path('profile_create/', views.profile_create, name='profile_create'),

3.1.3 view 추가

다음과 같이 뷰를 추가한다.

from .models import Profile

@login_required()
def profile_create(request):
    if request.method == "POST":
        form = Profile_create_form(request.POST)
        if form.is_valid():
            username = form.cleaned_data.get('identifier')      # 유저아이디를 입력받는다.
            raw_password = form.cleaned_data.get('password')    # 패스워드를 입력받는다.
            user = authenticate(username=username, password=raw_password)  # 인증 진행
            if user:  # 유저모델이 반환된다면.. 프로필 모델에 저장한다.
                profile = Profile()
                profile.username = form.cleaned_data.get('username')
                profile.nickname = form.cleaned_data.get('nickname')
                profile.email = form.cleaned_data.get('email')
                profile = profile.save()
                request.user.profile = profile  # 해당 로그인한 유저의 프로필을 이 프로필로 채운다.
                request.user.save()
                return redirect('account:profile')
            else:
                form.add_error('identifier','비밀번호 혹은 아이디가 다릅니다.')  # 인증이 안되면 필드에러를 발생시킨다.
    else:
        form = Profile_create_form()
    context = {'form': form,
               }
    return render(request, 'account/profile_create.html', context)

3.1.4 view에서 사용할 form 추가

계정 검증을 해야하기 때문에 모델에 기반한 폼이 아니라 일반 폼으로 제작한다.

class Profile_create_form(forms.Form):
    identifier = forms.CharField()
    password = forms.PasswordInput()
    username = forms.CharField(max_length=10)
    nickname = forms.CharField(max_length=10)
    email = forms.EmailField()