Можно ли подключить разные объекты-товары к одному договору?

Моя проблема:
Я хочу, чтобы мои Клиенты могли подключать много разных Продуктов к одному Контракту, а код для перечисления всех Продуктов, прикрепленных к Контракту, выглядит грязным.

Мои модели

class Contract(models.Model):
    # The contract, a customer can have many contracts
    customer = models.ForeignKey(Customer)


class Product(models.Model):
    # A contract can have many different products
    contract = models.ForeignKey(Contract)
    start_fee = models.PositiveIntegerField()

# A customer may have ordered a Car, a Book and a HouseCleaning, 
# 3 completly different Products

class Car(Product):
    brand = models.CharField(max_length=32)

class Book(Product):
    author = models.ForeignKey(Author)

class HouseCleaning(Product):
    address = models.TextField()

Чтобы перечислить все продукты, связанные с контрактом, код выглядит примерно так:

c = Contract.objects.get(pk=1)
for product in c.product_set.all():
    print product.book # Will raise an Exception if this product isnt a Book

Я не могу найти какой-либо вменяемый способ узнать, что это за продукт!

Мое текущее решение
Я решил это так... но весь этот беспорядок кажется... неправильным. Я был бы рад любым указателям в правильном направлении.

class Product(models.Model):
    # (as above + this method)

    def getit(self):
        current_module = sys.modules[__name__]
        classes = [ obj for name, obj in inspect.getmembers(current_module)
                    if inspect.isclass(obj) and Product in obj.__bases__ ]

        for prodclass in classes:
            classname = prodclass.__name__.lower()
            if hasattr(self, classname):
                return getattr(self, classname)

        raise Exception("No subproduct attached to Product") 

Так что я могу получить каждый конкретный продукт, как это (псевдо-код):

c = Contract.objects.get(pk=1)
for product in c.product_set.all():
    print product.getit()

перечислить все "настоящие" продукты, а не только экземпляр базового продукта.

С чем мне нужна помощь
Предложения сделать это каким-то вменяемым способом.
Я не возражаю против того, чтобы абстрагироваться от всего нескольких шагов, просто чтобы получить более чистый код.

2 ответа

Решение

Этот другой вопрос стека выглядит напрямую связанным - может быть, это поможет?

>>> Product.objects.all()
[<SimpleProduct: ...>, <OtherProduct: ...>, <BlueProduct: ...>, ...]

Подклассные модели django со встроенными наборами запросов

В частности, фрагмент имеет подклассы моделей MealSalad(Meal)

http://djangosnippets.org/snippets/1034/

Удачи!

Если вы знаете, что клиент никогда не собирается заказывать Productпочему бы не сделать его абстрактной моделью, а затем просто выполнить сортировку самостоятельно? Доступ к книгам пользователя, автомобилям или уборке дома становится легким в этот момент, потому что вы можете просто использовать c.book_set.all(), c.car_set.all(), и так далее.

Вы должны будете выполнить сортировку самостоятельно, если хотите, скажем, список всех Productс контрактом - но это не сложно написать sorted Обертка, чтобы поместить все в список для вас, если это то, что вы ищете.

Другие вопросы по тегам