6월 TIL

Soo Im·2022년 6월 2일
0

일별 TIL 기록

목록 보기
10/20

2022-06-02

FK로 연결된 모델 필드 읽기

ForeignKey로 다른 테이블의 모델(레코드)을 연결하면 그 모델의 필드도 사용할 수 있다. 예를 들어 User 모델이 name, age 필드를 가지고 이것이 Post 모델에 연결된다고 가정하자.

class Post():
	title = models.TextFiled()
    user = models.ForeignKey("users.User", on_delete = models.CASCADE)
    
    def __str__(self):
    	return self.user.name

이렇게 Post 모델에서 연결된 User 모델의 name 필드를 사용할 수 있다. 연결된 모델에서 또 연결된 모델로 접근할 수도 있다. 만약 User 모델이 Classroom이라는 모델과 연결되어 있으면 self.user.classroom.number 이런 식으로 Classroom 모델의 필드에도 접근 가능하다.

2022-06-06

앱 등록, 모델 설정, 어드민 패널 등록 정리

STEP 1. 앱 등록

  1. 특정 기능을 하는 앱을 만든다. 터미널에서 django-admin startapp 앱 이름
  2. 앱을 만들면 앱 폴더 내에 apps.py라는 파일이 들어있다. 그 안에 class (앱)Config가 있다. 이 클래스는 django.apps로부터 앱의 configuration과 검사 기능을 저장하는 레지스트리를 불러오는 역할을 한다. (문서를 되는대로 번역한 것이라 잘못된 설명일 수도 있음...)
  3. 프로젝트에서 내가 만든 앱을 사용하려면 config 폴더의 settings.py에 앱 configuration을 추가해야 한다. INSTALLED APPS = [...]에 2번에서 본 configuration을 추가한다.
    예를 들어 앱 이름이 user라면 INSTALEED APPS = [..., ..., users.apps.UsersConfig,] 와 같이 입력한다.

STEP 2. 모델 스키마 설정

  1. 앱 폴더의 model.py에서 모델의 필드 등을 설정한다. 보통은 만드려는 모델 클레스를 생성하고 그 안에 필드를 입력하는 방식이다. 예를 들면 다음과 같다.
class User(models.Model):	# 일반적으로 django.db의 models 내 Model 클래스를 상속한다.
	name = models.CharField()
  1. 앱의 모델, 즉 DB 스키마가 바뀌었으니 그것을 프로젝트 DB에 반영해주어야 한다. 터미널에서 python manage.py makemigrations (앱이름)으로 변경된 앱의 모델 클래스 스키마를 반영한 migration을 만들어준다.

    (앱이름)은 특정 앱의 DB 스키마만 변경하고 싶을 때 입력하고, 여러 앱을 한번에 적용하려면 (앱이름)은 빼고 하면 된다.

  2. 5번에서 만든 migration을 실제 프로젝트 DB에 적용한다. 터미널에서 python manage.py migrate

STEP 3. 어드민 패널에 모델 등록

  1. 만약 앱의 모델 클래스를 어드민 패널에서 관리하고 싶다면 앱 폴더의 admin.py에서 모델을 등록해야 한다. 모델 클래스 등록을 위해 models.py를 불러온다. from . import models
  2. 여기서부터 내가 듣는 강의와 공식 튜토리얼에서 모델 클래스를 등록하는 방법이 약간 다른데, 일단 두 가지 다 소개해본다.
  3. 강의에서 사용하는 방법: models.py 내에 생성한 모델 클래스를 등록한다. 만약 user라는 클래스가 있다면 다음과 같다.
from . import models

@admin.register(models.user)
class UserAdmin(admin.UserAdmin):	# 위와 두 줄 이상 띄어쓰면 안 된다.
	pass
  1. 튜토리얼에서 사용하는 방법: models.py 내에 생성한 모델 클래스를 등록한다. 위와 같은 user 클래스를 예시로 들면 다음과 같다.
from . import models

admin.site.register(models.user)

2022-06-07

어드민 패널 편집(보이는 필드, 필터링, 검색)

어드민 패널에서는 모델 클래스의 __str__ 혹은 모델 클래스명이 필드로 나온다. 예를 들어 Room 모델 클래스에서 아무런 __str__을 등록하지 않았다면 Room 어드민 패널은 이렇게 보인다.

패널에서 보이는 정보를 수정하려면 그 앱의 admin.py의 해당 모델 클래스에서 다음과 같이 편집한다.

  1. 패널에서 다른 필드를 보여주려면 list_display에 원하는 필드명을 튜플 혹은 리스트로 준다.
  2. 패널에서 필드를 기준으로 필터링하려면 list_filter에 필드명을 튜플 혹은 리스트로 준다.
  3. 패널에서 필드를 기준으로 검색하려면 search_fileds에 필드명을 튜플 혹은 리스트로 준다.

예를 들어 Room 모델 클래스의 어드민 패널을 변경하려면 다음과 같이 admin.py를 편집한다.

@admin.register(models.Room)
class RoomAdmin(admin.ModelAdmin):
    """Room Admin Definition"""

    list_display = (
        "name",
        "country",
        "city",
    )

    list_filter = (
        "city",
        "country",
    )

    search_fields = (
        "=city",
        "^host__username", # FK 필드로 검색
    )

이렇게 하면 어드민 패널은 이렇게 보인다.

