출처: https://meyouus.tistory.com/64 [정보 공유 - For Me For You For Us]
본문으로 바로가기

이번에는 Django models에서 decorator 중 하나인 @property를 알아보도록 하겠다.

 

다음의 예시를 보자:

# models.py
...
class Product(models.Model):
	name = models.CharField(max_length=200)
	price = models.FloatField()
	digital = models.BooleanField(default=False, null=True, blank=True)
	image = models.ImageField(null=True, blank=True)
...

Django에서 우리가 특정 모델에 사진을 부여하고 싶을 때 이런 식으로 사용할 수 있을 것이다. 또한, 이를 불러오기 위해서는 views.pyhtml template을 다음과 비슷하게 설정을 해야할 것이다:

# views.py
...
def store(request):
	products = Product.objects.all()
	context = {'products':products}
	return render(request, 'store/store.html', context)
<!-- store.html -->
...
	<img class="thumbnail" src={{product.image.url}}>
...

 

이를 통해 다음과 같은 사진을 웹사이트에 표현할 수 있을 것이다:

 

모든 것이 잘 되는 듯 하다. 하지만 만약 우리가 해당 제품에 대한 사진을 업로드 하는 것을 깜빡했다면 어떻게 되는 것일까??

다음과 같은 에러가 발생한다. 따라서 우리는 애초에 사진을 설정해주지 않으면 에러가 발생한다는 것을 알 수 있다. 하지만 만약 우리가 이 에러가 발생하는 것을 막고, 만약 사진이 없다면 기본적으로 특정 사진을 정해주게끔 하고 싶다면어떻게 해야될까?

 

 

※ @property decorator

위에서 원하는 방식을 하려면, @property를 사용하는 방법이 있다 (단순히 함수로 만들수도 있다):

# models.py
...
class Product(models.Model):
	name = models.CharField(max_length=200)
	price = models.FloatField()
	digital = models.BooleanField(default=False, null=True, blank=True)
	image = models.ImageField(null=True, blank=True)
    
	@property
	def imageURL(self):
		try:
			url = self.image.url
		except:
			url = 'images/placeholder.png'
		return url
...

@property decorator는, 메소드를 마치 필드인 것처럼 취급할 수 있게끔 해준다. 즉, html template에서 다음과 같이 불러올 수 있다는 것이다:

<!-- store.html -->
...
	<img class="thumbnail" src={{product.imageURL}}>
...

이런식으로 불러오게 된다면, Product class에 있는 imageURL에서  self.image.url을 찾아보도록 시도를 하고 만약 없다면 바로 images 폴더에 있는 placeholder.png를 불러온다는 것을 알 수 있다.

 

사실 저 @property가 없이 함수만 있어도 html template 에서는 {{ product.imageURL }} 로 불러올 수 있다. 하지만 이렇게 해주는 이유는 @property를 넣음으로써, 함수가 아닌 필드로 불러오기 때문에, views.py에서는 product.imageURL()이 아닌 product.imageURL 과 같은 형식으로 불러올 수 있는 것이다.

 

메소드를 마치 필드인 것처럼 취급할 수 있게끔 하는 것은, 이 외에도 gettersetter 를 사용할때 필요하기도 한데, 이에 대해서는 다음에 getter/setter를 다루어볼 때 함께 다루어볼 수 있도록 하겠다.