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 #상속받은 모델에서 변경할 사항 없음

좌: 모델등록 전 admin 패널 / 우: 모델 등록 후 admin 패널

 

좌: 등록한 모델 클릭시 나오는 화면 / 우: 데이터 입력할 수 있는 화면

 

 

[데이터 이름 보이게 하기]

  • 모델 데이터가 보여질때 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,) # 적용

action명 적용된 모습

 

 

[** 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에 들어간 정보 받아오기
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