(2022.10.27) Today I Learned_Day-40

imRoundยท2022๋…„ 10์›” 27์ผ
0
post-thumbnail

๐Ÿค– UserModel ์ƒ์„ฑ์ค‘ UserModel์„ CustomModel๋กœ ๋ณ€๊ฒฝํ•  ๋•Œ

# users/models.py

from django.db import models
from django.contrib.auth.models import (
    BaseUserManager, AbstractBaseUser
)

class UserManager(BaseUserManager):
    def create_user(self, email, date_of_birth, password=None):
        """
        Creates and saves a User with the given email, date of
        birth and password.
        """
        if not email:
            raise ValueError('Users must have an email address')

        user = self.model(
            email=self.normalize_email(email),
            date_of_birth=date_of_birth,
        )

        user.set_password(password)
        user.save(using=self._db)
        return user

    def create_superuser(self, email, date_of_birth, password=None):
        """
        Creates and saves a superuser with the given email, date of
        birth and password.
        """
        user = self.create_user(
            email,
            password=password,
            date_of_birth=date_of_birth,
        )
        user.is_admin = True
        user.save(using=self._db)
        return user

class User(AbstractBaseUser):
    email = models.EmailField( # ์ด๋ฉ”์ผ๋กœ ๋“ค์–ด์™”๊ณ 
        verbose_name='email address',
        max_length=255,
        unique=True,
    )
    date_of_birth = models.DateField() # ์ƒ๋…„์›”์ผ
    is_active = models.BooleanField(default=True) # ํ™œ๋™ ์ค‘์ธ์ง€
    is_admin = models.BooleanField(default=False) # ์–ด๋“œ๋ฏผ์ธ์ง€

    objects = UserManager() # ์œ ์ €๋งค๋‹ˆ์ € ์—ฐ๊ฒฐ

    USERNAME_FIELD = 'email' # ์ด๋ฉ”์ผ๋กœ ๋กœ๊ทธ์ธ
    REQUIRED_FIELDS = ['date_of_birth'] # ์ƒ๋…„์›”์ผ ๊ผญ ํ•„์ˆ˜๋กœ ๋„ฃ์–ด๋‹ฌ๋ผ

    def __str__(self):
        return self.email

    def has_perm(self, perm, obj=None): # ํผ๋ฏธ์…˜์ด ์žˆ๋Š”์ง€
        "Does the user have a specific permission?"
        # Simplest possible answer: Yes, always
        return True

    def has_module_perms(self, app_label):
        "Does the user have permissions to view the app `app_label`?"
        # Simplest possible answer: Yes, always
        return True

    @property
    def is_staff(self): # ์Šคํƒœํ”„์ธ์ง€?
        "Is the user a member of staff?"
        # Simplest possible answer: All admins are staff
        return self.is_admin
# settings.py

...
STATIC_URL = 'static/'

# Default primary key field type
# https://docs.djangoproject.com/en/4.1/ref/settings/#default-auto-field

DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField'

AUTH_USER_MODEL = 'users.user' # '์•ฑ.๋ชจ๋ธ'

db.sqlite3๋ฅผ ์‚ญ์ œํ•˜๊ณ , UserModel์„ Custom Model๋กœ ๋ฐ”๊พธ๊ณ  migrate๋ฅผ ์ง„ํ–‰ํ•˜์˜€๋‹ค.

user๋ชจ๋ธ์„ Custom user๋กœ ๋งŒ๋“ค๊ธฐ ํž˜๋“  ์ด์œ 

Changing to a custom user model mid-project

