django-registration form customize

2016-11-12

경고! 이 포스팅은 좋지 못한 방법을 안내하고 있습니다. 우는 짤

    이 포스팅대로 하면 User모델이 확장 되긴 하지만 바람직하지 않은 방법으로 확장합니다. 문제를 찝자면..

  1. ForeignKey로 user를 가져옴
  2. auth_user 테이블과 accounts_account 테이블 2개가 생성이 되며 회원가입을 하면 두 테이블에 들어감
  3. createsuperuser로 슈퍼유저를 생성하면 auth_user에 들어가고 accounts_account에는 들어가지 않음 (당연한 결과)

    user가 저장되고 가져오는 테이블은 하나로 두고 superuser와 일반 user가 함께 들어가게 하고싶음. 그래서 새로 포스팅을 했습니다. –> AbstractBaseUser를 사용한 User모델 확장


    AbstractUser로 상속받아서 확장하고 뭐..어떻게 하다가 잘 안되었다. github에서 django-registration을 사용하는 사람들의 코드를 꽤 찾아봤는데 버전별로 상이하고 버전과는 별개로 모델확장하는 방법이 다 달랐다. kboard프로젝트에서 별도의 accounts라는 이름의 앱을 만들고 accounts에서 작업했다. 요약을 하면 아래와 같다.

  • accounts/forms.py
        Email 필드를 unique하게 하기 위해서 아래를 import 하였음
from registration.forms import RegistrationFormUniqueEmail
  • accounts/views.py
        RegistrationView를 상속 및 오버라이딩
from registration.backends.hmac.views import RegistrationView
  • accounts/models.py
        각 계정을 관리하기 위해 Account 모델 생성
from django.db import models
class Account(models.Model):
    [...]


Form 확장

    새로 만드는 것이 아닌 기존의 것을 확장한다. Django의 User모델 필드 를 보면 내가 원하는 필드가 전부 있지 않다. 그래서 원하는 필드를 아래와 같이 추가 해 준다.

class RegistrationForm(RegistrationFormUniqueEmail):
    fullName = forms.CharField(max_length=150)
    terms = forms.BooleanField(error_messages={'required': _(u'You must agree to the terms to register')})

    기존의 User모델이 제공하는 필드를 사용하기 위해서 __init__을 사용한다.

[...]
def __init__(self, *args, **kwargs):
    super(RegistrationFormUniqueEmail, self).__init__(*args, **kwargs)
    if 'username' in self.fields:
        self.fields['username'].widget.attrs.update({'placeholder': _(u'Your ID'), 'autofocus': ''})
    if 'fullName' in self.fields:
        self.fields['fullName'].widget.attrs.update({'placeholder': _(u'Your name')})
    if 'email' in self.fields:
        self.fields['email'].widget.attrs.update({'placeholder': _(u'Your email')})
    if 'password1' in self.fields:
        self.fields['password1'].widget.attrs.update({'placeholder': _(u'Enter password')})
    if 'password2' in self.fields:
        self.fields['password2'].widget.attrs.update({'placeholder': _(u'Confirm password')})

    위의 __init__함수를 오버라이딩하고 나서 registration form의 필드는 아래와 같다. 블로그 적으면서 fullName 이 이질적이라는 생각이 들었다. fullname 이 좀 더 나을 듯..

username, email, password1, password2, fullName, terms

    필요한 것들이 더 있으면 saveclean_password2 등..을 오버라이딩 해 주면 된다. 생각없이 남들 코드짠거 보고 만들어서 saveclean_password2등을 오버라이딩 했는데 굳이 지금은 필요없는듯하다.

View

    여기서는 register함수를 오버라이딩 해 준다.

from registration.backends.hmac.views import RegistrationView as BaseRegistrationView
from .forms import RegistrationForm
from .models import Account
[...]
class RegistrationView(BaseRegistrationView):
    form_class = RegistrationForm

    def register(self, form):
        new_user = BaseRegistrationView.register(self, form)
        acc = Account()
        acc.fullName = form.cleaned_data['fullName']
        acc.user = new_user
        acc.status = 'created'
        acc.save()

Model

    settings.AUTH_USER_MODEL은 기본이 User모델로 되어있다. 이를 ForeignKey로 연결 해 준다. __str__함수는 admin페이지에서 Account object 이런식으로 나오는게 싫어서 오버라이딩 해 줬다.

class Account(models.Model):
    user = models.ForeignKey(
        settings.AUTH_USER_MODEL,
    )
    fullName = models.CharField(max_length=150)
    status = models.CharField(max_length=20)
    created_time = models.DateTimeField(auto_now_add=True)
    modified_time = models.DateTimeField(auto_now=True)

    def __str__(self):
        return self.fullName

    admin 페이지에서 이를 적용해 주려면 accounts/admin.py에 딱 아래 한 줄만 넣어주면 된다.

admin.site.register(Account)

끝?

    일단 DB에 잘 들어가고 form이 잘 나온다. 포스팅 하다보니까 수정하고 더 추가해야 할 것들이 눈에 보인다. Aㅏ… 조잡한 코드를 보고 싶으면 여기를 참고하면 된다.