https://docs.djangoproject.com/ko/4.2/intro/tutorial07/
저의 유저 모델과 유저 모델을 관리하는 매니저를 어드민 페이지에 등록하기 위해
다음과 같이 작업 하였습니다.
1. user/models.py 에 유저와 유저매니저 클래스 - 제가 필요한 필드값들을 직접 만들었습니다.
2. user/forms.py 에 유저를 생성할때와 수정할 때 클래스 - 공식 문서를 참고해서, 가져왔습니다.
3. user/admin.py 에 유저 어드민 페이지에 등록하기 - 필요한 것들을 커스터 마이징 해보았습니다.
user/models.py에 유저와 유저매니저 클래스를 작성해줍니다.
유저매니저 모델은
일반 유저와 슈퍼유저를 생성할 때 필요한 것들을 작성해주고
유저 모델은
유저에게 필요한 필드들과 조건들, 유저를 생성할 때 필요한
계정, 비밀번호, 필요한 필드들을 설정해줍니다.
(Django 인증 커스터마이징 하기, 공식 문서를 참고했습니다. )
from django.db import models
from django.contrib.auth.models import BaseUserManager
from django.contrib.auth.models import AbstractUser
class UserManager(BaseUserManager):
# 유저를 생성하는 함수
def create_user(self, email, account, username, 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),
account=account,
username=username,
)
user.set_password(password)
user.save(using=self._db)
return user
# 슈퍼 유저를 생성하는 함수. python3 manage.py createsuperuser 할때
def create_superuser(self, email, account, username, password=None):
"""
Creates and saves a superuser with the given email, date of
birth and password.
"""
# 슈퍼 유저를 생성할 때, 입력해야 하는 값들 + 비밀번호는 무조건 입력해야함
user = self.create_user(
email,
password=password,
account=account,
username=username,
)
user.is_admin = True # 슈퍼 유저는 관리자 권한이 있음
user.save(using=self._db)
return user
class User(AbstractUser):
# 메타 클래스는, DB 정보들에 대한 정보를 입력하는 곳
class Meta:
db_table = "my_user" # DB 테이블 이름을 my_user 로 설정해줌
email = models.EmailField(
verbose_name='이메일',
max_length=255,
unique=True,
)
GENDERS = (
('Men', 'Men'),
('Women', 'Women'),
)
# Email , account 는 unique 해야 한다.
account = models.CharField("계정이름", null=False, max_length=50, unique=True)
age = models.PositiveIntegerField("나이", null=True)
username = models.CharField("유저이름", null=False, blank=False, max_length=50)
gender = models.CharField("성별", choices=GENDERS, max_length=10)
introduction = models.TextField("자기소개", null=True, blank=True)
profile_img = models.ImageField(
"프로필 이미지",
upload_to='users/%Y%m%d',
# height_field=None,
# width_field=None,
# max_length=None,
# default='static/img/die1_1.png', # default 이미지
# default='default/die1_1.png', # default 이미지
blank=True,
)
followings = models.ManyToManyField(
"self", symmetrical=False, related_name='followers', blank=True)
# symmetrical 대칭 여부 False, 팔로우와 팔로워가 필요충분은 아님
created_at = models.DateField("계정 생성일", auto_now_add=True)
is_active = models.BooleanField("활성화 여부", default=True)
is_admin = models.BooleanField("관리자 여부", default=False)
objects = UserManager() #쿼리셋 매니저가 UserManager임을 밝힘
# USERNAME_FIELD 와 REQUIRED_FIELDS는 유저를 생성할 때, 필요한 필드이기 때문에 create_user 및 create_superuser시 필드를 추가시켜 줘야 함
USERNAME_FIELD = 'account' # 회원가입시, 계정이름으로 가입하기 때문에, Unique=True 로 해주어야 하는 필드
REQUIRED_FIELDS = ['email', 'username',]
def __str__(self):
return str(self.username)
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
user/forms.py 에
유저를 생성할 때 폼 형식과 유저 정보를 수정할 때 폼 형식을
커스터 마이징 해줍니다.
from django import forms
from django.core.exceptions import ValidationError
from .models import User
from django.contrib.auth.forms import ReadOnlyPasswordHashField
class UserCreationForm(forms.ModelForm):
"""A form for creating new users. Includes all the required
fields, plus a repeated password."""
password1 = forms.CharField(label="Password", widget=forms.PasswordInput)
password2 = forms.CharField(
label="Password confirmation", widget=forms.PasswordInput
)
class Meta:
model = User
fields = ["email"]
def clean_password2(self):
# Check that the two password entries match
password1 = self.cleaned_data.get("password1")
password2 = self.cleaned_data.get("password2")
if password1 and password2 and password1 != password2:
raise ValidationError("Passwords don't match")
return password2
def save(self, commit=True):
# Save the provided password in hashed format
user = super().save(commit=False)
user.set_password(self.cleaned_data["password1"])
if commit:
user.save()
return user
class UserChangeForm(forms.ModelForm):
"""A form for updating users. Includes all the fields on
the user, but replaces the password field with admin's
disabled password hash display field.
"""
password = ReadOnlyPasswordHashField()
class Meta:
model = User
fields = ["password", "is_active", "is_admin"]
user/admins.py 에
admin 페이지에
from django.contrib import admin
from .models import User
from django.contrib.auth.admin import UserAdmin as BaseUserAdmin
from user.forms import UserCreationForm, UserChangeForm
# Register your models here.
# Now register the new UserAdmin...
class MyUserAdmin(BaseUserAdmin):
# The forms to add and change user instances
form = UserChangeForm
add_form = UserCreationForm
# The fields to be used in displaying the User model.
# These override the definitions on the base UserAdmin
# that reference specific fields on auth.User.
list_display = ["id", "account", "email", "username",
"age", "gender","is_active", "is_admin", "created_at",]
list_filter = ["is_active", "is_admin"]
fieldsets = [
("User Information", {"fields": ["account", "username", "age", "gender", "password", "followings", ]}),
("Permissions", {"fields": ["is_active", "is_admin"]}),
]
# add_fieldsets is not a standard ModelAdmin attribute. UserAdmin
# overrides get_fieldsets to use this attribute when creating a user.
add_fieldsets = [
(
None,
{
"classes": ["wide"],
"fields": ["account", "email", "password1", "password2"],
},
),
]
search_fields = ["account"]
ordering = ["id"]
filter_horizontal = []
admin.site.register(User, MyUserAdmin)
에 대한 자세한 설명을 드리겠습니다.
form = UserChangeForm
add_form = UserCreationForm
말 그대로, 유저 수정 폼과 유저 생성 폼을 설정해줍니다.
list_display
list_display = ["id", "account", "email", "username",
"age", "gender","is_active", "is_admin", "created_at",]
list_display 는 admin 페이지에서 user 에 들어갔을 때
유저 정보들을 보여주는 row를 의미합니다. 사진으로 보여드리겠습니다.
list_filter
list_filter = ["is_active", "is_admin"]
list_filter 는 오른쪽 칸에 필터칸을 의미합니다.
활성화 여부와, 관리자 여부를 필터할 수 있습니다.
fieldsets = [
("User Information", {"fields": ["account", "username", "age", "gender", "password", "followings", ]}),
("Permissions", {"fields": ["is_active", "is_admin"]}),
]
fieldsets은 각각의 유저들에 대한 정보들을
어떻게 보여줄 지에 대한 설정인데
여기서는 크게 User Information과 Permissions라는 카테고리로 나눠서
필드들을 보여주고 있습니다.
사진은 다음과 같습니다.
models.py 에 각 필드들에 대한 이름들을
email = models.EmailField(
verbose_name='이메일',
max_length=255,
unique=True,
)
GENDERS = (
('Men', 'Men'),
('Women', 'Women'),
)
# Email , account 는 unique 해야 한다.
account = models.CharField("계정이름", null=False, max_length=50, unique=True)
age = models.PositiveIntegerField("나이", null=True)
username = models.CharField("유저이름", null=False, blank=False, max_length=50)
gender = models.CharField("성별", choices=GENDERS, max_length=10)
introduction = models.TextField("자기소개", null=True, blank=True)
profile_img = models.ImageField(
"프로필 이미지",
upload_to='users/%Y%m%d',
# height_field=None,
# width_field=None,
# max_length=None,
# default='static/img/die1_1.png', # default 이미지
# default='default/die1_1.png', # default 이미지
blank=True,
)
followings = models.ManyToManyField(
"self", symmetrical=False, related_name='followers', blank=True)
# symmetrical 대칭 여부 False, 팔로우와 팔로워가 필요충분은 아님
created_at = models.DateField("계정 생성일", auto_now_add=True)
is_active = models.BooleanField("활성화 여부", default=True)
is_admin = models.BooleanField("관리자 여부", default=False)
다음과 같이 저장해두었기 때문에, admin페이지에서도 변경된 이름으로 나오게 됩니다.
add_fieldsets
add_fieldsets = [
(
None,
{
"classes": ["wide"],
"fields": ["account", "email", "password1", "password2"],
},
),
]
"classes": ["wide"],의 의미는 어떤 것인지 잘 모르겠지만
여기서 fields의 값들이 다음과 같이 4개의 필드가 있기 때문에
유저를 생성할 때, 4개의 필드를 입력해야 함을
다음 사진으로 보아 알 수 있습니다.
search_fields
search_fields = ["account"]
search_fields는 유저를 검색할 때, 원하는 필드를 설정해주는 값입니다.
현재는 account로 설정되어 있기 때문에
계정 이름에 대한 검색을 할 수 있게 됩니다.
popk를 검색하게 되면
다음과 같이 두 유저의 정보들을 모아 볼 수 있습니다.
ordering
ordering은 정리하는 순서를 의미합니다.
ordering = ["id"]
지금은 id 를 기준으로, 순서를 정했지만
ordering = ["account"]
account를 기준으로 정렬하면
알파벳 순서로 유저들이 정렬됩니다.
마지막으로
filter_horizontal = []
admin.site.register(User, MyUserAdmin)
filter_horizontal = [] 은 아직 써보지 못해서, 어떤 코드인지 잘 모르겠고
admin.site.register(User, MyUserAdmin) 은
장고 어드민 페이지에, User 모델과 유저모델을 관리하는 MyUserAdmin를 등록하는 것입니다.
추후 다른 모델들도 추가해서, 어드민 페이지를 통해 백 오피스 환경을 만들어보려 합니다.
깃 허브 링크도 내일 추가하겠습니다.
'부트캠프TIL, WIL > AI웹개발(스파르타코딩클럽)' 카테고리의 다른 글
[AI웹개발][59일차TIL] 최종프로젝트 우신사 S.A (0) | 2023.06.07 |
---|---|
[AI웹개발][58일차TIL] [쇼핑몰ERD] 우신사 ERD 해보기 (0) | 2023.06.07 |
[AI웹개발][55일차TIL] Django 에서 Simple-JWT(Json Web Token) 토큰 인증 방식 적용하기 (0) | 2023.06.03 |
[AI웹개발][57일차TIL] 팀 프로젝트 HTML, CSS, JS조금... 거의 완성 (0) | 2023.05.25 |
[AI웹개발][52일차TIL] 파이썬, 장고, DRF 복습 2일차 (2) | 2023.05.20 |