: admin 페이지에서 유저를 생성하기위해 필요 (password가 해싱된 값으로 저장됨)
# user/admin.py
from django.contrib.auth.admin import UserAdmin as BaseUserAdmin
class UserAdmin(BaseUserAdmin):
list_display = ('id', 'username', 'fullname', 'email')
list_display_links = ('username', )
list_filter = ('username', )
search_fields = ('username', 'email', )
fieldsets = (
("info", {'fields': ('username', 'password', 'email', 'fullname', 'join_date',)}),
('Permissions', {'fields': ('is_admin', 'is_active', )}),)
filter_horizontal = []
def get_readonly_fields(self, request, obj=None):
if obj:
return ('username', 'join_date', )
else:
return ('join_date', )
admin.site.register(User, UserAdmin)
: 역참조된 object를 보여줄 수 있음
# user/admin.py
# 사용 방법은 TabulaInline과 StackedInline 모두 동일
# 둘 다 사용해보고 뭐가 좋은지 비교해보기
# class UserProfileInline(admin.TabularInline):
class UserProfileInline(admin.StackedInline):
model = UserProfile
class UserAdmin(admin.ModelAdmin):
...
inlines = (
UserProfileInline,
)
: admin 페이지에서 해당 object에 대한 수정/생성/삭제 권한 설정 가능
# user/admin.py
class UserAdmin(admin.ModelAdmin):
...
def has_add_permission(self, request, obj=None): # 추가 권한
return False
def has_delete_permission(self, request, obj=None): # 삭제 권한
return False
def has_change_permission(self, request, obj=None): # 수정 권한
return False
: method 별로 permission 설정 가능
# permissions.py
from rest_framework.permissions import BasePermission
from rest_framework.exceptions import APIException
from rest_framework import status
class GenericAPIException(APIException):
def __init__(self, status_code, detail=None, code=None):
self.status_code=status_code
super().__init__(detail=detail, code=code)
class IsAdminOrIsAuthenticatedReadOnly(BasePermission):
"""
admin 사용자는 모두 가능, 로그인 사용자는 조회만 가능
"""
SAFE_METHODS = ('GET', )
message = '접근 권한이 없습니다.'
def has_permission(self, request, view):
user = request.user
if not user.is_authenticated:
response ={
"detail": "서비스를 이용하기 위해 로그인 해주세요.",
}
raise GenericAPIException(status_code=status.HTTP_401_UNAUTHORIZED, detail=response)
if user.is_authenticated and user.is_admin:
return True
if user.is_authenticated and request.method in self.SAFE_METHODS:
return True
return False
: 특정 string이 포함된 object 찾기
# fullname에 "이름"이라는 string이 포함된 사용자들을 찾는다.
UserModel.objects.filter(fullname__contains="이름")
: 특정 string으로 시작하는/끝나는 object 찾기
# email이 "@naver.com"으로 끝나는 사용자들을 찾는다.
UserModel.objects.filter(email__endswith="@naver.com")
: 특정 값보다 크거나/작거나/크거나같거나/작거나같은 object 찾기
# 사용자 프로필의 나이가 19 이상인 사용자들을 찾는다.
UserProfileModel.objects.filter(age__gte=19)
: 특정 list에 포함된 object 찾기
# 사용자 프로필의 운동 혹은 독서를 취미로 가진 사용자들을 찾는다.
UserProfileModel.objects.filter(hobby__name__in=["운동", "독서"])
https://docs.djangoproject.com/en/4.0/ref/models/querysets/#field-lookups
: queryset을 정렬하여 가져오기
User.objects.all().order_by("join_date") # 가입일 순 정렬
User.objects.all().order_by("-join_date") # 가입일 역순 정렬
User.objects.all().order_by("?") # 랜덤 셔플
from django.db.models.query_utils import Q
class UserView(APIView)
def get(self, request):
# 취미 중 산책이 있거나 나이가 19살보다 많고 김씨인 사람만 필터 사람만 필터
qyery = Q(hobby__name="산책") | Q(age__gt=19, user__name__startswith="김")
# 취미 중 산책이 있으면서 나이가 19살보다 많은 사람만 필터
qyery = Q(hobby__name="산책") & Q(age__gt=19)
user_profile_list = UserProfileModel.objects.filter(qyery)