FrameWork/Django
App Admin
mansoorrr
2024. 7. 12. 10:00
Application(app)에 admin.py는 app을 admin패널에서 어떻게 보이게 할것인지에 대해 설정하는 장소이다.
models.py에 모델을 설정했으면 모델을 admin패널에서 관리할 수 있도록 등록한다.
[admin.py에 model등록]
- 임포트 되어있는 admin패키지를 상속
- 데코레이터를 활용하여 어떤 모델을 admin페이지에 띄울것인지를 명시
- 아래 코드를 입력하고 저장한 후 admin패널에 들어가면 등록한 모델이 보여지는 것을 확인 가능
- 모델에 데이터를 저장할 수 있도록 데이터 추가 버튼이 있고, 해당 버튼을 누르면 모델을 만들때 필드를 정의한 대로 입력가능
from django.contrib import admin
from .models import House
# Register your models here.
@admin.register(House) #상속받은 ModelAdmin은 House모델에 적용됨
class HouseAdmin(admin.ModelAdmin): #admin.ModelAdmin 상속받음
pass #상속받은 모델에서 변경할 사항 없음
[데이터 이름 보이게 하기]
- 모델 데이터가 보여질때 object(1) 형식으로 보여진다.
- 이를 해결하기 위해 python class 문법을 사용한다.
- 데이터가 보여지기 위한 것이므로 models.py에 def __str__(self)를 추가한다.
#-------------------- models.py
class House(models.Model):
''' House model '''
name = models.CharField(max_length=140) # 집의 이름
price_per_night = models.PositiveIntegerField() # 일박 가격
description = models.TextField() # 집의 설명
address = models.CharField(max_length=140) #집의 주소
pets_allowed = models.BooleanField(default=True) #펫 동반 여부
def __str__(self):
return self.name
[admin 패널 커스텀]
- 필터추가, 검색, 정렬, 컬럼추가 등 admin 패널에서 보여질 부분들을 커스텀 함(admin.py)
- 자주 쓰이는 녀석들을 아래 표에 정리
- 장고에서는 []를 거의 쓰지 않고 ()을 사용함. 대신 마지막에 꼭 ','를 넣어주는것이 좋음
번호 | 내용 | 코드 | 비고 |
1 | 모델의 필드(컬럼) 보기 | list_display = () | 필드명 작성 |
2 | 필드를 필터로 사용하기 | list_filter = () | 필드명 작성 |
3 | 검색기능 | search_field = () | 필드명 작성 필드명__startswith |
4 | 데이터에 링크걸기 | list_display_links = () | 필드명 작성 |
5 | 보여지는 것에서 바로 수정하기 | list_editable = () | 필드명 작성 |
6 | 수정 불가능한 읽기 필드만 보이게 하 | readonly_fields = () | 필드명 작성 |
Django 문서 | Django 문서
The web framework for perfectionists with deadlines.
docs.djangoproject.com
[**모델에 들어있지 않은 필드 보이게 하기**]
- 현재 상태인데 여기에 amenities 갯수를 나타내는 컬럼을 만들고자 함
- 모델에 존재하지 않는 필드를 admin패널에 보이기 위해서는 두가지 방법(ORM활용)이 있다.
- models.py에 필드를 새로 만드는 방법
- admin.py에 패널에만 보이는 필드를 만드는법
#-------------------- rooms/models.py에 만드는 법
class Room(CommonModel):
'''Room definition'''
class RoomKindChoice(models.TextChoices):
ENTIRE_PLACE = ('entire_place', 'Entire Place')
PRIVATE_ROOM = ('private_room', 'Private Room')
SHARED_ROOM = ('shared_room', 'Shared Room')
name = models.CharField(max_length=100,)
kind = models.CharField(max_length=50, choices=RoomKindChoice.choices,)
owner = models.ForeignKey('users.User', on_delete=models.CASCADE,)
amenities = models.ManyToManyField('rooms.Amenity', related_name='rooms',)
category = models.ForeignKey('categories.Category', on_delete=models.SET_NULL, null=True, blank=True,)
def __str__(self) -> str:
return self.name
def total_amenities(self):
print(self.name, self.price)
return self.amenities.count()
#-------------------- rooms/admin.py에 만드는법
@admin.register(Room)
class RoomAdmin(admin.ModelAdmin):
list_display = (
"name",
"price",
"kind",
"total_amenities",
"owner",
"created_at",
)
list_filter = (
"country",
"city",
"kind",
"amenities",
"created_at",
"modified_at",
)
readonly_fields = (
"created_at",
"modified_at",
)
def total_amenities(self, room):
return room.amenities.count()
[**Search Field Custom**]
- admin 패널에서 검색창을 둘 수 있음(search_field = (필드명1, 필드명2))
- 검색창은 기본적으로 __contains이다.
- startWith, endWith, equal등으로 커스텀 가능
- ForeignKey를 통해서도 검색할 수 있도록 커스텀 가능
@admin.register(Room)
class RoomAdmin(admin.ModelAdmin):
list_display = (
"name",
"price",
"kind",
"total_amenities",
'rating',
"owner",
"created_at",
)
# search field custom
search_fields = ('owner__username', '^name', '=price')
'''
1. ^name: startWith(해당단어로 시작)
2. =price: equal(정확히일치)
3. 필드명1__필드명2: 필드명1에 foreignkey로 연결되어있는 모델의 필드명2
4. name__contains: 포함(default)
'''
[**Action Custom**]
- admin패널에서 action을 설정할 수 있다(actions=(필드명1, 필드명2))
- 추가적으로 method를 만들어 action에 적용 가능 함
- 추가방법 및 순서
- @admin.action(description=<admin패널에서 확인할 action이름>): 데코레이터를 사용해 action명 지정
- def <매서드명>(admin class, request, querysets): @admin.action데코레이터는 3개의 parameter를 받음
- admin class: 본 매서드를 적용할 admin클래스
- request: 실행이 일어났을때 request
- querysets: 선택한 데이터들
- admin클래스에 선언한 매서드를 적용 actions = (매서드,)
#---------- 매서드 선언
@admin.action(description='price zero') # action이름
def price_zero(modelAdmin, request, querysets):
for room in querysets.all():
room.price = 0
room.save()
#---------- 클래스에 적용
@admin.register(Room)
class RoomAdmin(admin.ModelAdmin):
actions = (price_zero,) # 적용
[** Filter Custom ** ]
- 필터는 list_filter 를 통해 명시한다.
- 필터는 ForeignKey로도 설정할 수 있다.
- list_filter = (user__is_host,
- 필터를 커스텀할일은 거의 없으나 한번 알아본다.
- SimpleListFilter를 상속받음
- title: 필터 이름
- parameter_name: url에 들어갈 파라미터 이름
- lookups(self, request, model_admin) -> list[tuple[Any, str]]
- 필터에 적용될 데이터 [('url에 들어갈 데이터', '화면에 보여질 필터명')]
- queryset(self, request, queryset) -> QuerySet
- self.value(): url에 들어간 정보 받아오기
- SimpleListFilter를 상속받음
class WordFilter(admin.SimpleListFilter):
title = "Filter word"
parameter_name = "word"
def lookups(self, request: Any, model_admin: Any) -> list[tuple[Any, str]]:
return [
('good', 'Good'),
('asss', 'Asss'),
('awsome', 'Awsome'),
]
def queryset(self, request: Any, queryset: QuerySet[Any]) -> QuerySet[Any] | None:
word = self.value()
if word:
return queryset.filter(payload__contains=word)
else:
return queryset