We.TIL 25 : 쿼리셋, 객체, 정참조, 역참조

김기욱·2020년 8월 24일
0

We.TIL

목록 보기
43/69

Sample Model

class Product(models.Model):
    sub_category    = models.ForeignKey('SubCategory',on_delete=models.CASCADE)
    name            = models.CharField(max_length=100)
    price           = models.DecimalField(max_digits=50, decimal_places=2)
    
class Image(models.Model):
    product = models.ForeignKey('Product',on_delete=models.CASCADE)
    image   = models.TextField(max_length=300)

다음과 같은 모델로 이뤄진 데이터베이스가 있다고 생각해보자.

Image는 FK를 통해 Product를 정참조 하고 있으며, 반대로 Product는 Image 클래스를 역참조하고 있다. 이때 image를 가져오는 경우의 수는 두가지다. 하나는 역참조를 활용하는 방법, 두 번째는 역참조를 활용하는 방법이다.

정참조를 활용하는 경우

우선 Product.objects.all()을 실행하게 되면 다음과 같은 형식의 Queryset을 받게된다.

<QuerySet [<Product: Product object (1)>, <Product: Product object (2)>, <Product: Product object (3)>, <Product: Product object (4)>, <Product: Product object (5)>, <Product: Product object (6)>, <Product: Product object (7)>, <Product: Product object (8)>, <Product: Product object (9)>, <Product: Product object (10)>, <Product: Product object (11)>, <Product: Product object (12)>, <Product: Product object (13)>, <Product: Product object (14)>, <Product: Product object (15)>, <Product: Product object (16)>, <Product: Product object (17)>, <Product: Product object (18)>, <Product: Product object (19)>, <Product: Product object (20)>, '...(remaining elements truncated)...']>

ProjectObject라는 객체 전부가 담긴 List가 생성된다.

class Product(models.Model):
    sub_category    = 'Normal coffee'
    name            = 'Americano'
    price           = '$5'
    
class Image(models.Model):
    product = 1
    image   = '고흐 - 자화상'

객체는 쉽게 생각해서 미리 짜놓은 클래스명을 참조해 클래스 안에 담긴 데이터 집합이라고 보면된다. 그러므로 객체.name이라고 dot을 붙이면 '항목=객체명'에 담긴 'name'데이터가 반환된다.

즉, print(객체명.name) == 'Americano'다.

그래서 For loof를 활용 할 때는 쿼리셋을 이용하는게 좋다.
all() 말고 Product.objects.filter()라는 특정 값을 찾는 함수를 써도 쿼리셋이 반환된다.
all이나 filter를 이용해 쿼리셋을 불러온 경우 Product.objects.all()[0] 같이 인덱스를 붙인다면 객체를 불러올 수 있다.

Product.objects.all()[0]은 Product object(1)과 같다.
하지만 함수로 쿼리셋이 아닌 객체 하나를 바로 반환 시키는 경우가 있는데 그것이 바로 Get이다.

Product.objects.get(id=1)을 친다면 쿼리셋이 아닌 id가 1번인 객체 하나를 바로 불러올 수 있다.
즉 Product object(1) = Product.objects.get(id=1) = Product.objects.all()[0] = Product.objects.filter(id=1)[0]과 같다.

본론으로 들어가서 정참조를 활용하는 경우, 즉 Image의 product.name을 가져오고 싶은 경우 다음과 같은 방식으로 파고 들어가면 된다.

첫째. Image 클래스의 객체를 불러온다. 간단하게 get을 활용해보자
imageobject = Image.objects.get(id=1)

두번째. ImageObject에 product_id(FK)에 이름을 써서 불러온다.
imageobject.product.name = 'Americano'

역참조를 활용하는 경우

반대로 Product에 연결되어있는 Image를 불러오고싶다면 어떻게 할까(역참조)
다소 복잡하지만 역참조도 정참조와 크게 다르지않으며 set을 활용하면 된다.
set은 문자 그대로 쿼리셋을 불러온다.

첫째. Product 클래스의 객체를 불러온다.
po = Product.objects.get(id=1)

두번째. ProductObject의 Image_set(쿼리셋)를 불러오고 여기에 get이나 filter로 ImageObject를 부르고 여기에 image항목을 붙여서 불러온다.
po.image_set.get(id=1).image = '고흐-자화상'

profile
어려운 것은 없다, 다만 아직 익숙치않을뿐이다.

0개의 댓글