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 = '고흐-자화상'