• 카테고리

    질문 & 답변
  • 세부 분야

    웹 개발

  • 해결 여부

    미해결

옵션 설계에 관해서

23.06.30 13:00 작성 23.06.30 13:22 수정 조회수 169

0

이 강의에 있는 소스코드를 조금 수정해서 제가 원하는 서비스를 구현하고 있어요

이 강의에선 상품 모델만 있지만, 상품에 대한 옵션이 있는 서비스이거든요

구체적으로 청소 서비스인데, 청소 옵션으로 "이불빨래, 30분 추가 청소, 등등..."

처음에는 옵션이라는 ,별도의 테이블을 만드는 것을 생각했는데 재사용성에 있어서 그렇게 멋지다는 생각이 안들었어요. 템플릿에서 조회할 때 옵션 테이블을 따로 조회하는 것보다는

product라는 것을 조회하면 그것에 딸린 옵션들을 조회하게끔 설계하고 싶었거든요

 

부모 class --> Product

자식 클래스 ---> CleanProduct, OptionProduct

이렇게 테이블을 구현하고 템플릿에서는 product = Product테이블 인스턴스

이렇게 한 뒤, if ( product==CleanProduct) then 청소 상품임

elif (product ==OptionsProduct) then 옵션 상품임

 

이렇게 하려고 했거든요. Abstract는 이럴 때 쓰는 건 아닌 것 같고 찾아보니 멀티테이블 상속으로 처리를 하더군요. 근데 그것은 오버로딩을 하려면 별도의 유틸을 설치하고 그런 곤란함이 있고... 위 관점이 객체지향적인 관점에선 바람직해보이지만 SQL 관점에선 없는 개념(?)이라 좀 거시기 했습니다. 그래서 아래처럼 구현을 했는데 이게 바람직한 방향인지 궁금합니다

 

//모델
class Category(models.Model):
name = models.CharField(max_length=100, unique=True)

class Product(models.Model):
class Type(models.TextChoices):
SERVICE = "s", "용역"
OPTION = "o", "상품옵션"
PRODUCT = "p", "실물상품"

category = models.ForeignKey(Category, on_delete=models.CASCADE, db_constraint=False, related_name="product_set")
related_product = models.ForeignKey("Product", on_delete=models.CASCADE, db_constraint=False, null=True, blank=True)
type = models.CharField(choices=Type.choices, max_length=20, default="s")
name = models.CharField(max_length=100, db_index=True)
description = models.TextField(blank=True)
price1 = models.PositiveIntegerField() # 0 포함
price2 = models.PositiveIntegerField() # 0 포함
photo = models.ImageField(upload_to="store/product/photo/%Y/%m/%d", null=True, blank=True)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)

class CartProduct(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE, db_constraint=False, related_name="cart_product_set")
product = models.ForeignKey(Product, on_delete=models.CASCADE, db_constraint=False)
quantity = models.PositiveIntegerField(
default=0)

 

//뷰

def cart(request, pk):
product = get_object_or_404(Product, pk=pk)
option_qs= Product.objects.filter(related_product=product)
context={"product":product, "option_qs":option_qs}
return render(request, 'store/cart.html', context)

//템플릿

{{ product }}<hr>
{% for i in option_qs.all %}
{{ i }}<br>
{% endfor %}

 

 

Product안에 타입이라는 필드를 넣었고, Product가 자기 자신을 외래키로 활용하게끔 했어요(related_product)

 

그래서 A라는 상품과 b,c,d라는 옵션이 있다면

(1)A라는 상품을 얻어온다

(2)A라는 상품을 외래키로 갖고 있는 Product를 얻어온다.

하기 위해서요.

 

제가 너무 복잡하고 이상하게 구현하고 있는 건 아닌 지 궁금해요.

(1) 이렇게 외래키로 스스로를 참조해도 되는 것인지

(2) 멀티테이블 상속 방식으로 구현하는 게 나을 것인지?

(3) 더 멋진 방법이 있는 지? (상품 옵션 테이블 설계 관점에서)

너무 세세한 것 까지 여쭤봐서 죄송합니다. 근데 진석님 아니면 물어볼 곳이 없어요 ㅠ.ㅠ

답변 1

답변을 작성해보세요.

0

안녕하세요.

자기 참조를 하는 경우도 많습니다. 관계 모델 지정 시에 "self" 라고 쓰기도 합니다.

데이터베이스와 객체지향 간에는 패러다임의 불일치가 발생할 수 밖에 없습니다. 개발 편의성과 객체지향 중심으로 설계를 하시고, 성능 이슈가 있는 부분은 점진적으로 개선하는 방식이 낫지 않을까 생각이 듭니다. // 은총알은 없고, 어떤 선택이든 Trade off가 있는 것이겠죠.

설명의 맥락을 제가 온전히 잘 이해가 안 되어서요. 다형성을 생각하시는 것이라면, django-polymorphic 라이브러리도 괜찮은 선택지라고 생각합니다.

간략한 그림으로라도 설명해주시면, 제가 질문을 이해하는 데에 도움이 되지 않을까 싶습니다.

화이팅입니다. :-)