hashed password로 Django User Model instance 생성하기

Reading time ~2 minutes

Django에서 제공하는 User를 상속 받아서 사용하고 있다. 테스트할 때 매번 User 객체를 생성하는 것이 번거로워서 RunPython을 이용하여 migrate 할 때 테스트를 위한 User model instance 를 생성했는데 password가 해싱되지 않고 저장되는 문제가 발생했다. User.objects.create() 할 때 password를 hashing하여 생성하는 방법에 대해서 알아본다.


User model

from django.contrib.auth.models import AbstractUser
from django.core.validators import RegexValidator


class User(AbstractUser):
    phone_regex = RegexValidator(regex='^\d{11}$', message='Phone length has to be 11 & Only number')

    username = models.EmailField(unique=True, null=False, max_length=254)
    phone_number = models.CharField(max_length=11, validators=[phone_regex])
    # ...

User model은 AbstractUser 를 상속 받고 email을 username으로 사용하고 있다.


Create User instance

User.objects.create(
    username="test@email.com",
    password="pwd1234",
    phone_number="01012341234")

위와 같이 password를 지정해서 User instance를 생성하면 password가 hashing 되지 않고 DB에 “pwd1234” 값 그대로 저장이 된다. password를 hashing하여 instance를 생성하는 방법을 검색해보면 set_password() 을 이용하는 방법들이 많이 나오는데,

user = User(
    username="test@email.com",
    phone_number="01012341234")
user.set_password("pwd1234")
user.save()

적용해보면 ‘set_password’를 찾을 수 없다는 에러가 발생한다.

AttributeError: 'User' object has no attribute 'set_password'

Django Docs’s Password management in Django 을 참고해보면 make_password() 을 이용하면 hashed password를 생성할 수 있다고 한다.

from django.contrib.auth.hashers import make_password

hashed_password = make_password("pwd1234")

User.objects.create(
    username="test@email.com",
    password=hashed_password,
    phone_number="01012341234")


RunPython

RunPython을 이용하여 User instance를 생성하면 migrate 단계에서 User 데이터를 생성하여 DB에 저장된다.

from __future__ import unicode_literals
from django.db import migrations, models
from django.contrib.auth.hashers import make_password


def forwards_func(apps, schema_editor):
    User = apps.get_model("myapp", "User")

    hashed_password = make_password("pwd1234")
    User.objects.create(username="testman@email.com", password=hashed_password, phone_number="01012341234")


def reverse_func(apps, schema_editor):
    Meeting = apps.get_model("myapp", "User")
    db_alias = schema_editor.connection.alias


class Migration(migrations.Migration):
    dependencies = [
        ('myapp', '0001_initial'),
    ]

    operations = [
        migrations.RunPython(forwards_func, reverse_func),
    ]

DRF(Django Rest Framework) SerializerMethodField 이용하여 특정 필드 값 변경해서 반환하기

DRF(Django Rest Framework)에서 ModelSerializer 을 이용하면 class Meta:의 설정값에 따라서 REST API를 만들어준다. 기본적으로 model의 필드 값들을 JSON형태로 반환해주는데 날짜, 시간 등과...… Continue reading