自定义保存方法给出无效的元组大小错误

时间:2009-11-11 22:30:00

标签: django django-forms

我一直坚持这个可能非常简单的问题,但是没有得到它(Python和Django的新手)。我正在使用一些用户提交的数据并使用权重来计算分数。尽管我付出了最大的努力,但是当我通过表单提交数据时,我得到以下内容:“未定义全局名称'外观'”。我很确定我的问题是在views.py中,但我不是100%肯定。要么是类型错误,要么只是将得分的计算放在错误的位置。任何帮助深表感谢。这是我的代码:

更新:我在更改使用自定义保存方法的方法后收到的错误是:“从列表或元组创建十进制时无效的元组大小。列表或元组应该具有完全相同三个要素。“。

models.py

# Beer rating weights
APPEARANCE_WEIGHT = 0.15
AROMA_WEIGHT = 0.15
MOUTHFEEL_WEIGHT = 0.10
TASTE_WEIGHT = 0.25
TOTALPACKAGE_WEIGHT = 0.25

SERVING_TYPE = (
('0', 'Choose One'),
('Draft', 'Draft'),
('Bottle', 'Bottle'),
('Can', 'Can'),
)
SCORING = (
(0, ''),
(1, '1'),
(2, '2'),
(3, '3'),
(4, '4'),
(5, '5'),
(6, '6'),
(7, '7'),
(8, '8'),
(9, '9'),
(10, '10'),
)
class Beerrating(models.Model):
beerrated = models.ForeignKey(Beer)
user = models.ForeignKey(User)
date = models.DateTimeField(auto_now_add=True)
servingtype = models.CharField(max_length=10, choices=SERVING_TYPE)
appearance = models.IntegerField(choices=SCORING, default=0)
aroma = models.IntegerField(choices=SCORING, default=0)
mouthfeel = models.IntegerField(choices=SCORING, default=0)
taste = models.IntegerField(choices=SCORING, default=0)
totalpackage = models.IntegerField(choices=SCORING, default=0)
comments = models.TextField()
overallrating = models.DecimalField(max_digits=4, decimal_places=2)

def __unicode__(self):
    return u'%s, %s' % (self.user.username, self.beerrated.beername)

def save(self):
    if not self.id:
        scoredappearance = self.appearance * APPEARANCE_WEIGHT,
        scoredaroma = self.aroma * AROMA_WEIGHT,
        scoredmouthfeel = self.mouthfeel * MOUTHFEEL_WEIGHT,
        scoredtaste = self.taste * TASTE_WEIGHT,
        scoredtotalpackage = self.totalpackage * TOTALPACKAGE_WEIGHT,
        self.overallrating = (scoredappearance +    scoredaroma + 
            scoredmouthfeel + scoredtaste + scoredtotalpackage)
        super(Beerrating, self).save()

forms.py

class BeerReviewForm(ModelForm):
servingtype = forms.CharField(max_length=10,
    label=u'Serving Type',
    widget=forms.Select(choices=SERVING_TYPE)
)
totalpackage = forms.IntegerField(
    label=u'Total Package',
    widget=forms.Select(choices=SCORING)
)
class Meta:
    model = Beerrating
    exclude = ('beerrated', 'user', 'date', 'overallrating')

views.py

def beerreview(request, beer_id):
beer = get_object_or_404(Beer, id=beer_id)
if request.method == 'POST':
    form = BeerReviewForm(request.POST)
    if form.is_valid():
        # Create review
        beerrating = Beerrating(
            beerrated = beer,
            user = request.user,
            servingtype = form.cleaned_data['servingtype'],
            appearance = form.cleaned_data['appearance'],
            scoredappearance = appearance * APPEARANCE_WEIGHT,
            aroma = form.cleaned_data['aroma'],
            scoredaroma = aroma * AROMA_WEIGHT,
            mouthfeel = form.cleaned_data['mouthfeel'],
            scoredmouthfeel = mouthfeel * MOUTHFEEL_WEIGHT,
            taste = form.cleaned_data['taste'],
            scoredtaste = taste * TASTE_WEIGHT,
            totalpackage = form.cleaned_data['totalpackage'],
            scoredtotalpackage = totalpackage * TOTALPACKAGE_WEIGHT,
            comments = form.cleaned_data['comments'],
        )
        beerrating.save()
        return HttpResponseRedirect('/beers/')
else:
    form = BeerReviewForm()
variables = RequestContext(request, {
    'form': form
})
return render_to_response('beer_review.html', variables)

2 个答案:

答案 0 :(得分:1)

错误消息应该专门告诉您错误的文件和行号,但问题是views.py中的这两行:

appearance = form.cleaned_data['appearance'],
scoredappearance = appearance * APPEARANCE_WEIGHT,

您假设Python解释器在您在下一个参数中使用它之前计算appearance的值...这是一个不正确的假设。

在创建模型实例之前定义appearance,然后您的代码应该工作(或至少打破不同的错误)。

答案 1 :(得分:0)

在您的保存方法中,行:

scoredappearance = self.appearance * APPEARANCE_WEIGHT,
...

都是为变量分配元组,而不是您期望的数字。 tuple基本上是一个不可变列表。所有这些线上的训练逗号使它们成为元组。你想要的是:

scoredappearance = self.appearance * APPEARANCE_WEIGHT
...

保存功能还有两个问题。首先,由于你的缩进,你的 super 只会在更新时被调用 - 这意味着你永远无法创建这个对象!

其次,我建议将变量arg列表添加到保存功能中。这意味着如果使用参数调用它们,它们将透明地传递到 super

这是重写的功能:

def save(self,*args,**kwargs):
    if not self.id:
            scoredappearance = self.appearance * APPEARANCE_WEIGHT
            scoredaroma = self.aroma * AROMA_WEIGHT
            scoredmouthfeel = self.mouthfeel * MOUTHFEEL_WEIGHT
            scoredtaste = self.taste * TASTE_WEIGHT
            scoredtotalpackage = self.totalpackage * TOTALPACKAGE_WEIGHT
            self.overallrating = (scoredappearance +        scoredaroma + 
                    scoredmouthfeel + scoredtaste + scoredtotalpackage)

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

作为最后一点 - 如果你已经这样做了,我道歉 - 我真的建议像Learning Python那样写一本书。 Python是一种通常直截了当的语言 - 但它有一些微妙的功能(如元组和变量参数列表),如果你不理解它们会给你带来麻烦。