Можно ли подключить разные объекты-товары к одному договору?
Моя проблема:
Я хочу, чтобы мои Клиенты могли подключать много разных Продуктов к одному Контракту, а код для перечисления всех Продуктов, прикрепленных к Контракту, выглядит грязным.
Мои модели
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 со встроенными наборами запросов
В частности, фрагмент имеет подклассы моделей Meal
Salad(Meal)
http://djangosnippets.org/snippets/1034/
Удачи!
Если вы знаете, что клиент никогда не собирается заказывать Product
почему бы не сделать его абстрактной моделью, а затем просто выполнить сортировку самостоятельно? Доступ к книгам пользователя, автомобилям или уборке дома становится легким в этот момент, потому что вы можете просто использовать c.book_set.all()
, c.car_set.all()
, и так далее.
Вы должны будете выполнить сортировку самостоятельно, если хотите, скажем, список всех Product
с контрактом - но это не сложно написать sorted
Обертка, чтобы поместить все в список для вас, если это то, что вы ищете.