backend django 역참조 데이터 가져오기

eunji hwang·2020년 4월 16일
6

BACKEND-PYTHON-DJANGO

목록 보기
15/28

역참조

데이터베이스 테이블에서 Foreign Key(이하 FK)가 없고 다른테이블의 FK로 지정된 테이블일때, 나를 참조하는(나를 FK로 지정한) 테이블에 접근하는 것

예제 DB 구조

# 유저목록 테이블, 사용자이름과 비밀번호 저장한다.
class User(models.Model):
    # PK, unique, AI 자동생성
    # 직접 지정 : id = models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)
    user_name   = models.CharField(max_length=50)
    password    = models.CharField(max_length=200)
    create_at   = models.DateTimeField(auto_now_add=True)
    update_at   = models.DateTimeField(auto_now=True)
    # 지금 User테이블에서 userprofile이 역참조 되고 있다. 사용하기 불편쓰!!..
    # User가 Userprofile을 정참조하는것이 데이터 접근 이 용이하다.. 코드도 쉽공
    class Meta:
        db_table = 'users'

# 유저의 사진과, 자기소개 글이 등록된 테이블 유저테이블의 1:1관계
class UserProfile(models.Model):
    user        = models.ForeignKey(User, on_delete=models.CASCADE, related_name='user_uniq_id')
    # ! related_name은 역참조시 사용, 지정하지 않으면 기본 역참조는 테이블명소문자_set으로 역참조를 찾아간다.
    image_url   = models.CharField(max_length=300, null=True)
    description = models.CharField(max_length=100, null=True)
    create_at   = models.DateTimeField(auto_now_add=True)
    update_at   = models.DateTimeField(auto_now=True)

    class Meta:
        db_table = 'user_profile'

# 인스타그램 피드 테이블, 유저의 이름, 프로필사진, 댓글 정보를 외부에서 가져와야 한다.
class Feed(models.Model):
    user         = models.ForeignKey('account.User', on_delete = models.CASCADE, related_name = 'author')
                   # ? user, user_profile이 1:1일때 굳이 user_profile컬럼을 추가할 필요없다..! 
                   # user_profile = models.ForeignKey('account.UserProfile', on_delete = models.SET_NULL, null = True, related_name = 'avatar')
    image_url    = models.CharField(max_length = 300, verbose_name = 'image')
    content      = models.TextField(verbose_name = 'content')
    like         = models.IntegerField(verbose_name = 'likes', null = True)
    create_at    = models.DateTimeField(auto_now_add = True)
    update_at    = models.DateTimeField(auto_now = True)
    comment      = models.ManyToManyField('Comment', through = 'FeedComment', related_name = 'feed_comment')
    feed         = models.ManyToManyField('Feed', through = 'FeedComment', related_name = 'comment_feed')

    class Meta:
        db_table = 'feeds'

위 DB모델 구조는 User와 UserProfile의 참조방향이 잘못되어 있어 테이블에 접근방식이 복잡해졌다. (User테이블에 FK로 UserProfile을 두었으면 편한뎅..) 하지만 접근 할 수는 있기 때문에 그 방법을 알아보자!

역참조 데이터 얻기

1) 테이블명소문자_set

# 테이블에 related_name이 없이 역참조 되었을때
>>> feed.user.userprofile_set.all() 
>>> feed.user.userprofile_set.filter(user_id=feed.user.id)[0].image_url 
# 유저 프로필 사진url이 출력된다.
# 테이블에 related_name이 지정되었을 경우

# 위 _set 방식과 동일한 결과를 출력한다.
>>> feed.user.user_uniq_id.all()
>>> feed.user.user_uniq_id.filter(user_id=feed.user.id)[0].image_url
  • <현재테이블>.<FK인 user컬럼>.<역참조관계명>.all()
  • UserProfile에서 내가 필요한 정보는 유저의 프로필 사진이다. 그러므로 filter() 셀렉터를 통해 user_id가 feed.user.id(피드작성자의아이디) 와 동일한 컬럼을 찾아서 리턴받는다.
  • filter(), all()은 쿼리셋 배열<QuerySet [num]>을 리턴하기 때문에 인덱싱을 먼저 한뒤 객체 내용을 검색 할 수 있다.
  • get()의 경우 쿼리셋 오브젝트 <QuerySet Object>를 리턴한다.
  • values()의 경우 딕셔너리를 반환한다.
profile
TIL 기록 블로그 :: 문제가 있는 글엔 댓글 부탁드려요!

0개의 댓글