Ошибка типа: ‘<=' не поддерживается между экземплярами 'decimal.Decimal' и 'dict'

#python #django #django-views

#python #django #django-представления

Вопрос:

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

highest_bid = float(ставка.объекты.фильтр (id=bid_item.id ).агрегат (Max(‘bid_input’)))

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

ошибка

 Internal Server Error: /listing/2/bid
Traceback (most recent call last):
  File "C:PythonPython385libsite-packagesdjangocorehandlersexception.py", line 47, in inner
    response = get_response(request)
  File "C:PythonPython385libsite-packagesdjangocorehandlersbase.py", line 179, in _get_response
    response = wrapped_callback(request, *callback_args, **callback_kwargs)
  File "C:UserssarahDesktopcommerceauctionsviews.py", line 157, in placebid
    if bidform.cleaned_data['bid_input'] < listing.start_price and bidform.cleaned_data['bid_input'] <= highest_bid:
TypeError: '<=' not supported between instances of 'decimal.Decimal' and 'dict'
[08/Oct/2020 13:59:48] "POST /listing/2/bid HTTP/1.1" 500 62598
  

views.py

 def placebid(request, id):
    listing_bid = get_object_or_404(Listing, id=id)
    highest_bid = Bid.objects.filter(id=id).aggregate(Max('bid_input'))
    listing = Listing.objects.get(pk=id)
    if request.method == "POST":
        bidform = BidForm(request.POST)
        if bidform.is_valid():
            if bidform.cleaned_data['bid_input'] < listing.start_price and bidform.cleaned_data['bid_input'] <= highest_bid:
                return render(request, "auctions/listingPage.html", {
                    "listing": listing,
                    "error": "Make sure your bid is greater than the start price and current highest bid"
                    })
            else:
                listing_bid.bid_input = bidform.cleaned_data['bid_input']
                listing_bid.bidder = request.user
                listing_bid.bid_item = listing
                listing_bid.time = timezone.now()
                listing_bid.save()
                messages.success(request, 'Bid placed succesfully')
                return HttpResponseRedirect(reverse("listing", args=(id,)))
        else:
            return render(request, "auctions/listingPage.html", {
                "bidform": bidform })
    else:
        bidform = BidForm()
    return render(request, "auctions/listingPage.html", {
        "bidform": bidform })
  

Пожалуйста, дайте мне знать, если мне нужно включить какие-либо дополнительные подробности.

Отредактировано для добавления: models.py

 class Listing(models.Model):

    class NewManager(models.Manager):
        def get_queryset(self):
            return super().get_queryset().filter(status='active')

    options = (
        ('active', 'Active'),
        ('closed', 'Closed'),
    )

    title = models.CharField(max_length=64)
    description = models.TextField(max_length=64)
    start_price = models.DecimalField(max_digits=9, decimal_places=2, validators=[MinValueValidator(0.99)])
    image = models.URLField(max_length=200, blank=True)
    category = models.ForeignKey(Category, on_delete=models.CASCADE, related_name="listings")
    lister = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE, default=None, null=True, blank=True, related_name="lister_user")
    date_added = models.DateTimeField(default=timezone.now)
    status = models.CharField(max_length=10, choices=options, default="active")
    winner = models.ForeignKey('Bid', on_delete=models.CASCADE, null=True, related_name="bid_winner")
    favourites = models.ManyToManyField(User, related_name="favourite", default=None, blank=True)
    objects = models.Manager()
    listingmanager = NewManager()

    def __str__(self): 
        return f"{self.title} ({self.pk}, £{self.start_price}, {self.lister})"


class Bid(models.Model):
    bidder = models.ForeignKey(User, on_delete=models.CASCADE, related_name="bidders")
    bid_item = models.ForeignKey(Listing, on_delete=models.CASCADE, related_name="bid_items", default=None)
    bid_input = models.DecimalField(max_digits=9, decimal_places=2, default=None)
    time = models.DateTimeField(default=timezone.now)

    def __str__(self):
        return f"{self.bidder}, bid amount: {self.bid_input}"
  

Отредактировано для добавления: обновлено views.py

 def placebid(request, id):
    listing_bid = get_object_or_404(Listing, id=id)
    highest_bid = Bid.objects.filter(bid_item_id=id).aggregate(Max('bid_input'))['bid_input__max'] or Decimal('0')
    listing = Listing.objects.get(pk=id)
    if request.method == "POST":
        bidform = BidForm(request.POST)
        if bidform.is_valid():
            if bidform.cleaned_data['bid_input'] < listing.start_price and bidform.cleaned_data['bid_input'] <= highest_bid:
                return render(request, "auctions/listingPage.html", {
                    "listing": listing,
                    "error": "Make sure your bid is greater than the start price and current highest bid"
                })
            else:
                newbid = bidform.save(commit=False)
                newbid.bidder = request.user
                newbid.bid_input = bidform.cleaned_data['bid_input']
                newbid.bid_item = listing_bid
                newbid.time = timezone.now()
                newbid.save()
                messages.success(request, 'Bid placed succesfully')
            return HttpResponseRedirect(reverse("listing", args=(id,)))
        else:
            return render(request, "auctions/listingPage.html", {
                "bidform": bidform })
    else:
        bidform = BidForm()
    return render(request, "auctions/listingPage.html", {
        "bidform": bidform })
  

Ответ №1:

highest_bid это словарь, который сопоставляет имя агрегата со значением, так что, например { 'bid_input__max': Decimal('14.25') } , вы можете таким образом развернуть значение из словаря, подписавшись:

 highest_bid = Bid.objects.filter(
    id=id
).aggregate(Max('bid_input'))['bid_input__max']  

но, скорее всего, это не даст вам ожидаемого значения. Вы включаете фильтрацию id=id , так что это означает, что набор запросов охватывает одну запись. Вероятно, вы хотите отфильтровать bid_item_id=id или что-то подобное:

 highest_bid = Bid.objects.filter(
    bid_item_id=id
).aggregate(Max('bid_input'))['bid_input__max']  

основываясь на вашем комментарии, возможно, что ставки еще нет. В этом случае он вернет a None . Вместо этого мы можем использовать ноль с:

 highest_bid = Bid.objects.filter(
    bid_item_id=id
).aggregate(Max('bid_input'))['bid_input__max']  or Decimal('0')  

Комментарии:

1. Спасибо, поэтому я сначала попробовал ваше второе предложение, и ошибка появилась как: FieldError at /listing/2/bid Cannot resolve keyword 'listing_id' into field. Choices are: bid_input, bid_item, bid_item_id, bid_winner, bidder, bidder_id, id, time и когда я оставляю его как id = id, ошибка появляется как: '<=' not supported between instances of 'decimal.Decimal' and 'NoneType'

2. @sarchi-xo: как a Bid связано с a Listing ? Можете ли вы поделиться соответствующими моделями?

3. @sarchi-xo: тогда это так bid_item_id=id .

4. к сожалению, это возвращает ту же ошибку: '<=' not supported between instances of 'decimal.Decimal' and 'NoneType'

5. @sarchi-xo: но вы добавили ['bid_input__max'] в конце?