DJANGO 정참조 역참조

jeong_hyeon·2022년 4월 2일
0

TIL

목록 보기
18/22

예제 Models.py

from multiprocessing.spawn import old_main_modules
from django.db import models

# Create your models here.
class Actors(models.Model):
    first_name = models.CharField(max_length=45)
    last_name = models.CharField(max_length=45)
    date_of_birth = models.DateField()

    class Meta:
        db_table = 'actors'

class Movies(models.Model):
    title = models.CharField(max_length=45)
    relase_data = models.DateField()
    running_time = models.IntegerField()

    class Meta:
        db_table = 'movies'

class actors_movies(models.Model):
    actor = models.ForeignKey('Actors', on_delete=models.CASCADE)
    movie = models.ForeignKey('Movies', on_delete=models.CASCADE)

    class Meta:
        db_table = 'actors_movies'

class Test_acces(models.Model):
    name=models.CharField(max_length=45)
    test=models.OneToOneField('Test', on_delete=models.CASCADE)

class Test(models.Model):
    name=models.CharField(max_length=45)

Query Set 정참조 & 역참조

정참조 : 내가 참조하는 TABLE 접근

해당객체가 다른 객체의 Foreign Key 를 가지고 있거나 1:1 관계인 상황에서 참조하는경우

In [12]: a = Test.objects.get(id=2)
In [13]: b = a.test_acces.name
In [14]: b
Out[14]: 'hello_2'

select_related()없이 바로 relation중인 객체 정보를 볼 수 있다.

그럼어떤 상황에 왜 select_related()를 사용하는 걸까?

Hit(Database에 query를 요청하는 횟수)를 최소화하여 성능을 높인다.

한번의 Hit로 관계데이터를 가져오는 것과 같다.

In [16]: a = Test.objects.**select_related**('test_acces').get(id=3)
In [17]: a
Out[17]: <Test: Test object (3)>
In [18]: a.test_acces.name
Out[18]: 'hello_3'

역참조

나를 참조하는 Table접근

다른 객체가 ForeignKey를 가지고 있거나 N:N 관계인 상황

해당객체를 참조하고 있는 다른 객체를 참조 하려는 경우

Testacces 에서 test에 저장된 name 을 보고 싶은경우

In [20]: a = Testacces.objects.get(id=3)
In [21]: a.tested.name
Out[21]: 'test_3'

역참조 사용 방법

1) 테이블명소문자_set

In [84]: c = Actors.objects.get(id=4)

In [85]: c.actors_movies_set.all()[0].movie.title
Out[85]: 'hello_3'
In [86]: d = Movies.objects.get(id=3)
In [88]: d.actors_movies_set.all()[0].actor.first_name
Out[88]: '3'

_set을안쓸경우

In [87]: d.actors_movies.all()[0].actor.first_name
---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
Input In [87], in <cell line: 1>()
----> 1 d.actors_movies.all()[0].actor.first_name

AttributeError: 'Movies' object has no attribute 'actors_movies'

에러가 발생

2) related_name 지정 & 접근

# 테이블에 related_name이 지정되었을 경우 만 사용가능

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

0개의 댓글