Заполнение значения по умолчанию из другой таблицы - PullRequest
0 голосов
/ 05 мая 2011

Здесь немного убыток.По сути, у меня есть страница «Продукт» в разделе администратора, а внизу у меня есть TabularInline, которая позволяет мне выбирать размеры для продукта и устанавливать цену.Это работает, но я пытаюсь получить его так, чтобы оно вытягивало цену по умолчанию из таблицы размеров в качестве начального значения.

Я попробовал следующее:

class Size(models.Model):
    name = models.CharField(max_length=50)
    default_price = models.DecimalField(max_digits=9, decimal_places=2)
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now_add=True)

    class Meta:
        db_table = 'sizes'
        ordering = ['-created_at']
        verbose_name_plural = 'Sizes'

    def __unicode__(self):
        return self.name

    def default_price(self):
        return self.default_price

И затем

class ProductOption(models.Model):
    product = models.ForeignKey(Product)
    size = models.ForeignKey(Size)
    price = models.DecimalField(max_digits=9, decimal_places=2, default=Size.default_price)
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now_add=True)

Это подтверждает, но когда я загружаю страницу администратора, я получаю следующее:

необязательный метод get_default_price () должен вызываться с экземпляром Size в качестве первого аргумента (вместо этого ничего не получил)

Не уверен, куда еще идти отсюда.Я всегда просматривал документы Django, пытаясь найти что-то еще, чтобы попробовать.Есть идеи?

Ответы [ 2 ]

0 голосов
/ 05 мая 2011

У вас есть несколько вопросов здесь:

Size.default_price является вызываемым объектом, поэтому python пытается вызвать его при установке значения по умолчанию для вашего ProductOption. То, что вы можете искать:

class Size(models.Model):
    # Other stuff here
    @property
    def default_price(self):
        return self.default_price

Однако тогда это вызывает другую, более глубокую ошибку. Если у вас было следующее:

size = Size()
size.default_price

Вы бы получили StackOverflow из-за бесконечной рекурсии. Это свойство называет себя. Решение состоит в том, чтобы имя свойства отличалось от атрибута, или в этом простейшем случае оно уже действует как свойство. Вы можете просто удалить все определение default_price.

Однако вы вызываете Size.default_price, который ни к чему не привязан, если вы вызываете его на Size, классе, а не на экземпляре этого класса.

То, что вы на самом деле хотите сделать, это то, что предлагает Иссак Келли, но более того.

class ProductOption(models.Model):
    # column definitions

    def __init__(self, *args, **kwargs):
        super(ProductOption, self).__init__(*args, **kwargs)
        if self.size and not self.price:
            self.price = self.size.default_price

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

Вы также можете выполнить эту проверку во время сохранения, иначе:

po = ProductOption()
po.size = Size.objects.get(pk=1)
po.save()
# po.price is not set now!

po = ProductOption.objects.get(pk=po.pk)
# po.price is set now!

Итак, вы можете иметь следующее:

class ProductOption(models.Model):
    # columns

    def __init__(self, *args, **kwargs):
        super(ProductOption, self).__init__(*args, **kwargs)
        self.set_default_price()

    def save(self, *args, **kwargs):
        self.set_default_price()
        super(ProductOption, self).save(*args, **kwargs)

    def set_default_price(self):
        if self.size and not self.price:
            self.price = self.size.default_price

Обратите внимание на различие в порядке вызова super (): при инициализации объекта мы сначала хотим вызвать __init__ родительского объекта, но при сохранении мы хотим (возможно) сначала установить значение по умолчанию, а затем вызвать метод save родительского класса.

0 голосов
/ 05 мая 2011

Таким образом, вы можете переопределить метод сохранения, и, если self.id отсутствует, вы можете сначала заполнить некоторые другие поля, вот что мне показалось лучшим решением.

просто в качестве примера:

def save(*args, **kwargs):
    if not self.id:
        self.size = SomeOtherModel.objects.get(pk=size)

    super(Size, self).save(*args, **kwargs)
...