Changingย [AUTH_USER_MODEL](https://docs.djangoproject.com/en/4.1/ref/settings/#std-setting-AUTH_USER_MODEL)ย after youโ€™ve created database tables is significantly more difficult since it affects foreign keys and many-to-many relationships, for example.

This change canโ€™t be done automatically and requires manually fixing your schema, moving your data from the old user table, and possibly manually reapplying some migrations. Seeย #25313ย for an outline of the steps.

Due to limitations of Djangoโ€™s dynamic dependency feature for swappable models, the model referenced byย [AUTH_USER_MODEL](https://docs.djangoproject.com/en/4.1/ref/settings/#std-setting-AUTH_USER_MODEL)ย must be created in the first migration of its app (usually calledย 0001_initial); otherwise, youโ€™ll have dependency issues.

In addition, you may run into aย CircularDependencyErrorย when running your migrations as Django wonโ€™t be able to automatically break the dependency loop due to the dynamic dependency. If you see this error, you should break the loop by moving the models depended on by your user model into a second migration. (You can try making two normal models that have aย ForeignKeyย to each other and seeing howย makemigrationsย resolves that circular dependency if you want to see how itโ€™s usually done.)

ํ”„๋กœ์ ํŠธ ์ค‘๊ฐ„์— ์ปค์Šคํ…€ ์‚ฌ์šฉ์ž ๋ชจ๋ธ๋กœ ๋ณ€๊ฒฝํ•˜๊ธฐ

์˜ˆ๋ฅผ ๋“ค์–ด ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ํ…Œ์ด๋ธ”์„ ์ƒ์„ฑํ•œ ํ›„ ๋ณ€๊ฒฝย [AUTH_USER_MODEL](https://docs.djangoproject.com/en/4.1/ref/settings/#std-setting-AUTH_USER_MODEL)ํ•˜๋Š” ๊ฒƒ์€ ์™ธ๋ž˜ ํ‚ค ๋ฐ ๋‹ค๋Œ€๋‹ค ๊ด€๊ณ„์— ์˜ํ–ฅ์„ ๋ฏธ์น˜๊ธฐ ๋•Œ๋ฌธ์— ํ›จ์”ฌ ๋” ์–ด๋ ต์Šต๋‹ˆ๋‹ค.

์ด ๋ณ€๊ฒฝ์€ ์ž๋™์œผ๋กœ ์ˆ˜ํ–‰ํ•  ์ˆ˜ ์—†์œผ๋ฉฐ ์ˆ˜๋™์œผ๋กœ ์Šคํ‚ค๋งˆ๋ฅผ ์ˆ˜์ •ํ•˜๊ณ  ์ด์ „ ์‚ฌ์šฉ์ž ํ…Œ์ด๋ธ”์—์„œ ๋ฐ์ดํ„ฐ๋ฅผ ์ด๋™ํ•˜๊ณ  ์ผ๋ถ€ ๋งˆ์ด๊ทธ๋ ˆ์ด์…˜์„ ์ˆ˜๋™์œผ๋กœ ๋‹ค์‹œ ์ ์šฉํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.ย ๋‹จ๊ณ„์— ๋Œ€ํ•œ ๊ฐœ์š”๋Š”ย #25313ย ์„ ์ฐธ์กฐ ํ•˜์‹ญ์‹œ์˜ค.

๊ต์ฒด ๊ฐ€๋Šฅํ•œ ๋ชจ๋ธ์— ๋Œ€ํ•œ Django์˜ ๋™์  ์ข…์†์„ฑ ๊ธฐ๋Šฅ์˜ ์ œํ•œ์œผ๋กœ ์ธํ•ด ์—์„œ ์ฐธ์กฐํ•˜๋Š” ๋ชจ๋ธย [AUTH_USER_MODEL](https://docs.djangoproject.com/en/4.1/ref/settings/#std-setting-AUTH_USER_MODEL)์€ ์•ฑ์˜ ์ฒซ ๋ฒˆ์งธ ๋งˆ์ด๊ทธ๋ ˆ์ด์…˜(๋ณดํ†ต ์ด๋ผ๊ณ  ํ•จย 0001_initial)์—์„œ ์ƒ์„ฑ๋˜์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.ย ๊ทธ๋ ‡์ง€ ์•Š์œผ๋ฉด ์ข…์†์„ฑ ๋ฌธ์ œ๊ฐ€ ๋ฐœ์ƒํ•ฉ๋‹ˆ๋‹ค.

๋˜ํ•œย CircularDependencyErrorDjango๊ฐ€ ๋™์  ์ข…์†์„ฑ์œผ๋กœ ์ธํ•ด ์ข…์†์„ฑ ๋ฃจํ”„๋ฅผ ์ž๋™์œผ๋กœ ์ค‘๋‹จํ•  ์ˆ˜ ์—†๊ธฐ ๋•Œ๋ฌธ์— ๋งˆ์ด๊ทธ๋ ˆ์ด์…˜์„ ์‹คํ–‰ํ•  ๋•Œ ๋ฌธ์ œ๊ฐ€ ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.ย ์ด ์˜ค๋ฅ˜๊ฐ€ ํ‘œ์‹œ๋˜๋ฉด ์‚ฌ์šฉ์ž ๋ชจ๋ธ์— ์ข…์†๋œ ๋ชจ๋ธ์„ ๋‘ ๋ฒˆ์งธ ๋งˆ์ด๊ทธ๋ ˆ์ด์…˜์œผ๋กœ ์ด๋™ํ•˜์—ฌ ๋ฃจํ”„๋ฅผ ๋Š์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.ย ForeignKey( ์„œ๋กœย ๊ฐ€ ์žˆ๋Š” ๋‘ ๊ฐœ์˜ ์ผ๋ฐ˜ ๋ชจ๋ธ์„ ๋งŒ๋“ค๊ณ ย makemigrations์ผ๋ฐ˜์ ์œผ๋กœ ์ˆ˜ํ–‰๋˜๋Š” ๋ฐฉ์‹์„ ๋ณด๋ ค๋ฉด ์ˆœํ™˜ ์ข…์†์„ฑ์„ ํ•ด๊ฒฐํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ๋ณผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.)

Django ๊ณต์‹๋ฌธ์„œ์—์„œ ์ฐพ์•„๋ณด๊ณ  ์‹œ์ž‘ํ•˜๋Š” ๊ฒƒ์ด ์ข‹์„ ๋“ฏํ•˜๋‹ค.

profile
Django ๊ฐœ๋ฐœ์ž

0๊ฐœ์˜ ๋Œ“๊ธ€