Представление модели Django, которая содержит перестановки ForeignKeys - PullRequest
0 голосов
/ 09 февраля 2012

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

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

class Product(models.Model):
    name = models.CharField(max_length=200)

class Test(models.Model):
    product_a = models.ForeignKey(Product, related_name='a_products')
    product_b = models.ForeignKey(Product, related_name='b_products')

class Trial(models.Model):
    test = models.ForeignKey(Test)

    # Is there a more elegant way to represent the fact that these three
    # variables are all a permutation of test.product_a and test.product_b?
    order_1 = models.ForeignKey(Product, related_name='orders_1')
    order_2 = models.ForeignKey(Product, related_name='orders_2')
    order_3 = models.ForeignKey(Product, related_name='orders_3')

Мои модели примерно так настроены. Есть много Trials для одного Test. Trial должен содержать трехэлементную перестановку своих test.product_a и test.product_b. То, как я сейчас это настроил, совсем не отражает этого, и кажется, что оно действительно не элегантное. Я рассмотрел отображение целых чисел на перестановки и сохранение целого числа, соответствующего перестановке, но это тоже не кажется хорошим. Я совсем немного знаю о базах данных, поэтому мне бы хотелось услышать лучший способ структурировать это. Спасибо!

1 Ответ

1 голос
/ 09 февраля 2012

Вам просто нужна пробная версия, чтобы иметь три ссылки на продукты в любой комбинации двух продуктов теста? Я думаю, что ваши определения модели в порядке, но я бы использовал Trial.clean(), чтобы проверить, что каждый из (order_1, order_2, order_3) является одним из (product_a, product_b):

def clean(self):
  super(Trial, self).clean()
  for order in (order_1, order_2, order_3):
    if order not in (self.test.product_a, self.test.product_b):
      raise ValidationError("Order not one of test's products.")

Теперь, если нет разницы во взаимосвязи между тестом и его product_a и взаимосвязью между этим тестом и его product_b, я думаю, что на самом деле должно быть много ко многим. То же самое касается отношений Пробный продукт. Вы можете проверить, что установленные значения соответствуют вашим критериям. Вы могли бы пойти с чем-то вроде этого:

class Test(models.Model):
  products = models.ManyToManyField(Product, related_name='tests')
  def clean(self):
    super(Test, self).clean()
    if self.products.all().count() != 2:
      raise ValidationError('Test should have 2 products')

class Trial(models.Model):
  test = models.ForeignKey(Test)
  orders = models.ManyToManyField(Product, related_name='trials')
  def clean(self):
    super(Trial, self).clean()
    if self.orders.all().count() != 3:
      raise ValidationError('Trial should have 3 orders')
    for product in self.orders.all():
      if product not in self.test.products.all():
        raise ValidationError("Order not one of test's products")

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

product = //some Product
trials = product.trials.all()
tests = product.tests.all()
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...