Django пользовательская проверка приводит к просмотру, возвращающему None - PullRequest
1 голос
/ 07 августа 2020

Я создаю приложение для аукционов, и мне нужно проверить, что сумма ставки, введенная в форму, равна или превышает начальную ставку (если было 0 ставок), или превышает текущую ставку.

Я использовал настраиваемую проверку с помощью clean ():

class Bid(models.Model):
        
    listing = models.ForeignKey(Listing, on_delete=models.CASCADE)
    amount = models.DecimalField(max_digits=11, decimal_places=2)

    def clean(self):
        # if there has been one or more bids
        if self.listing.current_bid and self.listing.current_bid.amount >= self.amount:
            raise ValidationError({'amount': _('Amount must be greater than current bid')})
        # else if there has been 0 bids
        elif self.listing.starting_bid > self.amount:
            raise ValidationError({'amount': _('Amount must be great than or equal to starting bid')})

In views.py:

def listing_page(request, listing_id):
    listing_selected = Listing.objects.get(pk=listing_id)
    if request.method == "POST":
        # Since I don't want the user to have to fill out a field specifying what listing page
        # they're on, and since I don't have access to that information in the model class
        # definition, I did that here:

        request.POST._mutable = True
        form = BidForm(request.POST)
        form.data['listing'] = listing_selected
        if form.is_valid():
            # ...process clean data...
            return HttpResponseRedirect(reverse('auctions:listing_page', args=(listing_id,)))

Теперь, когда я отправляю форму со значением, которое проверяется с помощью этой настраиваемой проверки я получаю «ValueError: представление auctions.views.listing_page не вернуло объект HttpResponse. Вместо этого оно вернуло None». Я проверил, что is_valid () оценивает значение False с помощью оператора печати. Если я отправлю недопустимое значение по умолчанию, например 10.1111 или abcd, я получаю правильное сообщение об ошибке. Разве это не должно происходить, когда is_valid () оценивается как False из-за моей пользовательской проверки? Что мне не хватает?

Редактировать: по запросу, полный вид (думаю, я изначально включил все соответствующие части, но кто знает):

def listing_page(request, listing_id):
    listing_selected = Listing.objects.get(pk=listing_id)
    bids = Bid.objects.filter(listing=listing_selected)
    if request.method == "POST":
        if request.POST.get('add_to_watchlist') and request.user.is_authenticated:
            request.user.person.watchlist.add(listing_selected) 
            return HttpResponseRedirect(reverse('auctions:listing_page', args=(listing_id,)))
        elif request.POST.get('remove_from_watchlist') and request.user.is_authenticated:
            request.user.person.watchlist.remove(listing_selected)
            return HttpResponseRedirect(reverse('auctions:listing_page', args=(listing_id,)))
        elif (request.POST.get('close_listing') and request.user.is_authenticated 
        and request.user == listing_selected.user):
            listing_selected.active = False
            listing_selected.save()
            return HttpResponseRedirect(reverse('auctions:listing_page', args=(listing_id,)))
        elif request.POST.get('make_comment') and request.user.is_authenticated:
            comment_form = CommentForm(request.POST)
            if comment_form.is_valid():
                comment = Comment()
                comment.user = request.user
                comment.listing = listing_selected
                comment.comment = comment_form.cleaned_data['comment']
                comment.save()
                return HttpResponseRedirect(reverse('auctions:listing_page', args=(listing_id,)))
        elif request.POST.get('make_bid') and request.user.is_authenticated:
            request.POST._mutable = True
            form = BidForm(request.POST)
            form.data['listing'] = listing_selected
            if form.is_valid():
                bid = Bid()
                bid.listing = listing_selected
                bid.user = request.user
                bid.amount = form.cleaned_data['amount']
                bid.save()
                listing_selected.current_bid = bid
                listing_selected.save()
                request.session['bid_success_message'] = "Bid placed successfully."
                return HttpResponseRedirect(reverse('auctions:listing_page', args=(listing_id,)))
    else:
        form = BidForm()
        comment_form = CommentForm()
        winning = False
        if request.user.is_authenticated:
            person = Person.objects.filter(user=request.user).filter(watchlist=listing_selected)
        else: 
            person = False    
        if listing_selected.current_bid and listing_selected.current_bid.user == request.user:
            winning = True
        comments = Comment.objects.filter(listing=listing_selected)
        category = None
        if listing_selected.category:
            for value, label in Listing.Category.choices:
                if value == listing_selected.category:
                    category = label
        context = {
                "listing": listing_selected,
                "person": person,
                "num_bids": len(bids),
                "winning": winning,
                "form": form,
                "comment_form": comment_form,
                "comments": comments,
                "category": category
            }
        if "bid_fail_message" in request.session:
            message = request.session['bid_fail_message']
            del request.session['bid_fail_message']
            messages.error(request, message)
        if "bid_success_message" in request.session:
            message = request.session['bid_success_message']
            del request.session['bid_success_message']
            messages.success(request, message)
        return render(request, "auctions/listing_page.html", context)

Также по запросу html:

<form class="bidform" action="{% url 'auctions:listing_page' listing.id %}" method="POST">
    {% csrf_token %}
    {{  form.amount  }}
    <input class="button bid_button" type="submit" value="Place Bid" name="make_bid">
</form>

Редактировать: Я запустил отладчик, и он переходит к этому методу dunder str перед тем, как выдать ошибку:

class Listing(models.Model):

    def __str__(self):
        return f"Listing '{self.title}' created by user '{self.user.username}' \
                 on {self.time_created.date()}"

Это происходит в обоих случаях, если я делаю «шаг в» и если я "перешагну" при вызове is_valid (). Зачем ему это?

...