본문 바로가기
임시글/이전

[번역] Django User Model 확장하는 방법

by 동탄참새 2021. 6. 15.

원문 : https://simpleisbetterthancomplex.com/tutorial/2016/07/22/how-to-extend-django-user-model.html

 

How to Extend Django User Model

The Django’s built-in authentication system is great. For the most part we can use it out-of-the-box, saving a lot ofdevelopment and testing effort. It fits ...

simpleisbetterthancomplex.com

 

더보기

The Django’s built-in authentication system is great. For the most part we can use it out-of-the-box, saving a lot of development and testing effort. It fits most of the use cases and is very safe. But sometimes we need to do some fine adjustment so to fit our Web application.

 

Commonly we want to store a few more data related to our User. If your Web application have an social appeal, you might want to store a short bio, the location of the user, and other things like that.

 

In this tutorial I will present the strategies you can use to simply extend the default Django User Model, so you don’t need to implement everything from scratch.

 장고 계정 시스템은 훌륭합니다. 대부분의 내장 기능들은 많은 개발과 테스트 소요를 줄여주죠. 대부분 상황에서 적용 가능하고 안전하기까지 합니다. 하지만 Web application 을 개발하다보면 어느순간 조정이 필요할 때가 있습니다.

 

 우리의 User와 관계된 종류의 데이터를 저장합니다. 만약 Web application에서 소셜 어필을 강조해야하는 부분이 있다면, 당신은 짧은 자기소개, 사용자의 위치와 같은 정보들을 저장하고 싶을 것입니다.

 

 이번 튜토리얼에서 저는 기본 Django User Model에서 간단히 확장할 수 있는 방법을 소개할 예정입니다. 이제 더 이상 모든걸 처음부터 구현마세요.


더보기

Ways to Extend the Existing User Model

Generally speaking, there are four different ways to extend the existing User model. Read below why and when to use them.

기존 User Model을 확장하는 법

일반적으로, 기존 User model 에선 4가지의 확장 방법이 있습니다. 각 방법들을 언제 그리고, 왜 사용하는지 소개합니다.


더보기

Option 1: Using a Proxy Model

What is a Proxy Model?
It is a model inheritance without creating a new table in the database. It is used to change the behaviour of an existing model (e.g. default ordering, add new methods, etc.) without affecting the existing database schema.

 

When should I use a Proxy Model?
You should use a Proxy Model to extend the existing User model when you don’t need to store extra information in the database, but simply add extra methods or change the model’s query Manager.

옵션 1 : Proxy Model 사용법

Proxy Model이란?

 Database 내의 새로운 Table을 생성치않는 Model 객체입니다. 기존 Database Schema에 영향을 주지않으면서 기존 Model의 동작 (기본 정렬, 새 Methods 등등) 을 변화하고 싶을 때 사용합니다.

언제 Proxy Model을 사용해야하나요?

 기존 User Model에서 Database 원본을 변경치 않고, Model의 Query Manager를 변경하고 싶거나, 새 Methods를 간단히 추가하고 싶을때 사용하면 좋습니다.


더보기

Extending User Model Using a Proxy Model

This is the less intrusive way to extend the existing User model. You won’t have any drawbacks with that strategy. But it is very limited in many ways.

 

Here is how you do it:

from django.contrib.auth.models import User
from .managers import PersonManager

class Person(User):
    objects = PersonManager()

    class Meta:
        proxy = True
        ordering = ('first_name', )

    def do_something(self):
        ...

In the example above we have defined a Proxy Model named Person. We tell Django this is a Proxy Model by adding the following property inside the Meta class: proxy = True.

 

In this case I’ve redefined the default ordering, assigned a custom Manager to the model, and also defined a new method do_something.

 

It is worth noting that User.objects.all() and Person.objects.all() will query the same database table. The only difference is in the behavior we define for the Proxy Model.

 

If that’s all you need, go for it. Keep it simple.

기존 User Model에서 Proxy Model로 확장하는 법

 이건 기존 User Model에 상대적으로 덜 개입하는 방법입니다. 이 방법은 리스크가 없지만, 여러면에서 상당히 제한적이기도 합니다.

 

 여기 코드를 보시죠.

from django.contrib.auth.models import User
from .managers import PersonManager

class Person(User):
    objects = PersonManager()

    class Meta:
        proxy = True
        ordering = ('first_name', )

    def do_something(self):
        ...

 예제에서 Proxy Model을 Person 으로 명명했습니다. Proxy Model을 사용하기 위해선 Meta class 안에  proxy = True 을 넣어야 합니다.

 

 이번에 저는 기본 정렬을 재정의했구요. custom Manager을 Model에 할당하였으며, 또한 new Method do_something을 추가했습니다.

 