search_fileds 옵션
search_fields에 입력하는 필드명 앞에 =, ^를 붙여 검색 옵션을 줄 수 있다.
=: 검색 문자열과 정확히 일치해야 한다.
^: 검색 문자열로 시작해야 한다.
아무 옵션도 주지 않으면 substring으로 검색한다. 모든 옵션에서 대소문자는 구분하지 않는다.

search_fileds에서 FK 필드로 검색
모델 내에서 FK의 필드를 사용할 때: self.FK모델명.FK필드명 (예: self.user.name)
search_fields에서 FK의 필드를 사용할 때: FK모델명__FK필드명 (예: user__name)

2022-06-13

어드민 패널 편집(M:N 관계 필드 선택, 필드 숨기기)

  1. filter_horizontal
    Many to Many인 필드는 어드민 패널에서 편집하기가 불편하다(여러 모델을 Shift 키를 누른 상태로 클릭해야 다중선택이 된다). 모델 연결을 편리하게 해주는 옵션이 filter_horizontal이다.
    다음과 같이 admin.py를 설정하면 Many to Many 관계인 모델을 아래와 같은 편리한 GUI로 편집할 수 있다.
@admin.register(models.Room)
class RoomAdmin(admin.ModelAdmin):
    filter_horizontal = (
        "amenities",
        "facilities",
        "house_rules",
    )

  1. collapse로 여러 필드 숨기기
    필드 중 일부를 숨기려면 fieldsetsclassescollapse를 넣으면 된다. filedsets은 어드민 패널에서 보이는 필드를 그룹화할 때(fields) 주로 사용하는데, classes에 스타일 클래스를 줘서 그룹의 스타일을 바꿀 수 있다. 아래처럼 작성하면 해당 그룹이 숨겨져서 나온다.
@admin.register(models.Room)
class RoomAdmin(admin.ModelAdmin):
fieldsets = (
        (
        (
            "More About Space",
            {
                "classes": ("collapse",),	# 그룹의 스타일
                "fields": (	# 그룹화할 필드
                    "amenities",
                    "facilities",
                    "house_rules",
                ),
            },
        ),
        ("Last Details", {"fields": ("host",)}),
    )

classes 리스트
문서에 따르면 classes에는 CSS 클래스를 입력할 수 있다. collapsewide는 기본적으로 주어지는 옵션이고, 그 외 본인이 만든 CSS 클래스도 사용할 수 있다.

2022-06-29

Admin Actions

위에서 list_display에 원하는 필드 리스트를 넣어 어드민에서 해당 필드를 바로 볼 수 있다고 했다. 다만 여기에는 Many to Many 관계인 필드를 넣을 수 없다.

잊었을까 다시 보는 ForeignKey vs ManytoMany
ForeignKey 관계인 경우 외부 테이블에서 하나의 값만 가져오지만, ManytoMany에서는 여러 개의 값을 가져올 수 있다.

Many to Many 필드에 여러 개의 값이 있다면 그걸 전부 보여줄 수는 없으니 COUNT처럼 적당히 집계를 해서 보여주어야 한다.
집계 함수는 admin.py의 원하는 클래스 내에서 만들면 된다. 어드민 내 함수는 self, obj라는 파라미터를 자동으로 가지는데 각각 클래스, 모델(DB 내 데이터)을 가리킨다.

    def count_amenities(self, obj):
        print(obj)
        print(obj.amenities.all())
        return None

위 함수를 넣고 어드민 패널을 실행하면 현재 DB에 있는 모델(obj) 각각의 __str__ 과 모델의 amenities 필드 값을 출력한다.

Room No.2
<QuerySet [<Amenity: Shower>]>
Room No.1
<QuerySet []>

QuerySet?

QuerySet은 마치 SQL을 이용한 것처럼 DB의 모델 필드 값을 리스트로 반환한다. 이게 가능한 이유는 장고가 models.py내 클래스를 SQL 없이 모델을 조회할 수 있게 QuerySet API를 제공하기 때문이다.
위에서 사용한 all() 외에도 count(), filter() 등을 이용해 모델을 집계할 수 있다. 위의 경우에는 return obj.amenities.count()를 하면 우리가 원하는대로 개수가 나온다.

위의 예제는 Many to Many로 연결된 여러 개의 값을 조회하는 방법이었다. 거꾸로 말하면 ForeignKey로 역참조된 경우에도 역으로 어떤 값에 연결되었는지 조회하는 것도 가능하다.

A에 B 필드를 FK로 연결할 경우, A는 무조건 하나의 B를 가지지만 B는 여러 A를 가질 수 있다(1:N). 다만 A의 어드민에서는 각 모델이 어떤 B 모델을 가지는지 볼 수 있지만, B의 어드민에서 각 모델이 어떤 A 모델을 가지는지는 확인할 수 없다. 여기서 위의 M:N 관계처럼 QerySet을 사용할 수 있다.

유저(B)가 방(A)에 FK로 연결된 경우를 가정해보자. Soo라는 유저(B의 모델)가 어떤 방을 가지고 있는지 확인하는 방법은 아래와 같다.

soo = User.objects.get(username="Soo")
soo.room_set.all()

이처럼 A_set의 형식으로 어떤 A 모델에 연결되었는지 조회할 수 있다.

2022-06-30

서울ICT 이노베이션 블록체인 기획강의 수강신청 성공했다!! 이제 8월까지... 월화수목금 TIL은 블록체인으로 대체되었다

0개의 댓글