python - 表单返回 <django.db.models.query_utils.DeferredAttribute object at 0x10e6ee898>

标签 python django

免责声明:我对 Django 相当陌生(试图自学),目前正在尝试获取一个几乎没有文档的包 https://github.com/byteweaver/django-coupons为我正在构建的应用程序工作。

我正在尝试兑换我在后端创建的优惠券,但遇到了一些非常奇怪的错误。当我提交表单时 <django.db.models.query_utils.DeferredAttribute object at 0x10e6ee898>返回到表单框中,我收到“此代码无效”错误。任何有关这方面的帮助将不胜感激,因为我已经用头撞墙几个小时了。

View .py

def gift_card(request):

user = request.user

if request.user.is_authenticated:
    edit_profile = EditProfileForm(user=user)
    redeem = CouponForm()
    if request.method == 'POST':
        edit_profile = EditProfileForm(request.POST, user=user)
        redeem = CouponForm(request.POST, user=user)
        if redeem.is_valid():
            Coupon.redeem(request.POST, user=user)
        else:
            edit_profile = EditProfileForm(user=user)
        return render(request, 'main/profile.html', {'edit_profile': edit_profile, 'redeem': redeem})

    return render(request, 'main/profile.html', {'edit_profile': edit_profile, 'redeem': redeem})
else:
    return redirect('/')

表单.py

class CouponForm(forms.Form):
code = forms.CharField(required=True,
                       label=_("code"),
                       widget=forms.TextInput
                       (attrs={'placeholder':_('Code'),
                               'class': 'text-center'}))

def __init__(self, *args, **kwargs):
    self.user = None
    self.types = None
    if 'user' in kwargs:
        self.user = kwargs['user']
        del kwargs['user']
    if 'types' in kwargs:
        self.types = kwargs['types']
        del kwargs['types']
    super(CouponForm, self).__init__(*args, **kwargs)

def clean_code(self):
    code = self.cleaned_data['code']
    try:
        coupon = Coupon.objects.get(code=code)
    except Coupon.DoesNotExist:
        raise forms.ValidationError(_("This code is not valid."))
    self.coupon = coupon

    if self.user is None and coupon.user_limit is not 1:
        # coupons with can be used only once can be used without tracking the user, otherwise there is no chance
        # of excluding an unknown user from multiple usages.
        raise forms.ValidationError(_(
            "The server must provide an user to this form to allow you to use this code. Maybe you need to sign in?"
        ))

    if coupon.is_redeemed:
        raise forms.ValidationError(_("This code has already been used."))

    try:  # check if there is a user bound coupon existing
        user_coupon = coupon.users.get(user=self.user)
        if user_coupon.redeemed_at is not None:
            raise forms.ValidationError(_("This code has already been used by your account."))
    except CouponUser.DoesNotExist:
        if coupon.user_limit is not 0:  # zero means no limit of user count
            # only user bound coupons left and you don't have one
            if coupon.user_limit is coupon.users.filter(user__isnull=False).count():
                raise forms.ValidationError(_("This code is not valid for your account."))
            if coupon.user_limit is coupon.users.filter(redeemed_at__isnull=False).count():  # all coupons redeemed
                raise forms.ValidationError(_("This code has already been used."))
    if self.types is not None and coupon.type not in self.types:
        raise forms.ValidationError(_("This code is not meant to be used here."))
    if coupon.expired():
        raise forms.ValidationError(_("This code is expired."))
    return code

模型.py

@python_2_unicode_compatible
class Coupon(models.Model):
    value = models.IntegerField(_("Value"), help_text=_("Arbitrary coupon value"))
    code = models.CharField(
        _("Code"), max_length=30, unique=True, blank=True,
        help_text=_("Leaving this field empty will generate a random code."))
    type = models.CharField(_("Type"), max_length=20, choices=COUPON_TYPES)
    user_limit = models.PositiveIntegerField(_("User limit"), default=1)
    created_at = models.DateTimeField(_("Created at"), auto_now_add=True)
    valid_until = models.DateTimeField(
        _("Valid until"), blank=True, null=True,
        help_text=_("Leave empty for coupons that never expire"))
    campaign = models.ForeignKey('Campaign', verbose_name=_("Campaign"), blank=True, null=True, related_name='coupons')

    objects = CouponManager()

    class Meta:
        ordering = ['created_at']
        verbose_name = _("Coupon")
        verbose_name_plural = _("Coupons")

    def __str__(self):
        return self.code

    def save(self, *args, **kwargs):
        if not self.code:
            self.code = Coupon.generate_code()
        super(Coupon, self).save(*args, **kwargs)

    def redeem(self, user=None):
        try:
            coupon_user = self.users.get(user=user)
        except CouponUser.DoesNotExist:
            try:  # silently fix unbouned or nulled coupon users
                coupon_user = self.users.get(user__isnull=True)
                coupon_user.user = user
            except CouponUser.DoesNotExist:
                coupon_user = CouponUser(coupon=self, user=user)
        coupon_user.redeemed_at = timezone.now()
        coupon_user.save()
        redeem_done.send(sender=self.__class__, coupon=self)

更新 - Coupon.redeem 错误(请参阅代码 View ):

'QueryDict' object has no attribute 'users'

in models.py | coupon_user = self.users.get(user=user) 

最佳答案

您创建CouponForm实例的方式无效。你正在做

redeem = CouponForm({'code': Coupon.code}, user=user)

在此,您将 code 的初始数据作为 Coupon.code 传递,这是不正确的。您应该为 code 传递有效值,即。一些文字。但在这里,您传递的是带有 Coupon 模型属性的 Coupon.code,而不是预期值。

<小时/>

由于您的表单具有 code 字段,因此您可以传递 request.POST 以使用提交的值实例化表单。

redeem = CouponForm(request.POST, user=user)

此外,您多次实例化表单(例如,在 redeem.is_valid()ifelse 部分中),请勿我认为您不需要这个。

关于python - 表单返回 <django.db.models.query_utils.DeferredAttribute object at 0x10e6ee898>,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40478780/

相关文章:

python - 错误 HTTP 错误 403 : SSL is required when pip installing MySQL-python

python - django 一种形式多表

django - 获取 'DatabaseError' 对象在 DJango 中没有属性 'message'

mysql - Django 教程说我还没有设置 DATABASE_ENGINE 设置......但我有

python - Django CMS 3.1 和 Django 1.7.8 自定义用户模型

python - 字符串上的单次交换

python - 使用 MongoDB ( Python ) 将新属性插入文档

Python:将字符串转换为其二进制表示形式

python - 带选择器的 Flask html5 DateTimeField

django - 使用forloop.counter值作为Django模板中的列表索引