Django:验证 ModelForm 的字段依赖于该模型的另一个字段

问题描述 投票:0回答:1

我有这两个 Django 模型:

class Listing(models.Model):
    ...
    price = models.DecimalField(
        decimal_places=2, 
        max_digits=20, 
        default=0, 
        validators=[MinValueValidator(Decimal('0.01'))]
    )

class Bid(models.Model):
    ...
    listing = models.ForeignKey(Listing, default=None, on_delete=models.CASCADE)
    amount = models.DecimalField(
        decimal_places=2,
        max_digits=20, 
        default=0
        validators=[MinValueValidator(Decimal(listing.price))]
    )

我想验证一下

Bid.amount > Bid.listing.price

当我尝试在

MinValueValidator
django.core.validators
的帮助下执行此操作时,我收到此错误:

    validators=[MinValueValidator(Decimal(listing.price))])
                                          ^^^^^^^^^^^^^
    AttributeError: 'ForeignKey' object has no attribute 'price'

我还尝试使用

listing.price
属性引用
self
并收到以下错误:

validators=[MinValueValidator(Decimal(self.listing.price))])
                                          ^^^^
NameError: name 'self' is not defined

我知道一旦提交了 Model.Form,我就可以在“views.py”中检查上述条件,但我想知道是否有一种方法可以使用 Django Validators 来验证它。

如有任何帮助,我们将不胜感激!

python html django-models django-forms foreign-keys
1个回答
0
投票

我通过在

forms.py
中创建自定义验证器来解决这个问题:

from .models import Listing, Bid
from django.forms import ModelForm
from decimal import Decimal
from django.core.exceptions import ValidationError


class BidForm(ModelForm):
    class Meta():
        model = Bid
        fields = ["amount"]

    def clean_amount(self):
        amount = self.cleaned_data["amount"]
        if Decimal(amount) < Decimal("0.01"):
            raise ValidationError(
                "Ensure this value is greater than or equal to 0.01."
            )
        elif Decimal(amount) <= Decimal(self.instance.listing.price):
            raise ValidationError("Ensure this value exceeds the price.")
        return amount

然后,在

views.py

from django.http import HttpResponseRedirect
from .models import Listing
from .forms import BidForm
from decimal import Decimal

def listing(request, listing_id):
    listing = Listing.objects.get(pk=listing_id)
    if request.method == "POST":
        form = BidForm(request.POST)
        form.instance.holder = request.user
        form.instance.listing = listing
        if form.is_valid():
            form.save()
            Listing.objects.filter(pk=listing_id).update(
                price=Decimal(request.POST["amount"])
            )
            return HttpResponseRedirect(
                f"/listing/{listing_id}", 
                {"form":form, "listing":listing}
            )
    else:
        form = BidForm()
    return render(request, "auctions/listing.html", {"form": form, "listing": listing})

我没有验证 Django Model 的字段,而是借助

clean_amount()
方法验证 ModelForm 提交。根据 Django 文档

此方法执行特定于该特定属性的任何清理,与它所属的字段类型无关。

我希望这个答案能帮助别人。

© www.soinside.com 2019 - 2024. All rights reserved.