더 중요한건 User.objects.all() 과 Person.objects.all() 이 동일한 Database table을 가진다는 것입니다. 둘간의 차이점은 Proxy Model에서 정의한 동작밖에 없습니다.


더보기

Option 2: Using One-To-One Link With a User Model (Profile)

What is a One-To-One Link?
It is a regular Django model that’s gonna have it’s own database table and will hold a One-To-One relationship with the existing User Model through a OneToOneField.

When should I use a One-To-One Link?
You should use a One-To-One Link when you need to store extra information about the existing User Model that’s not related to the authentication process. We usually call it a User Profile.

옵션 2: User Model에 One-To-One Link를 사용하는 법 (Profile)

One-To-One Link가 뭔가요?

 자체 Database table을 가질 Django model이며, 기존 User Model과 OneToOneField를 통해 일대일로 연결됩니다.

 

언제 One-To-One Line를 사용하나요?

 기존 User Model에 일대일로 추가 정보를 저장하고 싶을때 사용합니다. 단 이때 정보는 계정 시스템과는 무관합니다. 보통 User Profile로 부릅니다.


더보기

Extending User Model Using a One-To-One Link

There is a good chance that this is what you want. Personally that is the method I use for the most part. We will be creating a new Django Model to store the extra information that relates to the User Model.

Bear in mind that using this strategy results in additional queries or joins to retrieve the related data. Basically all the time you access an related data, Django will fire an additional query. But this can be avoided for the most cases. I will get back to that later on.

 

I usually name the Django Model as Profile:

from django.db import models
from django.contrib.auth.models import User

class Profile(models.Model):
    user = models.OneToOneField(User, on_delete=models.CASCADE)
    bio = models.TextField(max_length=500, blank=True)
    location = models.CharField(max_length=30, blank=True)
    birth_date = models.DateField(null=True, blank=True)

Now this is where the magic happens: we will now define signals so our Profile model will be automatically created/updated when we create/update User instances.

from django.db import models
from django.contrib.auth.models import User
from django.db.models.signals import post_save
from django.dispatch import receiver

class Profile(models.Model):
    user = models.OneToOneField(User, on_delete=models.CASCADE)
    bio = models.TextField(max_length=500, blank=True)
    location = models.CharField(max_length=30, blank=True)
    birth_date = models.DateField(null=True, blank=True)

@receiver(post_save, sender=User)
def create_user_profile(sender, instance, created, **kwargs):
    if created:
        Profile.objects.create(user=instance)

@receiver(post_save, sender=User)
def save_user_profile(sender, instance, **kwargs):
    instance.profile.save()

Basically we are hooking the create_user_profile and save_user_profile methods to the User model, whenever a save event occurs. This kind of signal is called post_save.

Great stuff. Now, tell me how can I use it.

 

Piece of cake. Check this example in a Django Template:

One-To-One Link로 User Model을 확장하는 법

 개인적으로 제가 가장 많이 사용할만큼 추천하는 방법입니다. 우린 앞으로 User Model과 연결된 추가정보를 저장하는 새 Django Model을 생성할 것입니다.

 

 이 방법을 사용하면, 관련 데이터를 검색하기 위한 추가 Query와 Join이 발생합니다. 기본적으로 당신이 관련 데이터에 접근할때마다 Django는 추가 Query를 실행할 것입니다. 하지만 대부분의 경우 이를 피할 수 있습니다. 우선 나중에 다시 설명드리죠.

 

 저는 주로 Profile Model을 아래와 같이 작성합니다.

from django.db import models
from django.contrib.auth.models import User

class Profile(models.Model):
    user = models.OneToOneField(User, on_delete=models.CASCADE)
    bio = models.TextField(max_length=500, blank=True)
    location = models.CharField(max_length=30, blank=True)
    birth_date = models.DateField(null=True, blank=True)

 

 아래에서 우린 User 객체가 생성/업데이트 될때마다 Profile Model이 자동으로 생성/업데이트 될 것입니다.

from django.db import models
from django.contrib.auth.models import User
from django.db.models.signals import post_save
from django.dispatch import receiver

class Profile(models.Model):
    user = models.OneToOneField(User, on_delete=models.CASCADE)
    bio = models.TextField(max_length=500, blank=True)
    location = models.CharField(max_length=30, blank=True)
    birth_date = models.DateField(null=True, blank=True)

@receiver(post_save, sender=User)
def create_user_profile(sender, instance, created, **kwargs):
    if created:
        Profile.objects.create(user=instance)

@receiver(post_save, sender=User)
def save_user_profile(sender, instance, **kwargs):
    instance.profile.save()

 기본적으로 저장 이벤트가 발생할 때마다, create_user_profile 및 save_user_profile 메소드를 User 모델에 연결합니다. 이를 post_save라고합니다.

댓글